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