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