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)≪
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