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