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