rpcrt4/tests: Fix the marshalling test for Win64.
[wine] / dlls / rpcrt4 / tests / ndr_marshall.c
1 /*
2  * Unit test suite for ndr marshalling functions
3  *
4  * Copyright 2006 Huw Davies
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #define NTDDI_WIN2K   0x05000000
24 #define NTDDI_VERSION NTDDI_WIN2K /* for some MIDL_STUB_MESSAGE fields */
25
26 #include "wine/test.h"
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winnt.h>
30 #include <winerror.h>
31
32 #include "rpc.h"
33 #include "rpcdce.h"
34 #include "rpcproxy.h"
35
36
37 static int my_alloc_called;
38 static int my_free_called;
39 static void * CALLBACK my_alloc(SIZE_T size)
40 {
41     my_alloc_called++;
42     return NdrOleAllocate(size);
43 }
44
45 static void CALLBACK my_free(void *ptr)
46 {
47     my_free_called++;
48     NdrOleFree(ptr);
49 }
50
51 static const MIDL_STUB_DESC Object_StubDesc = 
52     {
53     NULL,
54     my_alloc,
55     my_free,
56     { 0 },
57     0,
58     0,
59     0,
60     0,
61     NULL, /* format string, filled in by tests */
62     1, /* -error bounds_check flag */
63     0x20000, /* Ndr library version */
64     0,
65     0x50100a4, /* MIDL Version 5.1.164 */
66     0,
67     NULL,
68     0,  /* notify & notify_flag routine table */
69     1,  /* Flags */
70     0,  /* Reserved3 */
71     0,  /* Reserved4 */
72     0   /* Reserved5 */
73     };
74
75 static RPC_DISPATCH_FUNCTION IFoo_table[] =
76 {
77     0
78 };
79
80 static RPC_DISPATCH_TABLE IFoo_v0_0_DispatchTable =
81 {
82     0,
83     IFoo_table
84 };
85
86 static const RPC_SERVER_INTERFACE IFoo___RpcServerInterface =
87 {
88     sizeof(RPC_SERVER_INTERFACE),
89     {{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x34}},{0,0}},
90     {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},
91     &IFoo_v0_0_DispatchTable,
92     0,
93     0,
94     0,
95     0,
96     0,
97 };
98
99 static RPC_IF_HANDLE IFoo_v0_0_s_ifspec = (RPC_IF_HANDLE)& IFoo___RpcServerInterface;
100 static BOOL use_pointer_ids = FALSE;
101
102 static void determine_pointer_marshalling_style(void)
103 {
104     RPC_MESSAGE RpcMessage;
105     MIDL_STUB_MESSAGE StubMsg;
106     MIDL_STUB_DESC StubDesc;
107     char ch = 0xde;
108
109     static const unsigned char fmtstr_up_char[] =
110     {
111         0x12, 0x8,      /* FC_UP [simple_pointer] */
112         0x2,            /* FC_CHAR */
113         0x5c,           /* FC_PAD */
114     };
115
116     StubDesc = Object_StubDesc;
117     StubDesc.pFormatTypes = NULL;
118
119     NdrClientInitializeNew(
120                            &RpcMessage,
121                            &StubMsg,
122                            &StubDesc,
123                            0);
124
125     StubMsg.BufferLength = 8;
126     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
127     NdrPointerMarshall(&StubMsg, (unsigned char*)&ch, fmtstr_up_char);
128     ok(StubMsg.Buffer == StubMsg.BufferStart + 5, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
129
130     use_pointer_ids = (*(unsigned int *)StubMsg.BufferStart != (UINT_PTR)&ch);
131     trace("Pointer marshalling using %s\n", use_pointer_ids ? "pointer ids" : "pointer value");
132
133     HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
134 }
135
136 static void test_ndr_simple_type(void)
137 {
138     RPC_MESSAGE RpcMessage;
139     MIDL_STUB_MESSAGE StubMsg;
140     MIDL_STUB_DESC StubDesc;
141     LONG l, l2 = 0;
142
143     StubDesc = Object_StubDesc;
144     StubDesc.pFormatTypes = NULL;
145
146     NdrClientInitializeNew(
147                            &RpcMessage,
148                            &StubMsg,
149                            &StubDesc,
150                            0);
151
152     StubMsg.BufferLength = 16;
153     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
154     l = 0xcafebabe;
155     NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */);
156     ok(StubMsg.Buffer == StubMsg.BufferStart + 4, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
157     ok(*(LONG*)StubMsg.BufferStart == l, "%d\n", *(LONG*)StubMsg.BufferStart);
158
159     StubMsg.Buffer = StubMsg.BufferStart + 1;
160     NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */);
161     ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
162     ok(*(LONG*)(StubMsg.BufferStart + 4) == l, "%d\n", *(LONG*)StubMsg.BufferStart);
163
164     StubMsg.Buffer = StubMsg.BufferStart + 1;
165     NdrSimpleTypeUnmarshall(&StubMsg, (unsigned char*)&l2, 8 /* FC_LONG */);
166     ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
167     ok(l2 == l, "%d\n", l2);
168
169     HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
170 }
171
172 static void test_pointer_marshal(const unsigned char *formattypes,
173                                  void *memsrc, DWORD srcsize,
174                                  const void *wiredata,
175                                  ULONG wiredatalen,
176                                  int(*cmp)(const void*,const void*,size_t),
177                                  int num_additional_allocs,
178                                  const char *msgpfx)
179 {
180     RPC_MESSAGE RpcMessage;
181     MIDL_STUB_MESSAGE StubMsg;
182     MIDL_STUB_DESC StubDesc;
183     DWORD size;
184     void *ptr;
185     unsigned char *mem, *mem_orig;
186
187     my_alloc_called = my_free_called = 0;
188     if(!cmp)
189         cmp = memcmp;
190
191     StubDesc = Object_StubDesc;
192     StubDesc.pFormatTypes = formattypes;
193
194     NdrClientInitializeNew(
195                            &RpcMessage,
196                            &StubMsg,
197                            &StubDesc,
198                            0);
199
200     StubMsg.BufferLength = 0;
201     NdrPointerBufferSize( &StubMsg,
202                           memsrc,
203                           formattypes );
204     ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength);
205
206     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
207     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
208     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
209
210     memset(StubMsg.BufferStart, 0x0, StubMsg.BufferLength); /* This is a hack to clear the padding between the ptr and longlong/double */
211
212     ptr = NdrPointerMarshall( &StubMsg,  memsrc, formattypes );
213     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
214     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
215     ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx);
216
217     StubMsg.Buffer = StubMsg.BufferStart;
218     StubMsg.MemorySize = 0;
219
220     size = NdrPointerMemorySize( &StubMsg, formattypes );
221     ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
222     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
223     if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
224         ok(size == srcsize + sizeof(void *), "%s: mem size %u\n", msgpfx, size);
225     else
226         ok(size == srcsize, "%s: mem size %u\n", msgpfx, size);
227
228     StubMsg.Buffer = StubMsg.BufferStart;
229     StubMsg.MemorySize = 16;
230     size = NdrPointerMemorySize( &StubMsg, formattypes );
231     ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
232     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
233     if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
234         ok(size == srcsize + sizeof(void *) + 16, "%s: mem size %u\n", msgpfx, size);
235     else
236         ok(size == srcsize + 16, "%s: mem size %u\n", msgpfx, size);
237
238     StubMsg.Buffer = StubMsg.BufferStart;
239     StubMsg.MemorySize = 1;
240     size = NdrPointerMemorySize( &StubMsg, formattypes );
241     ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
242     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
243     if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
244         ok(size == srcsize + sizeof(void *) + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size);
245     else
246         ok(size == srcsize + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size);
247
248     size = srcsize;
249     if(formattypes[1] & 0x10) size += 4;
250
251     StubMsg.Buffer = StubMsg.BufferStart;
252     StubMsg.MemorySize = 0;
253     mem_orig = mem = HeapAlloc(GetProcessHeap(), 0, size); 
254
255     if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
256         *(void**)mem = NULL;
257     ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
258     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
259     ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
260     ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
261     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
262     ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
263     ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 
264     my_alloc_called = 0;
265
266     /* reset the buffer and call with must alloc */
267     StubMsg.Buffer = StubMsg.BufferStart;
268     if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
269         *(void**)mem = NULL;
270     ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 );
271     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
272     /* doesn't allocate mem in this case */
273 todo_wine {
274     ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
275  }
276     ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
277     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
278     ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
279
280 todo_wine {
281     ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 
282 }
283     my_alloc_called = 0;
284     if(formattypes[0] != 0x11 /* FC_RP */)
285     {
286         /* now pass the address of a NULL ptr */
287         mem = NULL;
288         StubMsg.Buffer = StubMsg.BufferStart;
289         ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
290         ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
291         ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
292         ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
293         ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
294         ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
295         ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 
296         my_alloc_called = 0;
297         NdrPointerFree(&StubMsg, mem, formattypes);
298  
299         /* again pass address of NULL ptr, but pretend we're a server */
300         if (0)  /* crashes on Win9x and NT4 */
301         {
302             mem = NULL;
303             StubMsg.Buffer = StubMsg.BufferStart;
304             StubMsg.IsClient = 0;
305             ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
306             ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
307             if (formattypes[2] == 0xd /* FC_ENUM16 */)
308                 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
309             else
310                 ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
311             ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
312             ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
313             ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
314             if (formattypes[2] != 0xd /* FC_ENUM16 */) {
315                 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
316                 my_alloc_called = 0;
317             }
318         }
319     }
320     HeapFree(GetProcessHeap(), 0, mem_orig);
321     HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
322 }
323
324 static int deref_cmp(const void *s1, const void *s2, size_t num)
325 {
326     return memcmp(*(const void *const *)s1, *(const void *const *)s2, num);
327 }
328
329
330 static void test_simple_types(void)
331 {
332     unsigned char wiredata[16];
333     unsigned char ch;
334     unsigned char *ch_ptr;
335     unsigned short s;
336     unsigned int i;
337     ULONG l;
338     ULONGLONG ll;
339     float f;
340     double d;
341
342     static const unsigned char fmtstr_up_char[] =
343     {
344         0x12, 0x8,      /* FC_UP [simple_pointer] */
345         0x2,            /* FC_CHAR */
346         0x5c,           /* FC_PAD */
347     };
348     static const unsigned char fmtstr_up_byte[] =
349     {
350         0x12, 0x8,      /* FC_UP [simple_pointer] */
351         0x1,            /* FC_BYTE */
352         0x5c,           /* FC_PAD */
353     };
354     static const unsigned char fmtstr_up_small[] =
355     {
356         0x12, 0x8,      /* FC_UP [simple_pointer] */
357         0x3,            /* FC_SMALL */
358         0x5c,           /* FC_PAD */
359     };
360     static const unsigned char fmtstr_up_usmall[] =
361     {
362         0x12, 0x8,      /* FC_UP [simple_pointer] */
363         0x4,            /* FC_USMALL */
364         0x5c,           /* FC_PAD */
365     };  
366     static const unsigned char fmtstr_rp_char[] =
367     {
368         0x11, 0x8,      /* FC_RP [simple_pointer] */
369         0x2,            /* FC_CHAR */
370         0x5c,           /* FC_PAD */
371     };
372     static const unsigned char fmtstr_rpup_char[] =
373     {
374         0x11, 0x14,     /* FC_RP [alloced_on_stack] */
375         NdrFcShort( 0x2 ),      /* Offset= 2 (4) */
376         0x12, 0x8,      /* FC_UP [simple_pointer] */
377         0x2,            /* FC_CHAR */
378         0x5c,           /* FC_PAD */
379     };
380     static const unsigned char fmtstr_rpup_char2[] =
381     {
382         0x11, 0x04,     /* FC_RP [alloced_on_stack] */
383         NdrFcShort( 0x2 ),      /* Offset= 2 (4) */
384         0x12, 0x8,      /* FC_UP [simple_pointer] */
385         0x2,            /* FC_CHAR */
386         0x5c,           /* FC_PAD */
387     };
388
389     static const unsigned char fmtstr_up_wchar[] =
390     {
391         0x12, 0x8,      /* FC_UP [simple_pointer] */
392         0x5,            /* FC_WCHAR */
393         0x5c,           /* FC_PAD */
394     };
395     static const unsigned char fmtstr_up_short[] =
396     {
397         0x12, 0x8,      /* FC_UP [simple_pointer] */
398         0x6,            /* FC_SHORT */
399         0x5c,           /* FC_PAD */
400     };
401     static const unsigned char fmtstr_up_ushort[] =
402     {
403         0x12, 0x8,      /* FC_UP [simple_pointer] */
404         0x7,            /* FC_USHORT */
405         0x5c,           /* FC_PAD */
406     };
407     static const unsigned char fmtstr_up_enum16[] =
408     {
409         0x12, 0x8,      /* FC_UP [simple_pointer] */
410         0xd,            /* FC_ENUM16 */
411         0x5c,           /* FC_PAD */
412     };
413     static const unsigned char fmtstr_up_long[] =
414     {
415         0x12, 0x8,      /* FC_UP [simple_pointer] */
416         0x8,            /* FC_LONG */
417         0x5c,           /* FC_PAD */
418     };
419     static const unsigned char fmtstr_up_ulong[] =
420     {
421         0x12, 0x8,      /* FC_UP [simple_pointer] */
422         0x9,            /* FC_ULONG */
423         0x5c,           /* FC_PAD */
424     };
425     static const unsigned char fmtstr_up_enum32[] =
426     {
427         0x12, 0x8,      /* FC_UP [simple_pointer] */
428         0xe,            /* FC_ENUM32 */
429         0x5c,           /* FC_PAD */
430     };
431     static const unsigned char fmtstr_up_errorstatus[] =
432     {
433         0x12, 0x8,      /* FC_UP [simple_pointer] */
434         0x10,           /* FC_ERROR_STATUS_T */
435         0x5c,           /* FC_PAD */
436     };
437
438     static const unsigned char fmtstr_up_longlong[] =
439     {
440         0x12, 0x8,      /* FC_UP [simple_pointer] */
441         0xb,            /* FC_HYPER */
442         0x5c,           /* FC_PAD */
443     };
444     static const unsigned char fmtstr_up_float[] =
445     {
446         0x12, 0x8,      /* FC_UP [simple_pointer] */
447         0xa,            /* FC_FLOAT */
448         0x5c,           /* FC_PAD */
449     };
450     static const unsigned char fmtstr_up_double[] =
451     {
452         0x12, 0x8,      /* FC_UP [simple_pointer] */
453         0xc,            /* FC_DOUBLE */
454         0x5c,           /* FC_PAD */
455     };
456
457     ch = 0xa5;
458     ch_ptr = &ch;
459     if (use_pointer_ids)
460         *(unsigned int *)wiredata = 0x20000;
461     else
462         *(unsigned int *)wiredata = (UINT_PTR)ch_ptr;
463     wiredata[4] = ch;
464  
465     test_pointer_marshal(fmtstr_up_char, ch_ptr, 1, wiredata, 5, NULL, 0, "up_char");
466     test_pointer_marshal(fmtstr_up_byte, ch_ptr, 1, wiredata, 5, NULL, 0, "up_byte");
467     test_pointer_marshal(fmtstr_up_small, ch_ptr, 1, wiredata, 5, NULL, 0,  "up_small");
468     test_pointer_marshal(fmtstr_up_usmall, ch_ptr, 1, wiredata, 5, NULL, 0, "up_usmall");
469
470     test_pointer_marshal(fmtstr_rp_char, ch_ptr, 1, &ch, 1, NULL, 0, "rp_char");
471
472     test_pointer_marshal(fmtstr_rpup_char, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char");
473     test_pointer_marshal(fmtstr_rpup_char2, ch_ptr, 1, wiredata, 5, NULL, 0, "rpup_char2");
474
475     s = 0xa597;
476     if (use_pointer_ids)
477         *(unsigned int *)wiredata = 0x20000;
478     else
479         *(unsigned int *)wiredata = (UINT_PTR)&s;
480     *(unsigned short*)(wiredata + 4) = s;
481
482     test_pointer_marshal(fmtstr_up_wchar, &s, 2, wiredata, 6, NULL, 0, "up_wchar");
483     test_pointer_marshal(fmtstr_up_short, &s, 2, wiredata, 6, NULL, 0, "up_short");
484     test_pointer_marshal(fmtstr_up_ushort, &s, 2, wiredata, 6, NULL, 0, "up_ushort");
485
486     i = 0x7fff;
487     if (use_pointer_ids)
488         *(unsigned int *)wiredata = 0x20000;
489     else
490         *(unsigned int *)wiredata = (UINT_PTR)&i;
491     *(unsigned short*)(wiredata + 4) = i;
492     test_pointer_marshal(fmtstr_up_enum16, &i, 4, wiredata, 6, NULL, 0, "up_enum16");
493
494     l = 0xcafebabe;
495     if (use_pointer_ids)
496         *(unsigned int *)wiredata = 0x20000;
497     else
498         *(unsigned int *)wiredata = (UINT_PTR)&l;
499     *(ULONG*)(wiredata + 4) = l;
500
501     test_pointer_marshal(fmtstr_up_long, &l, 4, wiredata, 8, NULL, 0, "up_long");
502     test_pointer_marshal(fmtstr_up_ulong, &l, 4, wiredata, 8, NULL, 0,  "up_ulong");
503     test_pointer_marshal(fmtstr_up_enum32, &l, 4, wiredata, 8, NULL, 0,  "up_emun32");
504     test_pointer_marshal(fmtstr_up_errorstatus, &l, 4, wiredata, 8, NULL, 0,  "up_errorstatus");
505
506     ll = ((ULONGLONG)0xcafebabe) << 32 | 0xdeadbeef;
507     if (use_pointer_ids)
508         *(unsigned int *)wiredata = 0x20000;
509     else
510         *(unsigned int *)wiredata = (UINT_PTR)&ll;
511     *(unsigned int *)(wiredata + 4) = 0;
512     *(ULONGLONG*)(wiredata + 8) = ll;
513     test_pointer_marshal(fmtstr_up_longlong, &ll, 8, wiredata, 16, NULL, 0, "up_longlong");
514
515     f = 3.1415f;
516     if (use_pointer_ids)
517         *(unsigned int *)wiredata = 0x20000;
518     else
519         *(unsigned int *)wiredata = (UINT_PTR)&f;
520     *(float*)(wiredata + 4) = f;
521     test_pointer_marshal(fmtstr_up_float, &f, 4, wiredata, 8, NULL, 0, "up_float");
522
523     d = 3.1415;
524     if (use_pointer_ids)
525         *(unsigned int *)wiredata = 0x20000;
526     else
527         *(unsigned int *)wiredata = (UINT_PTR)&d;
528     *(unsigned int *)(wiredata + 4) = 0;
529     *(double*)(wiredata + 8) = d;
530     test_pointer_marshal(fmtstr_up_double, &d, 8, wiredata, 16, NULL, 0,  "up_double");
531
532 }
533
534 static void test_nontrivial_pointer_types(void)
535 {
536     RPC_MESSAGE RpcMessage;
537     MIDL_STUB_MESSAGE StubMsg;
538     MIDL_STUB_DESC StubDesc;
539     DWORD size;
540     void *ptr;
541     char **p1;
542     char *p2;
543     char ch;
544     unsigned char *mem, *mem_orig;
545
546     static const unsigned char fmtstr_ref_unique_out[] =
547     {
548         0x12, 0x8,      /* FC_UP [simple_pointer] */
549         0x2,            /* FC_CHAR */
550         0x5c,           /* FC_PAD */
551         0x11, 0x14,     /* FC_RP [alloced_on_stack] [pointer_deref] */
552         NdrFcShort( 0xfffffffa ),       /* Offset= -6 (0) */
553     };
554
555     p1 = &p2;
556     p2 = &ch;
557     ch = 0x22;
558
559     StubDesc = Object_StubDesc;
560     StubDesc.pFormatTypes = fmtstr_ref_unique_out;
561
562     NdrClientInitializeNew(
563                            &RpcMessage,
564                            &StubMsg,
565                            &StubDesc,
566                            0);
567
568     StubMsg.BufferLength = 0;
569     NdrPointerBufferSize( &StubMsg,
570                           (unsigned char *)p1,
571                           &fmtstr_ref_unique_out[4] );
572
573     /* Windows overestimates the buffer size */
574     ok(StubMsg.BufferLength >= 5, "length %d\n", StubMsg.BufferLength);
575
576     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
577     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
578     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
579
580     ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)p1, &fmtstr_ref_unique_out[4] );
581     ok(ptr == NULL, "ret %p\n", ptr);
582     size = StubMsg.Buffer - StubMsg.BufferStart;
583     ok(size == 5, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, size);
584     ok(*(unsigned int *)StubMsg.BufferStart != 0, "pointer ID marshalled incorrectly\n");
585     ok(*(unsigned char *)(StubMsg.BufferStart + 4) == 0x22, "char data marshalled incorrectly: 0x%x\n",
586        *(unsigned char *)(StubMsg.BufferStart + 4));
587
588     StubMsg.Buffer = StubMsg.BufferStart;
589     StubMsg.MemorySize = 0;
590     mem = NULL;
591
592     /* Client */
593     my_alloc_called = 0;
594     StubMsg.Buffer = StubMsg.BufferStart;
595     mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(void *));
596     *(void **)mem = NULL;
597     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
598     ok(mem == mem_orig, "mem alloced\n");
599     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
600
601     my_alloc_called = 0;
602     StubMsg.Buffer = StubMsg.BufferStart;
603     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
604     todo_wine {
605         ok(mem == mem_orig, "mem alloced\n");
606         ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
607     }
608
609     my_free_called = 0;
610     StubMsg.Buffer = StubMsg.BufferStart;
611     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
612     ok(my_free_called == 1, "free called %d\n", my_free_called);
613
614     mem = my_alloc(sizeof(void *));
615     *(void **)mem = NULL;
616     my_free_called = 0;
617     StubMsg.Buffer = StubMsg.BufferStart;
618     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
619     ok(my_free_called == 0, "free called %d\n", my_free_called);
620     my_free(mem);
621
622     mem = my_alloc(sizeof(void *));
623     *(void **)mem = my_alloc(sizeof(char));
624     my_free_called = 0;
625     StubMsg.Buffer = StubMsg.BufferStart;
626     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
627     ok(my_free_called == 1, "free called %d\n", my_free_called);
628     my_free(mem);
629
630     /* Server */
631     my_alloc_called = 0;
632     StubMsg.IsClient = 0;
633     mem = NULL;
634     StubMsg.Buffer = StubMsg.BufferStart;
635     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
636     ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
637     todo_wine
638     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
639     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
640
641     my_alloc_called = 0;
642     mem = NULL;
643     StubMsg.Buffer = StubMsg.BufferStart;
644     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
645     ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
646     todo_wine
647     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
648     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
649
650     my_alloc_called = 0;
651     mem = mem_orig;
652     *(void **)mem = NULL;
653     StubMsg.Buffer = StubMsg.BufferStart;
654     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
655     todo_wine {
656         ok(mem == mem_orig, "mem alloced\n");
657         ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
658     }
659
660     my_alloc_called = 0;
661     mem = mem_orig;
662     *(void **)mem = NULL;
663     StubMsg.Buffer = StubMsg.BufferStart;
664     NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
665     todo_wine {
666         ok(mem == mem_orig, "mem alloced\n");
667         ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
668     }
669
670     mem = my_alloc(sizeof(void *));
671     *(void **)mem = NULL;
672     my_free_called = 0;
673     StubMsg.Buffer = StubMsg.BufferStart;
674     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
675     ok(my_free_called == 0, "free called %d\n", my_free_called);
676     my_free(mem);
677
678     mem = my_alloc(sizeof(void *));
679     *(void **)mem = my_alloc(sizeof(char));
680     my_free_called = 0;
681     StubMsg.Buffer = StubMsg.BufferStart;
682     NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
683     ok(my_free_called == 1, "free called %d\n", my_free_called);
684     my_free(mem);
685
686     HeapFree(GetProcessHeap(), 0, mem_orig);
687     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
688 }
689
690 static void test_simple_struct_marshal(const unsigned char *formattypes,
691                                        void *memsrc, DWORD srcsize,
692                                        const void *wiredata,
693                                        ULONG wiredatalen,
694                                        int(*cmp)(const void*,const void*,size_t),
695                                        int num_additional_allocs,
696                                        const char *msgpfx)
697 {
698     RPC_MESSAGE RpcMessage;
699     MIDL_STUB_MESSAGE StubMsg;
700     MIDL_STUB_DESC StubDesc;
701     DWORD size;
702     void *ptr;
703     unsigned char *mem, *mem_orig;
704
705     my_alloc_called = my_free_called = 0;
706     if(!cmp)
707         cmp = memcmp;
708
709     StubDesc = Object_StubDesc;
710     StubDesc.pFormatTypes = formattypes;
711
712     NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
713
714     StubMsg.BufferLength = 0;
715     NdrSimpleStructBufferSize( &StubMsg, memsrc, formattypes );
716     ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength);
717     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
718     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
719     ptr = NdrSimpleStructMarshall( &StubMsg,  memsrc, formattypes );
720     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
721     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
722     ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled %08x %08x %08x\n", msgpfx, *(DWORD*)StubMsg.BufferStart,*((DWORD*)StubMsg.BufferStart+1),*((DWORD*)StubMsg.BufferStart+2));
723
724     StubMsg.Buffer = StubMsg.BufferStart;
725     StubMsg.MemorySize = 0;
726     size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
727     ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
728     ok(size == srcsize, "%s: mem size %u\n", msgpfx, size);
729     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
730
731     StubMsg.Buffer = StubMsg.BufferStart;
732     size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
733     ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
734     ok(StubMsg.MemorySize == ((srcsize + 3) & ~3) + srcsize, "%s: mem size %u\n", msgpfx, size);
735     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
736     size = srcsize;
737     /*** Unmarshalling first with must_alloc false ***/
738
739     StubMsg.Buffer = StubMsg.BufferStart;
740     StubMsg.MemorySize = 0;
741     mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, srcsize);
742     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
743     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
744     ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
745     ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
746     ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
747     ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 
748     my_alloc_called = 0;
749     ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
750
751     /* If we're a server we still use the supplied memory */
752     StubMsg.Buffer = StubMsg.BufferStart;
753     StubMsg.IsClient = 0;
754     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
755     ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
756     ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
757     ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 
758     ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
759     my_alloc_called = 0;
760     ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
761
762     /* ...unless we pass a NULL ptr, then the buffer is used. 
763        Passing a NULL ptr while we're a client && !must_alloc
764        crashes on Windows, so we won't do that. */
765
766     if (0)  /* crashes on Win9x and NT4 */
767     {
768         mem = NULL;
769         StubMsg.IsClient = 0;
770         StubMsg.Buffer = StubMsg.BufferStart;
771         ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, FALSE );
772         ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
773         ok(mem == StubMsg.BufferStart, "%s: mem not equal buffer\n", msgpfx);
774         ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
775         ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
776         my_alloc_called = 0;
777         ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
778     }
779
780     /*** now must_alloc is true ***/
781
782     /* with must_alloc set we always allocate new memory whether or not we're
783        a server and also when passing NULL */
784     mem = mem_orig;
785     StubMsg.IsClient = 1;
786     StubMsg.Buffer = StubMsg.BufferStart;
787     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
788     ok(ptr == NULL, "ret %p\n", ptr);
789     ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
790     ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
791     ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
792     my_alloc_called = 0;
793     ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
794
795     mem = NULL;
796     StubMsg.Buffer = StubMsg.BufferStart;
797     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
798     ok(ptr == NULL, "ret %p\n", ptr);
799     ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
800     ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
801     ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
802     my_alloc_called = 0; 
803     ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
804
805     mem = mem_orig;
806     StubMsg.Buffer = StubMsg.BufferStart;
807     StubMsg.IsClient = 0;
808     StubMsg.ReuseBuffer = 1;
809     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
810     ok(ptr == NULL, "ret %p\n", ptr);
811     ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
812     ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
813     ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
814     ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
815     my_alloc_called = 0;
816     ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
817
818     mem = NULL;
819     StubMsg.Buffer = StubMsg.BufferStart;
820     StubMsg.IsClient = 0;
821     StubMsg.ReuseBuffer = 1;
822     ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
823     ok(ptr == NULL, "ret %p\n", ptr);
824     ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
825     ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); 
826     ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
827     my_alloc_called = 0;
828     ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
829
830     HeapFree(GetProcessHeap(), 0, mem_orig);
831     HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
832 }
833
834 typedef struct
835 {
836     LONG l1;
837     LONG *pl1;
838     char *pc1;
839 } ps1_t;
840
841 static int ps1_cmp(const void *s1, const void *s2, size_t num)
842 {
843     const ps1_t *p1, *p2;
844
845     p1 = s1;
846     p2 = s2;
847
848     if(p1->l1 != p2->l1)
849         return 1;
850
851     if(p1->pl1 && p2->pl1)
852     {
853         if(*p1->pl1 != *p2->pl1)
854             return 1;
855     }
856     else if(p1->pl1 || p1->pl1)
857         return 1;
858
859     if(p1->pc1 && p2->pc1)
860     {
861         if(*p1->pc1 != *p2->pc1)
862             return 1;
863     }
864     else if(p1->pc1 || p1->pc1)
865         return 1;
866
867     return 0;
868 }
869
870 static void test_simple_struct(void)
871 {
872     unsigned char wiredata[28];
873     ULONG wiredatalen;
874     LONG l;
875     char c;
876     ps1_t ps1;
877
878     static const unsigned char fmtstr_simple_struct[] =
879     {
880         0x12, 0x0,      /* FC_UP */
881         NdrFcShort( 0x2 ), /* Offset=2 */
882         0x15, 0x3,      /* FC_STRUCT [align 4] */
883         NdrFcShort( 0x18 ),      /* [size 24] */
884         0x6,            /* FC_SHORT */
885         0x2,            /* FC_CHAR */ 
886         0x38,           /* FC_ALIGNM4 */
887         0x8,            /* FC_LONG */
888         0x8,            /* FC_LONG */
889         0x39,           /* FC_ALIGNM8 */
890         0xb,            /* FC_HYPER */ 
891         0x5b,           /* FC_END */
892     };
893     struct {
894         short s;
895         char c;
896         LONG l1, l2;
897         LONGLONG ll;
898     } s1;
899
900     static const unsigned char fmtstr_pointer_struct[] =
901     { 
902         0x12, 0x0,      /* FC_UP */
903         NdrFcShort( 0x2 ), /* Offset=2 */
904 #ifdef _WIN64
905         0x1a,   /* FC_BOGUS_STRUCT */
906         0x3,    /* 3 */
907         NdrFcShort(0x18),       /* [size 24] */
908         NdrFcShort(0x0),
909         NdrFcShort(0x8),        /* Offset= 8 (266) */
910         0x08,   /* FC_LONG */
911         0x39,   /* FC_ALIGNM8 */
912         0x36,   /* FC_POINTER */
913         0x36,   /* FC_POINTER */
914         0x5c,           /* FC_PAD */
915         0x5b,           /* FC_END */
916         0x12, 0x8,      /* FC_UP [simple_pointer] */
917         0x08,   /* FC_LONG */
918         0x5c,   /* FC_PAD */
919         0x12, 0x8,      /* FC_UP [simple_pointer] */
920         0x02,   /* FC_CHAR */
921         0x5c,   /* FC_PAD */
922 #else
923         0x16, 0x3,      /* FC_PSTRUCT [align 4] */
924         NdrFcShort( 0xc ),      /* [size 12] */
925         0x4b,           /* FC_PP */
926         0x5c,           /* FC_PAD */
927         0x46,           /* FC_NO_REPEAT */
928         0x5c,           /* FC_PAD */
929         NdrFcShort( 0x4 ),      /* 4 */
930         NdrFcShort( 0x4 ),      /* 4 */
931         0x13, 0x8,      /* FC_OP [simple_pointer] */
932         0x8,            /* FC_LONG */
933         0x5c,           /* FC_PAD */
934         0x46,           /* FC_NO_REPEAT */
935         0x5c,           /* FC_PAD */
936         NdrFcShort( 0x8 ),      /* 8 */
937         NdrFcShort( 0x8 ),      /* 8 */
938         0x13, 0x8,      /* FC_OP [simple_pointer] */
939         0x2,            /* FC_CHAR */
940         0x5c,           /* FC_PAD */
941         0x5b,           /* FC_END */
942         0x8,            /* FC_LONG */
943         0x8,            /* FC_LONG */
944         0x8,            /* FC_LONG */
945         0x5c,           /* FC_PAD */
946         0x5b,           /* FC_END */
947 #endif
948     };
949
950     /* zero the entire structure, including the holes */
951     memset(&s1, 0, sizeof(s1));
952
953     /* FC_STRUCT */
954     s1.s = 0x1234;
955     s1.c = 0xa5;
956     s1.l1 = 0xdeadbeef;
957     s1.l2 = 0xcafebabe;
958     s1.ll = ((LONGLONG) 0xbadefeed << 32) | 0x2468ace0;
959
960     wiredatalen = 24;
961     memcpy(wiredata, &s1, wiredatalen); 
962     test_simple_struct_marshal(fmtstr_simple_struct + 4, &s1, 24, wiredata, 24, NULL, 0, "struct");
963
964     if (use_pointer_ids)
965         *(unsigned int *)wiredata = 0x20000;
966     else
967         *(unsigned int *)wiredata = (UINT_PTR)&s1;
968     memcpy(wiredata + 4, &s1, wiredatalen);
969     test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct");
970
971     if (sizeof(void *) == 8) return;  /* it cannot be represented as a simple struct on Win64 */
972
973     /* zero the entire structure, including the hole */
974     memset(&ps1, 0, sizeof(ps1));
975
976     /* FC_PSTRUCT */
977     ps1.l1 = 0xdeadbeef;
978     l = 0xcafebabe;
979     ps1.pl1 = &l;
980     c = 'a';
981     ps1.pc1 = &c;
982     *(unsigned int *)(wiredata + 4) = 0xdeadbeef;
983     if (use_pointer_ids)
984     {
985         *(unsigned int *)(wiredata + 8) = 0x20000;
986         *(unsigned int *)(wiredata + 12) = 0x20004;
987     }
988     else
989     {
990         *(unsigned int *)(wiredata + 8) = (UINT_PTR)&l;
991         *(unsigned int *)(wiredata + 12) = (UINT_PTR)&c;
992     }
993     memcpy(wiredata + 16, &l, 4);
994     memcpy(wiredata + 20, &c, 1);
995
996     test_simple_struct_marshal(fmtstr_pointer_struct + 4, &ps1, 17, wiredata + 4, 17, ps1_cmp, 2, "pointer_struct");
997     if (use_pointer_ids)
998     {
999         *(unsigned int *)wiredata = 0x20000;
1000         *(unsigned int *)(wiredata + 8) = 0x20004;
1001         *(unsigned int *)(wiredata + 12) = 0x20008;
1002     }
1003     else
1004         *(unsigned int *)wiredata = (UINT_PTR)&ps1;
1005     test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct");
1006 }
1007
1008 static void test_fullpointer_xlat(void)
1009 {
1010     PFULL_PTR_XLAT_TABLES pXlatTables;
1011     ULONG RefId;
1012     int ret;
1013     void *Pointer;
1014
1015     pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT);
1016
1017     /* "marshaling" phase */
1018
1019     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1020     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1021     ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId);
1022
1023     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
1024     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1025     ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId);
1026
1027     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
1028     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1029     ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId);
1030
1031     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
1032     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1033     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1034
1035     ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId);
1036     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1037     ok(RefId == 0, "RefId should be 0 instead of 0x%x\n", RefId);
1038
1039     /* "unmarshaling" phase */
1040
1041     ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
1042     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1043     ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer);
1044
1045     ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer);
1046     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1047     ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
1048
1049     NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe);
1050
1051     ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer);
1052     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1053     ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer);
1054
1055     NdrFullPointerXlatFree(pXlatTables);
1056
1057     pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER);
1058
1059     /* "unmarshaling" phase */
1060
1061     ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
1062     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1063     ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
1064
1065     NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe);
1066
1067     ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
1068     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1069     ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
1070
1071     ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
1072     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1073     ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
1074
1075     /* "marshaling" phase */
1076
1077     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1078     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1079     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1080
1081     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1082     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1083     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1084
1085     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
1086     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1087     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1088
1089     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
1090     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1091     ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId);
1092
1093     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
1094     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1095     ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1096
1097     /* "freeing" phase */
1098
1099     ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef);
1100     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1101
1102     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0x20, &RefId);
1103     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1104     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1105
1106     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1107     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1108     ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1109
1110     ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe);
1111     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1112
1113     ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef);
1114     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1115
1116     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0x20, &RefId);
1117     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1118     ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1119
1120     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId);
1121     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1122     ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1123
1124     ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId);
1125     ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1126     ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1127
1128     ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef);
1129     ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1130
1131     NdrFullPointerXlatFree(pXlatTables);
1132 }
1133
1134 /* verify stub data that is identical between client and server */
1135 static void test_common_stub_data( const char *prefix, const MIDL_STUB_MESSAGE *stubMsg )
1136 {
1137     void *unset_ptr;
1138
1139     memset(&unset_ptr, 0xcc, sizeof(unset_ptr));
1140
1141 #define TEST_ZERO(field, fmt) ok(stubMsg->field == 0, "%s: " #field " should have been set to zero instead of " fmt "\n", prefix, stubMsg->field)
1142 #define TEST_POINTER_UNSET(field) ok(stubMsg->field == unset_ptr, "%s: " #field " should have been unset instead of %p\n", prefix, stubMsg->field)
1143 #define TEST_ULONG_UNSET(field) ok(stubMsg->field == 0xcccccccc, "%s: " #field " should have been unset instead of 0x%x\n", prefix, stubMsg->field)
1144 #define TEST_ULONG_PTR_UNSET(field) ok(stubMsg->field == (ULONG_PTR)unset_ptr, "%s: " #field " should have been unset instead of 0x%lx\n", prefix, stubMsg->field)
1145
1146     TEST_POINTER_UNSET(BufferMark);
1147     TEST_ULONG_UNSET(MemorySize);
1148     TEST_POINTER_UNSET(Memory);
1149     TEST_ZERO(pAllocAllNodesContext, "%p");
1150     ok(stubMsg->pPointerQueueState == 0 ||
1151        broken(stubMsg->pPointerQueueState == unset_ptr), /* win2k */
1152        "%s: pPointerQueueState should have been unset instead of %p\n",
1153        prefix, stubMsg->pPointerQueueState);
1154     TEST_ZERO(IgnoreEmbeddedPointers, "%d");
1155     TEST_ZERO(PointerBufferMark, "%p");
1156     ok( stubMsg->uFlags == 0 ||
1157         broken(stubMsg->uFlags == 0xcc), /* win9x */
1158         "%s: uFlags should have been set to zero instead of 0x%x\n", prefix, stubMsg->uFlags );
1159     /* FIXME: UniquePtrCount */
1160     TEST_ULONG_PTR_UNSET(MaxCount);
1161     TEST_ULONG_UNSET(Offset);
1162     TEST_ULONG_UNSET(ActualCount);
1163     ok(stubMsg->pfnAllocate == my_alloc, "%s: pfnAllocate should have been %p instead of %p\n",
1164        prefix, my_alloc, stubMsg->pfnAllocate);
1165     ok(stubMsg->pfnFree == my_free, "%s: pfnFree should have been %p instead of %p\n",
1166        prefix, my_free, stubMsg->pfnFree);
1167     TEST_ZERO(StackTop, "%p");
1168     TEST_POINTER_UNSET(pPresentedType);
1169     TEST_POINTER_UNSET(pTransmitType);
1170     TEST_POINTER_UNSET(SavedHandle);
1171     ok(stubMsg->StubDesc == &Object_StubDesc, "%s: StubDesc should have been %p instead of %p\n",
1172        prefix, &Object_StubDesc, stubMsg->StubDesc);
1173     TEST_ZERO(FullPtrRefId, "%d");
1174     ok( stubMsg->PointerLength == 0 ||
1175         broken(stubMsg->PointerLength == 1), /* win9x, nt4 */
1176         "%s: pAsyncMsg should have been set to zero instead of %d\n", prefix, stubMsg->PointerLength );
1177     TEST_ZERO(fInDontFree, "%d");
1178     TEST_ZERO(fDontCallFreeInst, "%d");
1179     ok(stubMsg->fInOnlyParam == 0 ||
1180        stubMsg->fInOnlyParam == -1, /* Vista */
1181        "%s: fInOnlyParam should have been set to 0 or -1 instead of %d\n", prefix, stubMsg->fInOnlyParam);
1182     ok( stubMsg->fHasReturn == 0 ||
1183         broken(stubMsg->fHasReturn == -1), /* win9x, nt4 */
1184         "%s: fHasReturn should have been set to zero instead of %d\n", prefix, stubMsg->fHasReturn );
1185     TEST_ZERO(fHasExtensions, "%d");
1186     TEST_ZERO(fHasNewCorrDesc, "%d");
1187     ok(stubMsg->fIsIn == 0 ||
1188        broken(stubMsg->fIsIn == -1), /* win9x, nt4 */
1189        "%s: fIsIn should have been set to 0 instead of %d\n", prefix, stubMsg->fIsIn);
1190     ok(stubMsg->fIsOut == 0 ||
1191        stubMsg->fIsOut == -1, /* XP-SP3 */
1192        "%s: fIsOut should have been set to 0 or -1 instead of %d\n", prefix, stubMsg->fIsOut);
1193     TEST_ZERO(fIsOicf, "%d");
1194     ok(stubMsg->fBufferValid == 0,
1195        "%s: fBufferValid should have been set to 0 instead of %d\n", prefix, stubMsg->fBufferValid);
1196     ok(stubMsg->fHasMemoryValidateCallback == 0 ||
1197        stubMsg->fHasMemoryValidateCallback == -1, /* XP-SP3 */
1198        "%s: fHasMemoryValidateCallback should have been set to 0 or -1 instead of %d\n",
1199        prefix, stubMsg->fHasMemoryValidateCallback);
1200     ok(stubMsg->fInFree == 0 ||
1201        stubMsg->fInFree == -1, /* XP-SP3 */
1202        "%s: fInFree should have been set to 0 or -1 instead of %d\n", prefix, stubMsg->fInFree);
1203     TEST_ZERO(fNeedMCCP, "%d");
1204     ok(stubMsg->fUnused == 0 ||
1205        stubMsg->fUnused == -2, /* Vista */
1206        "%s: fUnused should have been set to 0 or -2 instead of %d\n", prefix, stubMsg->fUnused);
1207     ok(stubMsg->fUnused2 == 0xffffcccc, "%s: fUnused2 should have been 0xffffcccc instead of 0x%x\n",
1208        prefix, stubMsg->fUnused2);
1209     ok(stubMsg->dwDestContext == MSHCTX_DIFFERENTMACHINE,
1210        "%s: dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n",
1211        prefix, stubMsg->dwDestContext);
1212     TEST_ZERO(pvDestContext, "%p");
1213     TEST_POINTER_UNSET(SavedContextHandles);
1214     TEST_ULONG_UNSET(ParamNumber);
1215     TEST_ZERO(pRpcChannelBuffer, "%p");
1216     TEST_ZERO(pArrayInfo, "%p");
1217     TEST_POINTER_UNSET(SizePtrCountArray);
1218     TEST_POINTER_UNSET(SizePtrOffsetArray);
1219     TEST_POINTER_UNSET(SizePtrLengthArray);
1220     TEST_POINTER_UNSET(pArgQueue);
1221     TEST_ZERO(dwStubPhase, "%d");
1222     /* FIXME: where does this value come from? */
1223     trace("%s: LowStackMark is %p\n", prefix, stubMsg->LowStackMark);
1224     ok( stubMsg->pAsyncMsg == 0 || broken(stubMsg->pAsyncMsg == unset_ptr), /* win9x, nt4 */
1225         "%s: pAsyncMsg should have been set to zero instead of %p\n", prefix, stubMsg->pAsyncMsg );
1226     ok( stubMsg->pCorrInfo == 0 || broken(stubMsg->pCorrInfo == unset_ptr), /* win9x, nt4 */
1227         "%s: pCorrInfo should have been set to zero instead of %p\n", prefix, stubMsg->pCorrInfo );
1228     ok( stubMsg->pCorrMemory == 0 || broken(stubMsg->pCorrMemory == unset_ptr), /* win9x, nt4 */
1229         "%s: pCorrMemory should have been set to zero instead of %p\n", prefix, stubMsg->pCorrMemory );
1230     ok( stubMsg->pMemoryList == 0 || broken(stubMsg->pMemoryList == unset_ptr), /* win9x, nt4 */
1231         "%s: pMemoryList should have been set to zero instead of %p\n", prefix, stubMsg->pMemoryList );
1232     TEST_POINTER_UNSET(pCSInfo);
1233     TEST_POINTER_UNSET(ConformanceMark);
1234     TEST_POINTER_UNSET(VarianceMark);
1235     ok(stubMsg->Unused == (ULONG_PTR)unset_ptr, "%s: Unused should have be unset instead of 0x%lx\n",
1236        prefix, stubMsg->Unused);
1237     TEST_POINTER_UNSET(pContext);
1238     TEST_POINTER_UNSET(ContextHandleHash);
1239     TEST_POINTER_UNSET(pUserMarshalList);
1240     TEST_ULONG_PTR_UNSET(Reserved51_3);
1241     TEST_ULONG_PTR_UNSET(Reserved51_4);
1242     TEST_ULONG_PTR_UNSET(Reserved51_5);
1243
1244 #undef TEST_ULONG_PTR_UNSET
1245 #undef TEST_ULONG_UNSET
1246 #undef TEST_POINTER_UNSET
1247 #undef TEST_ZERO
1248 }
1249
1250 static void test_client_init(void)
1251 {
1252     MIDL_STUB_MESSAGE stubMsg;
1253     RPC_MESSAGE rpcMsg;
1254     void *unset_ptr;
1255
1256     memset(&rpcMsg, 0xcc, sizeof(rpcMsg));
1257     memset(&stubMsg, 0xcc, sizeof(stubMsg));
1258     memset(&unset_ptr, 0xcc, sizeof(unset_ptr));
1259
1260     NdrClientInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc, 1);
1261
1262     test_common_stub_data( "NdrClientInitializeNew", &stubMsg );
1263
1264     ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg);
1265     ok(rpcMsg.Handle == NULL, "rpcMsg.Handle should have been NULL instead of %p\n", rpcMsg.Handle);
1266     ok(rpcMsg.Buffer == unset_ptr, "rpcMsg.Buffer should have been unset instead of %p\n",
1267        rpcMsg.Buffer);
1268     ok(rpcMsg.BufferLength == 0xcccccccc, "rpcMsg.BufferLength should have been unset instead of %d\n", rpcMsg.BufferLength);
1269     ok(rpcMsg.ProcNum == 0x8001, "rpcMsg.ProcNum should have been 0x8001 instead of 0x%x\n", rpcMsg.ProcNum);
1270     ok(rpcMsg.TransferSyntax == unset_ptr, "rpcMsg.TransferSyntax should have been unset instead of %p\n", rpcMsg.TransferSyntax);
1271     ok(rpcMsg.RpcInterfaceInformation == Object_StubDesc.RpcInterfaceInformation,
1272         "rpcMsg.RpcInterfaceInformation should have been %p instead of %p\n",
1273         Object_StubDesc.RpcInterfaceInformation, rpcMsg.RpcInterfaceInformation);
1274     /* Note: ReservedForRuntime not tested */
1275     ok(rpcMsg.ManagerEpv == unset_ptr, "rpcMsg.ManagerEpv should have been unset instead of %p\n", rpcMsg.ManagerEpv);
1276     ok(rpcMsg.ImportContext == unset_ptr, "rpcMsg.ImportContext should have been unset instead of %p\n", rpcMsg.ImportContext);
1277     ok(rpcMsg.RpcFlags == 0, "rpcMsg.RpcFlags should have been 0 instead of 0x%x\n", rpcMsg.RpcFlags);
1278
1279     ok(stubMsg.Buffer == unset_ptr, "stubMsg.Buffer should have been unset instead of %p\n",
1280        stubMsg.Buffer);
1281     ok(stubMsg.BufferStart == NULL, "stubMsg.BufferStart should have been NULL instead of %p\n",
1282        stubMsg.BufferStart);
1283     ok(stubMsg.BufferEnd == NULL, "stubMsg.BufferEnd should have been NULL instead of %p\n",
1284        stubMsg.BufferEnd);
1285     ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n",
1286        stubMsg.BufferLength);
1287     ok(stubMsg.IsClient == 1, "stubMsg.IsClient should have been 1 instead of %u\n", stubMsg.IsClient);
1288     ok(stubMsg.ReuseBuffer == 0, "stubMsg.ReuseBuffer should have been 0 instead of %d\n",
1289        stubMsg.ReuseBuffer);
1290     ok(stubMsg.CorrDespIncrement == 0, "stubMsg.CorrDespIncrement should have been 0 instead of %d\n",
1291        stubMsg.CorrDespIncrement);
1292     ok(stubMsg.FullPtrXlatTables == unset_ptr, "stubMsg.FullPtrXlatTables should have been unset instead of %p\n",
1293        stubMsg.FullPtrXlatTables);
1294 }
1295
1296 static void test_server_init(void)
1297 {
1298     MIDL_STUB_MESSAGE stubMsg;
1299     RPC_MESSAGE rpcMsg;
1300     unsigned char *ret;
1301     unsigned char buffer[256];
1302
1303     memset(&rpcMsg, 0, sizeof(rpcMsg));
1304     rpcMsg.Buffer = buffer;
1305     rpcMsg.BufferLength = sizeof(buffer);
1306     rpcMsg.RpcFlags = RPC_BUFFER_COMPLETE;
1307
1308     memset(&stubMsg, 0xcc, sizeof(stubMsg));
1309
1310     ret = NdrServerInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc);
1311     ok(ret == NULL, "NdrServerInitializeNew should have returned NULL instead of %p\n", ret);
1312
1313     test_common_stub_data( "NdrServerInitializeNew", &stubMsg );
1314
1315     ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg);
1316     ok(stubMsg.Buffer == buffer, "stubMsg.Buffer should have been %p instead of %p\n", buffer, stubMsg.Buffer);
1317     ok(stubMsg.BufferStart == buffer, "stubMsg.BufferStart should have been %p instead of %p\n", buffer, stubMsg.BufferStart);
1318     ok(stubMsg.BufferEnd == buffer + sizeof(buffer), "stubMsg.BufferEnd should have been %p instead of %p\n", buffer + sizeof(buffer), stubMsg.BufferEnd);
1319 todo_wine
1320     ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n", stubMsg.BufferLength);
1321     ok(stubMsg.IsClient == 0, "stubMsg.IsClient should have been 0 instead of %u\n", stubMsg.IsClient);
1322     ok(stubMsg.ReuseBuffer == 0 ||
1323        broken(stubMsg.ReuseBuffer == 1), /* win2k */
1324        "stubMsg.ReuseBuffer should have been set to zero instead of %d\n", stubMsg.ReuseBuffer);
1325     ok(stubMsg.CorrDespIncrement == 0xcc ||
1326        stubMsg.CorrDespIncrement == 0,
1327        "CorrDespIncrement should have been unset instead of 0x%x\n", stubMsg.CorrDespIncrement);
1328     ok(stubMsg.FullPtrXlatTables == 0, "stubMsg.BufferLength should have been 0 instead of %p\n", stubMsg.FullPtrXlatTables);
1329 }
1330
1331 static void test_ndr_allocate(void)
1332 {
1333     RPC_MESSAGE RpcMessage;
1334     MIDL_STUB_MESSAGE StubMsg;
1335     MIDL_STUB_DESC StubDesc;
1336     void *p1, *p2;
1337     struct tag_mem_list_v2_t
1338     {
1339         DWORD magic;
1340         DWORD size;
1341         DWORD unknown;
1342         struct tag_mem_list_v2_t *next;
1343     } *mem_list_v2;
1344     const DWORD magic_MEML = 'M' << 24 | 'E' << 16 | 'M' << 8 | 'L';
1345
1346     StubDesc = Object_StubDesc;
1347     NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
1348
1349     my_alloc_called = my_free_called = 0;
1350     p1 = NdrAllocate(&StubMsg, 10);
1351     p2 = NdrAllocate(&StubMsg, 24);
1352     ok(my_alloc_called == 2, "alloc called %d\n", my_alloc_called);
1353     ok(StubMsg.pMemoryList != NULL, "StubMsg.pMemoryList NULL\n");
1354     if(StubMsg.pMemoryList)
1355     {
1356         mem_list_v2 = StubMsg.pMemoryList;
1357         if (mem_list_v2->size == 24)
1358         {
1359             trace("v2 mem list format\n");
1360             ok((char *)mem_list_v2 == (char *)p2 + 24, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p2 + 24, mem_list_v2);
1361             ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic);
1362             ok(mem_list_v2->size == 24, "wrong size for p2 %d\n", mem_list_v2->size);
1363             ok(mem_list_v2->unknown == 0, "wrong unknown for p2 0x%x\n", mem_list_v2->unknown);
1364             ok(mem_list_v2->next != NULL, "next NULL\n");
1365             mem_list_v2 = mem_list_v2->next;
1366             if(mem_list_v2)
1367             {
1368                 ok((char *)mem_list_v2 == (char *)p1 + 16, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p1 + 16, mem_list_v2);
1369                 ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic);
1370                 ok(mem_list_v2->size == 16, "wrong size for p1 %d\n", mem_list_v2->size);
1371                 ok(mem_list_v2->unknown == 0, "wrong unknown for p1 0x%x\n", mem_list_v2->unknown);
1372                 ok(mem_list_v2->next == NULL, "next %p\n", mem_list_v2->next);
1373             }
1374         }
1375         else win_skip("v1 mem list format\n");
1376     }
1377     /* NdrFree isn't exported so we can't test free'ing */
1378 }
1379
1380 static void test_conformant_array(void)
1381 {
1382     RPC_MESSAGE RpcMessage;
1383     MIDL_STUB_MESSAGE StubMsg;
1384     MIDL_STUB_DESC StubDesc;
1385     void *ptr;
1386     unsigned char *mem, *mem_orig;
1387     unsigned char memsrc[20];
1388     unsigned int i;
1389
1390     static const unsigned char fmtstr_conf_array[] =
1391     {
1392         0x1b,              /* FC_CARRAY */
1393         0x0,               /* align */
1394         NdrFcShort( 0x1 ), /* elem size */
1395         0x40,              /* Corr desc:  const */
1396         0x0,
1397         NdrFcShort(0x10),  /* const = 0x10 */
1398         0x1,               /* FC_BYTE */
1399         0x5b               /* FC_END */
1400     };
1401
1402     for (i = 0; i < sizeof(memsrc); i++)
1403         memsrc[i] = i * i;
1404
1405     StubDesc = Object_StubDesc;
1406     StubDesc.pFormatTypes = fmtstr_conf_array;
1407
1408     NdrClientInitializeNew(
1409                            &RpcMessage,
1410                            &StubMsg,
1411                            &StubDesc,
1412                            0);
1413
1414     StubMsg.BufferLength = 0;
1415     NdrConformantArrayBufferSize( &StubMsg,
1416                           memsrc,
1417                           fmtstr_conf_array );
1418     ok(StubMsg.BufferLength >= 20, "length %d\n", StubMsg.BufferLength);
1419
1420     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1421     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1422     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1423
1424     ptr = NdrConformantArrayMarshall( &StubMsg,  memsrc, fmtstr_conf_array );
1425     ok(ptr == NULL, "ret %p\n", ptr);
1426     ok(StubMsg.Buffer - StubMsg.BufferStart == 20, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, 20);
1427     ok(!memcmp(StubMsg.BufferStart + 4, memsrc, 16), "incorrectly marshaled\n");
1428
1429     StubMsg.Buffer = StubMsg.BufferStart;
1430     StubMsg.MemorySize = 0;
1431     mem = NULL;
1432
1433     /* Client */
1434     my_alloc_called = 0;
1435     /* passing mem == NULL with must_alloc == 0 crashes under Windows */
1436     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1437     ok(mem != NULL, "mem not alloced\n");
1438     ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1439     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1440
1441     my_alloc_called = 0;
1442     StubMsg.Buffer = StubMsg.BufferStart;
1443     mem_orig = mem;
1444     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1445     ok(mem == mem_orig, "mem alloced\n");
1446     ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1447     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1448
1449     my_alloc_called = 0;
1450     StubMsg.Buffer = StubMsg.BufferStart;
1451     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1452     ok(mem != mem_orig, "mem not alloced\n");
1453     ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1454     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1455
1456     my_free_called = 0;
1457     StubMsg.Buffer = StubMsg.BufferStart;
1458     NdrConformantArrayFree( &StubMsg, mem, fmtstr_conf_array );
1459     ok(my_free_called == 0, "free called %d\n", my_free_called);
1460     StubMsg.pfnFree(mem);
1461
1462     /* Server */
1463     my_alloc_called = 0;
1464     StubMsg.IsClient = 0;
1465     mem = NULL;
1466     StubMsg.Buffer = StubMsg.BufferStart;
1467     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1468     ok(mem == StubMsg.BufferStart + 4 || broken(!mem),  /* win9x, nt4 */
1469        "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 4);
1470     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1471     my_alloc_called = 0;
1472     mem = NULL;
1473     StubMsg.Buffer = StubMsg.BufferStart;
1474     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1475     ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1476     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1477     StubMsg.pfnFree(mem);
1478
1479     my_alloc_called = 0;
1480     mem = mem_orig;
1481     StubMsg.Buffer = StubMsg.BufferStart;
1482     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1483     ok(mem == mem_orig, "mem alloced\n");
1484     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1485
1486     my_alloc_called = 0;
1487     mem = mem_orig;
1488     StubMsg.Buffer = StubMsg.BufferStart;
1489     NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1490     ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1491     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1492     StubMsg.pfnFree(mem);
1493     StubMsg.pfnFree(mem_orig);
1494
1495     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1496 }
1497
1498 static void test_conformant_string(void)
1499 {
1500     RPC_MESSAGE RpcMessage;
1501     MIDL_STUB_MESSAGE StubMsg;
1502     MIDL_STUB_DESC StubDesc;
1503     DWORD size;
1504     void *ptr;
1505     unsigned char *mem, *mem_orig;
1506     char memsrc[] = "This is a test string";
1507
1508     static const unsigned char fmtstr_conf_str[] =
1509     {
1510                         0x11, 0x8,      /* FC_RP [simple_pointer] */
1511                         0x22,           /* FC_C_CSTRING */
1512                         0x5c,           /* FC_PAD */
1513     };
1514
1515     StubDesc = Object_StubDesc;
1516     StubDesc.pFormatTypes = fmtstr_conf_str;
1517
1518     memset( &StubMsg, 0, sizeof(StubMsg) );  /* needed on win9x and nt4 */
1519     NdrClientInitializeNew(
1520                            &RpcMessage,
1521                            &StubMsg,
1522                            &StubDesc,
1523                            0);
1524
1525     StubMsg.BufferLength = 0;
1526     NdrPointerBufferSize( &StubMsg,
1527                           (unsigned char *)memsrc,
1528                           fmtstr_conf_str );
1529     ok(StubMsg.BufferLength >= sizeof(memsrc) + 12, "length %d\n", StubMsg.BufferLength);
1530
1531     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1532     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1533     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1534
1535     ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)memsrc, fmtstr_conf_str );
1536     ok(ptr == NULL, "ret %p\n", ptr);
1537     size = StubMsg.Buffer - StubMsg.BufferStart;
1538     ok(size == sizeof(memsrc) + 12, "Buffer %p Start %p len %d\n",
1539        StubMsg.Buffer, StubMsg.BufferStart, size);
1540     ok(!memcmp(StubMsg.BufferStart + 12, memsrc, sizeof(memsrc)), "incorrectly marshaled\n");
1541
1542     StubMsg.Buffer = StubMsg.BufferStart;
1543     StubMsg.MemorySize = 0;
1544     mem = NULL;
1545
1546     /* Client */
1547     my_alloc_called = 0;
1548     StubMsg.Buffer = StubMsg.BufferStart;
1549     mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1550     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1551     ok(mem == mem_orig, "mem not alloced\n");
1552     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1553
1554     my_alloc_called = 0;
1555     StubMsg.Buffer = StubMsg.BufferStart;
1556     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1557 todo_wine {
1558     ok(mem == mem_orig, "mem not alloced\n");
1559     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1560 }
1561
1562     my_free_called = 0;
1563     StubMsg.Buffer = StubMsg.BufferStart;
1564     NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1565     ok(my_free_called == 1, "free called %d\n", my_free_called);
1566
1567     mem = my_alloc(10);
1568     my_free_called = 0;
1569     StubMsg.Buffer = StubMsg.BufferStart;
1570     NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1571     ok(my_free_called == 1, "free called %d\n", my_free_called);
1572
1573     /* Server */
1574     my_alloc_called = 0;
1575     StubMsg.IsClient = 0;
1576     mem = NULL;
1577     StubMsg.Buffer = StubMsg.BufferStart;
1578     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1579     ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1580        "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1581     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1582
1583     my_alloc_called = 0;
1584     mem = NULL;
1585     StubMsg.Buffer = StubMsg.BufferStart;
1586     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1587 todo_wine {
1588     ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1589        "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1590     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1591 }
1592
1593     my_alloc_called = 0;
1594     mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1595     StubMsg.Buffer = StubMsg.BufferStart;
1596     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1597     ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1598        "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1599     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1600
1601     my_alloc_called = 0;
1602     mem = mem_orig;
1603     StubMsg.Buffer = StubMsg.BufferStart;
1604     NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1605 todo_wine {
1606     ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1607        "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1608     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1609 }
1610
1611     mem = my_alloc(10);
1612     my_free_called = 0;
1613     StubMsg.Buffer = StubMsg.BufferStart;
1614     NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1615     ok(my_free_called == 1, "free called %d\n", my_free_called);
1616
1617     HeapFree(GetProcessHeap(), 0, mem_orig);
1618     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1619 }
1620
1621 static void test_nonconformant_string(void)
1622 {
1623     RPC_MESSAGE RpcMessage;
1624     MIDL_STUB_MESSAGE StubMsg;
1625     MIDL_STUB_DESC StubDesc;
1626     DWORD size;
1627     void *ptr;
1628     unsigned char *mem, *mem_orig;
1629     unsigned char memsrc[10] = "This is";
1630     unsigned char memsrc2[10] = "This is a";
1631
1632     static const unsigned char fmtstr_nonconf_str[] =
1633     {
1634                         0x26,           /* FC_CSTRING */
1635                         0x5c,           /* FC_PAD */
1636                         NdrFcShort( 0xa ),      /* 10 */
1637     };
1638
1639     StubDesc = Object_StubDesc;
1640     StubDesc.pFormatTypes = fmtstr_nonconf_str;
1641
1642     /* length < size */
1643     NdrClientInitializeNew(
1644                            &RpcMessage,
1645                            &StubMsg,
1646                            &StubDesc,
1647                            0);
1648
1649     StubMsg.BufferLength = 0;
1650
1651     NdrNonConformantStringBufferSize( &StubMsg, memsrc, fmtstr_nonconf_str );
1652     ok(StubMsg.BufferLength >= strlen((char *)memsrc) + 1 + 8, "length %d\n", StubMsg.BufferLength);
1653
1654     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1655     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1656     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1657
1658     ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc, fmtstr_nonconf_str );
1659     ok(ptr == NULL, "ret %p\n", ptr);
1660     size = StubMsg.Buffer - StubMsg.BufferStart;
1661     ok(size == strlen((char *)memsrc) + 1 + 8, "Buffer %p Start %p len %d\n",
1662        StubMsg.Buffer, StubMsg.BufferStart, size);
1663     ok(!memcmp(StubMsg.BufferStart + 8, memsrc, strlen((char *)memsrc) + 1), "incorrectly marshaled\n");
1664
1665     StubMsg.Buffer = StubMsg.BufferStart;
1666     StubMsg.MemorySize = 0;
1667     mem = NULL;
1668
1669     /* Client */
1670     my_alloc_called = 0;
1671     StubMsg.Buffer = StubMsg.BufferStart;
1672     mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1673     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1674     ok(mem == mem_orig, "mem alloced\n");
1675     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1676
1677     my_alloc_called = 0;
1678     StubMsg.Buffer = StubMsg.BufferStart;
1679     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1680     todo_wine
1681     ok(mem == mem_orig, "mem alloced\n");
1682     todo_wine
1683     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1684
1685     /* Server */
1686     my_alloc_called = 0;
1687     StubMsg.IsClient = 0;
1688     mem = NULL;
1689     StubMsg.Buffer = StubMsg.BufferStart;
1690     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1691     ok(mem != mem_orig, "mem not alloced\n");
1692     ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n");
1693     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1694     NdrOleFree(mem);
1695
1696     my_alloc_called = 0;
1697     mem = mem_orig;
1698     StubMsg.Buffer = StubMsg.BufferStart;
1699     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1700     ok(mem == mem_orig, "mem alloced\n");
1701     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1702
1703     my_alloc_called = 0;
1704     mem = mem_orig;
1705     StubMsg.Buffer = StubMsg.BufferStart;
1706     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1707     todo_wine
1708     ok(mem == mem_orig, "mem alloced\n");
1709     todo_wine
1710     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1711
1712     HeapFree(GetProcessHeap(), 0, mem_orig);
1713     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1714
1715     /* length = size */
1716     NdrClientInitializeNew(
1717                            &RpcMessage,
1718                            &StubMsg,
1719                            &StubDesc,
1720                            0);
1721
1722     StubMsg.BufferLength = 0;
1723
1724     NdrNonConformantStringBufferSize( &StubMsg, memsrc2, fmtstr_nonconf_str );
1725     ok(StubMsg.BufferLength >= strlen((char *)memsrc2) + 1 + 8, "length %d\n", StubMsg.BufferLength);
1726
1727     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1728     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1729     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1730
1731     ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc2, fmtstr_nonconf_str );
1732     ok(ptr == NULL, "ret %p\n", ptr);
1733     size = StubMsg.Buffer - StubMsg.BufferStart;
1734     ok(size == strlen((char *)memsrc2) + 1 + 8, "Buffer %p Start %p len %d\n",
1735        StubMsg.Buffer, StubMsg.BufferStart, size);
1736     ok(!memcmp(StubMsg.BufferStart + 8, memsrc2, strlen((char *)memsrc2) + 1), "incorrectly marshaled\n");
1737
1738     StubMsg.Buffer = StubMsg.BufferStart;
1739     StubMsg.MemorySize = 0;
1740     mem = NULL;
1741
1742     /* Client */
1743     my_alloc_called = 0;
1744     StubMsg.Buffer = StubMsg.BufferStart;
1745     mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1746     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1747     ok(mem == mem_orig, "mem alloced\n");
1748     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1749
1750     my_alloc_called = 0;
1751     StubMsg.Buffer = StubMsg.BufferStart;
1752     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1753     todo_wine
1754     ok(mem == mem_orig, "mem alloced\n");
1755     todo_wine
1756     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1757
1758     /* Server */
1759     my_alloc_called = 0;
1760     StubMsg.IsClient = 0;
1761     mem = NULL;
1762     StubMsg.Buffer = StubMsg.BufferStart;
1763     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1764     ok(mem != mem_orig, "mem not alloced\n");
1765     ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n");
1766     ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1767     NdrOleFree(mem);
1768
1769     my_alloc_called = 0;
1770     mem = mem_orig;
1771     StubMsg.Buffer = StubMsg.BufferStart;
1772     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1773     ok(mem == mem_orig, "mem alloced\n");
1774     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1775
1776     my_alloc_called = 0;
1777     mem = mem_orig;
1778     StubMsg.Buffer = StubMsg.BufferStart;
1779     NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1780     todo_wine
1781     ok(mem == mem_orig, "mem alloced\n");
1782     todo_wine
1783     ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1784
1785     HeapFree(GetProcessHeap(), 0, mem_orig);
1786     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1787 }
1788
1789 static void test_conf_complex_struct(void)
1790 {
1791     RPC_MESSAGE RpcMessage;
1792     MIDL_STUB_MESSAGE StubMsg;
1793     MIDL_STUB_DESC StubDesc;
1794     void *ptr;
1795     unsigned int i;
1796     struct conf_complex
1797     {
1798       unsigned int size;
1799       unsigned int *array[1];
1800     };
1801     struct conf_complex *memsrc;
1802     struct conf_complex *mem;
1803
1804     static const unsigned char fmtstr_complex_struct[] =
1805     {
1806 /* 0 */
1807                         0x1b,           /* FC_CARRAY */
1808                         0x3,            /* 3 */
1809 /* 2 */ NdrFcShort( 0x4 ),      /* 4 */
1810 /* 4 */ 0x8,            /* Corr desc: FC_LONG */
1811                         0x0,            /*  */
1812 /* 6 */ NdrFcShort( 0xfffc ),   /* -4 */
1813 /* 8 */
1814                         0x4b,           /* FC_PP */
1815                         0x5c,           /* FC_PAD */
1816 /* 10 */
1817                         0x48,           /* FC_VARIABLE_REPEAT */
1818                         0x49,           /* FC_FIXED_OFFSET */
1819 /* 12 */        NdrFcShort( 0x4 ),      /* 4 */
1820 /* 14 */        NdrFcShort( 0x0 ),      /* 0 */
1821 /* 16 */        NdrFcShort( 0x1 ),      /* 1 */
1822 /* 18 */        NdrFcShort( 0x0 ),      /* 0 */
1823 /* 20 */        NdrFcShort( 0x0 ),      /* 0 */
1824 /* 22 */        0x12, 0x8,      /* FC_UP [simple_pointer] */
1825 /* 24 */        0x8,            /* FC_LONG */
1826                         0x5c,           /* FC_PAD */
1827 /* 26 */
1828                         0x5b,           /* FC_END */
1829
1830                         0x8,            /* FC_LONG */
1831 /* 28 */        0x5c,           /* FC_PAD */
1832                         0x5b,           /* FC_END */
1833 /* 30 */
1834                         0x1a,           /* FC_BOGUS_STRUCT */
1835                         0x3,            /* 3 */
1836 /* 32 */        NdrFcShort( 0x4 ),      /* 4 */
1837 /* 34 */        NdrFcShort( 0xffffffde ),       /* Offset= -34 (0) */
1838 /* 36 */        NdrFcShort( 0x0 ),      /* Offset= 0 (36) */
1839 /* 38 */        0x8,            /* FC_LONG */
1840                         0x5b,           /* FC_END */
1841     };
1842
1843     memsrc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1844                        FIELD_OFFSET(struct conf_complex, array[20]));
1845     memsrc->size = 20;
1846
1847     StubDesc = Object_StubDesc;
1848     StubDesc.pFormatTypes = fmtstr_complex_struct;
1849
1850     NdrClientInitializeNew(
1851                            &RpcMessage,
1852                            &StubMsg,
1853                            &StubDesc,
1854                            0);
1855
1856     StubMsg.BufferLength = 0;
1857     NdrComplexStructBufferSize( &StubMsg,
1858                                 (unsigned char *)memsrc,
1859                                 &fmtstr_complex_struct[30] );
1860     ok(StubMsg.BufferLength >= 28, "length %d\n", StubMsg.BufferLength);
1861
1862     /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1863     StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1864     StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1865
1866     ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)memsrc,
1867                                     &fmtstr_complex_struct[30] );
1868     ok(ptr == NULL, "ret %p\n", ptr);
1869     ok(*(unsigned int *)StubMsg.BufferStart == 20, "Conformance should have been 20 instead of %d\n", *(unsigned int *)StubMsg.BufferStart);
1870     ok(*(unsigned int *)(StubMsg.BufferStart + 4) == 20, "conf_complex.size should have been 20 instead of %d\n", *(unsigned int *)(StubMsg.BufferStart + 4));
1871     for (i = 0; i < 20; i++)
1872       ok(*(unsigned int *)(StubMsg.BufferStart + 8 + i * 4) == 0, "pointer id for conf_complex.array[%d] should have been 0 instead of 0x%x\n", i, *(unsigned int *)(StubMsg.BufferStart + 8 + i * 4));
1873
1874     /* Server */
1875     my_alloc_called = 0;
1876     StubMsg.IsClient = 0;
1877     mem = NULL;
1878     StubMsg.Buffer = StubMsg.BufferStart;
1879     ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_struct[30], 0);
1880     ok(ptr == NULL, "ret %p\n", ptr);
1881     ok(mem->size == 20, "mem->size wasn't unmarshalled correctly (%d)\n", mem->size);
1882     ok(mem->array[0] == NULL, "mem->array[0] wasn't unmarshalled correctly (%p)\n", mem->array[0]);
1883     StubMsg.pfnFree(mem);
1884
1885     HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1886 }
1887
1888 static void test_ndr_buffer(void)
1889 {
1890     static unsigned char ncalrpc[] = "ncalrpc";
1891     static unsigned char endpoint[] = "winetest:test_ndr_buffer";
1892     RPC_MESSAGE RpcMessage;
1893     MIDL_STUB_MESSAGE StubMsg;
1894     MIDL_STUB_DESC StubDesc = Object_StubDesc;
1895     unsigned char *ret;
1896     unsigned char *binding;
1897     RPC_BINDING_HANDLE Handle;
1898     RPC_STATUS status;
1899     ULONG prev_buffer_length;
1900     BOOL old_buffer_valid_location;
1901
1902     StubDesc.RpcInterfaceInformation = (void *)&IFoo___RpcServerInterface;
1903
1904     status = RpcServerUseProtseqEp(ncalrpc, 20, endpoint, NULL);
1905     ok(RPC_S_OK == status, "RpcServerUseProtseqEp failed with status %u\n", status);
1906     status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL);
1907     ok(RPC_S_OK == status, "RpcServerRegisterIf failed with status %u\n", status);
1908     status = RpcServerListen(1, 20, TRUE);
1909     ok(RPC_S_OK == status, "RpcServerListen failed with status %u\n", status);
1910     if (status != RPC_S_OK)
1911     {
1912         /* Failed to create a server, running client tests is useless */
1913         return;
1914     }
1915
1916     status = RpcStringBindingCompose(NULL, ncalrpc, NULL, endpoint, NULL, &binding);
1917     ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%u)\n", status);
1918
1919     status = RpcBindingFromStringBinding(binding, &Handle);
1920     ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%u)\n", status);
1921     RpcStringFree(&binding);
1922
1923     NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 5);
1924
1925     ret = NdrGetBuffer(&StubMsg, 10, Handle);
1926     ok(ret == StubMsg.Buffer, "NdrGetBuffer should have returned the same value as StubMsg.Buffer instead of %p\n", ret);
1927     ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
1928     ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
1929     ok(RpcMessage.BufferLength == 10 ||
1930        broken(RpcMessage.BufferLength == 12), /* win2k */
1931        "RpcMessage.BufferLength should have been 10 instead of %d\n", RpcMessage.BufferLength);
1932     ok(RpcMessage.RpcFlags == 0, "RpcMessage.RpcFlags should have been 0x0 instead of 0x%x\n", RpcMessage.RpcFlags);
1933     ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
1934     ok(!StubMsg.BufferStart, "BufferStart should have been NULL instead of %p\n", StubMsg.BufferStart);
1935     ok(!StubMsg.BufferEnd, "BufferEnd should have been NULL instead of %p\n", StubMsg.BufferEnd);
1936 todo_wine
1937     ok(StubMsg.BufferLength == 0, "BufferLength should have left as 0 instead of being set to %d\n", StubMsg.BufferLength);
1938     old_buffer_valid_location = !StubMsg.fBufferValid;
1939     if (old_buffer_valid_location)
1940         ok(broken(StubMsg.CorrDespIncrement == TRUE), "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.CorrDespIncrement);
1941     else
1942         ok(StubMsg.fBufferValid, "fBufferValid should have been non-zero instead of 0x%x\n", StubMsg.fBufferValid);
1943
1944     prev_buffer_length = RpcMessage.BufferLength;
1945     StubMsg.BufferLength = 1;
1946     NdrFreeBuffer(&StubMsg);
1947     ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
1948     ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
1949     ok(RpcMessage.BufferLength == prev_buffer_length, "RpcMessage.BufferLength should have been left as %d instead of %d\n", prev_buffer_length, RpcMessage.BufferLength);
1950     ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
1951     ok(StubMsg.BufferLength == 1, "BufferLength should have left as 1 instead of being set to %d\n", StubMsg.BufferLength);
1952     if (old_buffer_valid_location)
1953         ok(broken(StubMsg.CorrDespIncrement == FALSE), "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.CorrDespIncrement);
1954     else
1955         ok(!StubMsg.fBufferValid, "fBufferValid should have been FALSE instead of %d\n", StubMsg.fBufferValid);
1956
1957     /* attempt double-free */
1958     NdrFreeBuffer(&StubMsg);
1959
1960     RpcBindingFree(&Handle);
1961
1962     status = RpcServerUnregisterIf(NULL, NULL, FALSE);
1963     ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%u)\n", status);
1964 }
1965
1966 static void test_NdrMapCommAndFaultStatus(void)
1967 {
1968     RPC_STATUS rpc_status;
1969     MIDL_STUB_MESSAGE StubMsg;
1970     RPC_MESSAGE RpcMessage;
1971
1972     NdrClientInitializeNew(&RpcMessage, &StubMsg, &Object_StubDesc, 5);
1973
1974     for (rpc_status = 0; rpc_status < 10000; rpc_status++)
1975     {
1976         RPC_STATUS status;
1977         ULONG comm_status = 0;
1978         ULONG fault_status = 0;
1979         ULONG expected_comm_status = 0;
1980         ULONG expected_fault_status = 0;
1981         status = NdrMapCommAndFaultStatus(&StubMsg, &comm_status, &fault_status, rpc_status);
1982         ok(status == RPC_S_OK, "NdrMapCommAndFaultStatus failed with error %d\n", status);
1983         switch (rpc_status)
1984         {
1985         case ERROR_INVALID_HANDLE:
1986         case RPC_S_INVALID_BINDING:
1987         case RPC_S_UNKNOWN_IF:
1988         case RPC_S_SERVER_UNAVAILABLE:
1989         case RPC_S_SERVER_TOO_BUSY:
1990         case RPC_S_CALL_FAILED_DNE:
1991         case RPC_S_PROTOCOL_ERROR:
1992         case RPC_S_UNSUPPORTED_TRANS_SYN:
1993         case RPC_S_UNSUPPORTED_TYPE:
1994         case RPC_S_PROCNUM_OUT_OF_RANGE:
1995         case EPT_S_NOT_REGISTERED:
1996         case RPC_S_COMM_FAILURE:
1997             expected_comm_status = rpc_status;
1998             break;
1999         default:
2000             expected_fault_status = rpc_status;
2001         }
2002         ok(comm_status == expected_comm_status, "NdrMapCommAndFaultStatus should have mapped %d to comm status %d instead of %d\n",
2003             rpc_status, expected_comm_status, comm_status);
2004         ok(fault_status == expected_fault_status, "NdrMapCommAndFaultStatus should have mapped %d to fault status %d instead of %d\n",
2005             rpc_status, expected_fault_status, fault_status);
2006     }
2007 }
2008
2009 static void test_NdrGetUserMarshalInfo(void)
2010 {
2011     RPC_STATUS status;
2012     MIDL_STUB_MESSAGE stubmsg;
2013     USER_MARSHAL_CB umcb;
2014     NDR_USER_MARSHAL_INFO umi;
2015     unsigned char buffer[16];
2016     void *rpc_channel_buffer = (void *)(ULONG_PTR)0xcafebabe;
2017     RPC_MESSAGE rpc_msg;
2018     RPC_STATUS (RPC_ENTRY *pNdrGetUserMarshalInfo)(ULONG *,ULONG,NDR_USER_MARSHAL_INFO *);
2019
2020     pNdrGetUserMarshalInfo = (void *)GetProcAddress(GetModuleHandle("rpcrt4.dll"), "NdrGetUserMarshalInfo");
2021     if (!pNdrGetUserMarshalInfo)
2022     {
2023         skip("NdrGetUserMarshalInfo not exported\n");
2024         return;
2025     }
2026
2027     /* unmarshall */
2028
2029     memset(&rpc_msg, 0xcc, sizeof(rpc_msg));
2030     rpc_msg.Buffer = buffer;
2031     rpc_msg.BufferLength = 16;
2032
2033     memset(&stubmsg, 0xcc, sizeof(stubmsg));
2034     stubmsg.RpcMsg = &rpc_msg;
2035     stubmsg.dwDestContext = MSHCTX_INPROC;
2036     stubmsg.pvDestContext = NULL;
2037     stubmsg.Buffer = buffer + 15;
2038     stubmsg.BufferLength = 0;
2039     stubmsg.BufferEnd = NULL;
2040     stubmsg.pRpcChannelBuffer = rpc_channel_buffer;
2041     stubmsg.StubDesc = NULL;
2042     stubmsg.pfnAllocate = my_alloc;
2043     stubmsg.pfnFree = my_free;
2044
2045     memset(&umcb, 0xcc, sizeof(umcb));
2046     umcb.Flags = MAKELONG(MSHCTX_INPROC, NDR_LOCAL_DATA_REPRESENTATION);
2047     umcb.pStubMsg = &stubmsg;
2048     umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
2049     umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
2050
2051     memset(&umi, 0xaa, sizeof(umi));
2052
2053     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2054     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2055     ok( umi.InformationLevel == 1,
2056        "umi.InformationLevel was %u instead of 1\n",
2057         umi.InformationLevel);
2058     ok( U(umi.Level1).Buffer == buffer + 15,
2059        "U(umi.Level1).Buffer was %p instead of %p\n",
2060         U(umi.Level1).Buffer, buffer);
2061     ok( U(umi.Level1).BufferSize == 1,
2062        "U(umi.Level1).BufferSize was %u instead of 1\n",
2063         U(umi.Level1).BufferSize);
2064     ok( U(umi.Level1).pfnAllocate == my_alloc,
2065        "U(umi.Level1).pfnAllocate was %p instead of %p\n",
2066         U(umi.Level1).pfnAllocate, my_alloc);
2067     ok( U(umi.Level1).pfnFree == my_free,
2068        "U(umi.Level1).pfnFree was %p instead of %p\n",
2069         U(umi.Level1).pfnFree, my_free);
2070     ok( U(umi.Level1).pRpcChannelBuffer == rpc_channel_buffer,
2071        "U(umi.Level1).pRpcChannelBuffer was %p instead of %p\n",
2072         U(umi.Level1).pRpcChannelBuffer, rpc_channel_buffer);
2073
2074     /* buffer size */
2075
2076     rpc_msg.Buffer = buffer;
2077     rpc_msg.BufferLength = 16;
2078
2079     stubmsg.Buffer = buffer;
2080     stubmsg.BufferLength = 16;
2081     stubmsg.BufferEnd = NULL;
2082
2083     umcb.CBType = USER_MARSHAL_CB_BUFFER_SIZE;
2084
2085     memset(&umi, 0xaa, sizeof(umi));
2086
2087     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2088     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2089     ok( umi.InformationLevel == 1,
2090        "umi.InformationLevel was %u instead of 1\n",
2091         umi.InformationLevel);
2092     ok( U(umi.Level1).Buffer == NULL,
2093        "U(umi.Level1).Buffer was %p instead of NULL\n",
2094         U(umi.Level1).Buffer);
2095     ok( U(umi.Level1).BufferSize == 0,
2096        "U(umi.Level1).BufferSize was %u instead of 0\n",
2097         U(umi.Level1).BufferSize);
2098     ok( U(umi.Level1).pfnAllocate == my_alloc,
2099        "U(umi.Level1).pfnAllocate was %p instead of %p\n",
2100         U(umi.Level1).pfnAllocate, my_alloc);
2101     ok( U(umi.Level1).pfnFree == my_free,
2102        "U(umi.Level1).pfnFree was %p instead of %p\n",
2103         U(umi.Level1).pfnFree, my_free);
2104     ok( U(umi.Level1).pRpcChannelBuffer == rpc_channel_buffer,
2105        "U(umi.Level1).pRpcChannelBuffer was %p instead of %p\n",
2106         U(umi.Level1).pRpcChannelBuffer, rpc_channel_buffer);
2107
2108     /* marshall */
2109
2110     rpc_msg.Buffer = buffer;
2111     rpc_msg.BufferLength = 16;
2112
2113     stubmsg.Buffer = buffer + 15;
2114     stubmsg.BufferLength = 0;
2115     stubmsg.BufferEnd = NULL;
2116
2117     umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2118
2119     memset(&umi, 0xaa, sizeof(umi));
2120
2121     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2122     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2123     ok( umi.InformationLevel == 1,
2124        "umi.InformationLevel was %u instead of 1\n",
2125         umi.InformationLevel);
2126     ok( U(umi.Level1).Buffer == buffer + 15,
2127        "U(umi.Level1).Buffer was %p instead of %p\n",
2128         U(umi.Level1).Buffer, buffer);
2129     ok( U(umi.Level1).BufferSize == 1,
2130        "U(umi.Level1).BufferSize was %u instead of 1\n",
2131         U(umi.Level1).BufferSize);
2132     ok( U(umi.Level1).pfnAllocate == my_alloc,
2133        "U(umi.Level1).pfnAllocate was %p instead of %p\n",
2134         U(umi.Level1).pfnAllocate, my_alloc);
2135     ok( U(umi.Level1).pfnFree == my_free,
2136        "U(umi.Level1).pfnFree was %p instead of %p\n",
2137         U(umi.Level1).pfnFree, my_free);
2138     ok( U(umi.Level1).pRpcChannelBuffer == rpc_channel_buffer,
2139        "U(umi.Level1).pRpcChannelBuffer was %p instead of %p\n",
2140         U(umi.Level1).pRpcChannelBuffer, rpc_channel_buffer);
2141
2142     /* free */
2143
2144     rpc_msg.Buffer = buffer;
2145     rpc_msg.BufferLength = 16;
2146
2147     stubmsg.Buffer = buffer;
2148     stubmsg.BufferLength = 16;
2149     stubmsg.BufferEnd = NULL;
2150
2151     umcb.CBType = USER_MARSHAL_CB_FREE;
2152
2153     memset(&umi, 0xaa, sizeof(umi));
2154
2155     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2156     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2157     ok( umi.InformationLevel == 1,
2158        "umi.InformationLevel was %u instead of 1\n",
2159         umi.InformationLevel);
2160     ok( U(umi.Level1).Buffer == NULL,
2161        "U(umi.Level1).Buffer was %p instead of NULL\n",
2162         U(umi.Level1).Buffer);
2163     ok( U(umi.Level1).BufferSize == 0,
2164        "U(umi.Level1).BufferSize was %u instead of 0\n",
2165         U(umi.Level1).BufferSize);
2166     ok( U(umi.Level1).pfnAllocate == my_alloc,
2167        "U(umi.Level1).pfnAllocate was %p instead of %p\n",
2168         U(umi.Level1).pfnAllocate, my_alloc);
2169     ok( U(umi.Level1).pfnFree == my_free,
2170        "U(umi.Level1).pfnFree was %p instead of %p\n",
2171         U(umi.Level1).pfnFree, my_free);
2172     ok( U(umi.Level1).pRpcChannelBuffer == rpc_channel_buffer,
2173        "U(umi.Level1).pRpcChannelBuffer was %p instead of %p\n",
2174         U(umi.Level1).pRpcChannelBuffer, rpc_channel_buffer);
2175
2176     /* boundary test */
2177
2178     rpc_msg.Buffer = buffer;
2179     rpc_msg.BufferLength = 15;
2180
2181     stubmsg.Buffer = buffer + 15;
2182     stubmsg.BufferLength = 0;
2183     stubmsg.BufferEnd = NULL;
2184
2185     umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2186
2187     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2188     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2189     ok( U(umi.Level1).BufferSize == 0,
2190        "U(umi.Level1).BufferSize was %u instead of 0\n",
2191         U(umi.Level1).BufferSize);
2192
2193     /* error conditions */
2194
2195     rpc_msg.BufferLength = 14;
2196     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2197     ok(status == ERROR_INVALID_USER_BUFFER,
2198         "NdrGetUserMarshalInfo should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", status);
2199
2200     rpc_msg.BufferLength = 15;
2201     status = pNdrGetUserMarshalInfo(&umcb.Flags, 9999, &umi);
2202     ok(status == RPC_S_INVALID_ARG,
2203         "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status);
2204
2205     umcb.CBType = 9999;
2206     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2207     ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2208
2209     umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2210     umcb.Signature = 0;
2211     status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2212     ok(status == RPC_S_INVALID_ARG,
2213         "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status);
2214 }
2215
2216 START_TEST( ndr_marshall )
2217 {
2218     determine_pointer_marshalling_style();
2219
2220     test_ndr_simple_type();
2221     test_simple_types();
2222     test_nontrivial_pointer_types();
2223     test_simple_struct();
2224     test_fullpointer_xlat();
2225     test_client_init();
2226     test_server_init();
2227     test_ndr_allocate();
2228     test_conformant_array();
2229     test_conformant_string();
2230     test_nonconformant_string();
2231     test_conf_complex_struct();
2232     test_ndr_buffer();
2233     test_NdrMapCommAndFaultStatus();
2234     test_NdrGetUserMarshalInfo();
2235 }