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