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