1 /* 2 * NDR -Oi,-Oif,-Oicf Interpreter 3 * 4 * Copyright 2001 Ove Kåven, TransGaming Technologies 5 * Copyright 2003-5 Robert Shearman (for CodeWeavers) 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 * 21 * TODO: 22 * - Pipes 23 * - Some types of binding handles 24 */ 25 26 #include <stdarg.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "winerror.h" 33 34 #include "objbase.h" 35 #include "rpc.h" 36 #include "rpcproxy.h" 37 38 #include "wine/exception.h" 39 #include "wine/asm.h" 40 #include "wine/debug.h" 41 42 #include "cpsf.h" 43 #include "ndr_misc.h" 44 #include "ndr_stubless.h" 45 46 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 47 48 #define NDR_TABLE_MASK 127 49 50 static inline BOOL is_oicf_stubdesc(const PMIDL_STUB_DESC pStubDesc) 51 { 52 return pStubDesc->Version >= 0x20000; 53 } 54 55 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 56 const NDR_PARAM_OIF *param) 57 { 58 PFORMAT_STRING pFormat; 59 NDR_BUFFERSIZE m; 60 61 if (param->attr.IsBasetype) 62 { 63 pFormat = ¶m->u.type_format_char; 64 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; 65 } 66 else 67 { 68 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 69 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 70 } 71 72 m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; 73 if (m) m(pStubMsg, pMemory, pFormat); 74 else 75 { 76 FIXME("format type 0x%x not implemented\n", pFormat[0]); 77 RpcRaiseException(RPC_X_BAD_STUB_DATA); 78 } 79 } 80 81 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 82 const NDR_PARAM_OIF *param) 83 { 84 PFORMAT_STRING pFormat; 85 NDR_MARSHALL m; 86 87 if (param->attr.IsBasetype) 88 { 89 pFormat = ¶m->u.type_format_char; 90 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; 91 } 92 else 93 { 94 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 95 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 96 } 97 98 m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; 99 if (m) return m(pStubMsg, pMemory, pFormat); 100 else 101 { 102 FIXME("format type 0x%x not implemented\n", pFormat[0]); 103 RpcRaiseException(RPC_X_BAD_STUB_DATA); 104 return NULL; 105 } 106 } 107 108 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, 109 const NDR_PARAM_OIF *param, unsigned char fMustAlloc) 110 { 111 PFORMAT_STRING pFormat; 112 NDR_UNMARSHALL m; 113 114 if (param->attr.IsBasetype) 115 { 116 pFormat = ¶m->u.type_format_char; 117 if (param->attr.IsSimpleRef) ppMemory = (unsigned char **)*ppMemory; 118 } 119 else 120 { 121 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 122 if (!param->attr.IsByValue) ppMemory = (unsigned char **)*ppMemory; 123 } 124 125 m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; 126 if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); 127 else 128 { 129 FIXME("format type 0x%x not implemented\n", pFormat[0]); 130 RpcRaiseException(RPC_X_BAD_STUB_DATA); 131 return NULL; 132 } 133 } 134 135 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 136 const NDR_PARAM_OIF *param) 137 { 138 PFORMAT_STRING pFormat; 139 NDR_FREE m; 140 141 if (param->attr.IsBasetype) return; /* nothing to do */ 142 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 143 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 144 145 m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; 146 if (m) m(pStubMsg, pMemory, pFormat); 147 } 148 149 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) 150 { 151 DWORD size; 152 switch(*pFormat) 153 { 154 case FC_RP: 155 if (pFormat[1] & FC_SIMPLE_POINTER) 156 { 157 size = 0; 158 break; 159 } 160 size = calc_arg_size(pStubMsg, &pFormat[2] + *(const SHORT*)&pFormat[2]); 161 break; 162 case FC_STRUCT: 163 case FC_PSTRUCT: 164 size = *(const WORD*)(pFormat + 2); 165 break; 166 case FC_BOGUS_STRUCT: 167 size = *(const WORD*)(pFormat + 2); 168 if(*(const WORD*)(pFormat + 4)) 169 FIXME("Unhandled conformant description\n"); 170 break; 171 case FC_CARRAY: 172 case FC_CVARRAY: 173 size = *(const WORD*)(pFormat + 2); 174 ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); 175 size *= pStubMsg->MaxCount; 176 break; 177 case FC_SMFARRAY: 178 case FC_SMVARRAY: 179 size = *(const WORD*)(pFormat + 2); 180 break; 181 case FC_LGFARRAY: 182 case FC_LGVARRAY: 183 size = *(const DWORD*)(pFormat + 2); 184 break; 185 case FC_BOGUS_ARRAY: 186 pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]); 187 TRACE("conformance = %ld\n", pStubMsg->MaxCount); 188 pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount); 189 size = ComplexStructSize(pStubMsg, pFormat); 190 size *= pStubMsg->MaxCount; 191 break; 192 case FC_USER_MARSHAL: 193 size = *(const WORD*)(pFormat + 4); 194 break; 195 case FC_CSTRING: 196 size = *(const WORD*)(pFormat + 2); 197 break; 198 case FC_WSTRING: 199 size = *(const WORD*)(pFormat + 2) * sizeof(WCHAR); 200 break; 201 case FC_C_CSTRING: 202 case FC_C_WSTRING: 203 if (*pFormat == FC_C_CSTRING) 204 size = sizeof(CHAR); 205 else 206 size = sizeof(WCHAR); 207 if (pFormat[1] == FC_STRING_SIZED) 208 ComputeConformance(pStubMsg, NULL, pFormat + 2, 0); 209 else 210 pStubMsg->MaxCount = 0; 211 size *= pStubMsg->MaxCount; 212 break; 213 default: 214 FIXME("Unhandled type %02x\n", *pFormat); 215 /* fallthrough */ 216 case FC_UP: 217 case FC_OP: 218 case FC_FP: 219 case FC_IP: 220 size = sizeof(void *); 221 break; 222 } 223 return size; 224 } 225 226 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) 227 { 228 #if 0 /* these functions are not defined yet */ 229 pMessage->pfnAllocate = NdrRpcSmClientAllocate; 230 pMessage->pfnFree = NdrRpcSmClientFree; 231 #endif 232 } 233 234 static const char *debugstr_PROC_PF(PARAM_ATTRIBUTES param_attributes) 235 { 236 char buffer[160]; 237 238 buffer[0] = 0; 239 if (param_attributes.MustSize) strcat(buffer, " MustSize"); 240 if (param_attributes.MustFree) strcat(buffer, " MustFree"); 241 if (param_attributes.IsPipe) strcat(buffer, " IsPipe"); 242 if (param_attributes.IsIn) strcat(buffer, " IsIn"); 243 if (param_attributes.IsOut) strcat(buffer, " IsOut"); 244 if (param_attributes.IsReturn) strcat(buffer, " IsReturn"); 245 if (param_attributes.IsBasetype) strcat(buffer, " IsBasetype"); 246 if (param_attributes.IsByValue) strcat(buffer, " IsByValue"); 247 if (param_attributes.IsSimpleRef) strcat(buffer, " IsSimpleRef"); 248 if (param_attributes.IsDontCallFreeInst) strcat(buffer, " IsDontCallFreeInst"); 249 if (param_attributes.SaveForAsyncFinish) strcat(buffer, " SaveForAsyncFinish"); 250 if (param_attributes.ServerAllocSize) 251 sprintf( buffer + strlen(buffer), " ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); 252 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; 253 } 254 255 static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) 256 { 257 char buffer[160]; 258 259 buffer[0] = 0; 260 if (Oi2Flags.ServerMustSize) strcat(buffer, " ServerMustSize"); 261 if (Oi2Flags.ClientMustSize) strcat(buffer, " ClientMustSize"); 262 if (Oi2Flags.HasReturn) strcat(buffer, " HasReturn"); 263 if (Oi2Flags.HasPipes) strcat(buffer, " HasPipes"); 264 if (Oi2Flags.Unused) strcat(buffer, " Unused"); 265 if (Oi2Flags.HasAsyncUuid) strcat(buffer, " HasAsyncUuid"); 266 if (Oi2Flags.HasExtensions) strcat(buffer, " HasExtensions"); 267 if (Oi2Flags.HasAsyncHandle) strcat(buffer, " HasAsyncHandle"); 268 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; 269 } 270 271 #define ARG_FROM_OFFSET(args, offset) ((args) + (offset)) 272 273 static size_t get_handle_desc_size(const NDR_PROC_HEADER *proc_header, PFORMAT_STRING format) 274 { 275 if (!proc_header->handle_type) 276 { 277 if (*format == FC_BIND_PRIMITIVE) 278 return sizeof(NDR_EHD_PRIMITIVE); 279 else if (*format == FC_BIND_GENERIC) 280 return sizeof(NDR_EHD_GENERIC); 281 else if (*format == FC_BIND_CONTEXT) 282 return sizeof(NDR_EHD_CONTEXT); 283 } 284 return 0; 285 } 286 287 static handle_t client_get_handle(const MIDL_STUB_MESSAGE *pStubMsg, 288 const NDR_PROC_HEADER *pProcHeader, const PFORMAT_STRING pFormat) 289 { 290 /* binding */ 291 switch (pProcHeader->handle_type) 292 { 293 /* explicit binding: parse additional section */ 294 case 0: 295 switch (*pFormat) /* handle_type */ 296 { 297 case FC_BIND_PRIMITIVE: /* explicit primitive */ 298 { 299 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; 300 301 TRACE("Explicit primitive handle @ %d\n", pDesc->offset); 302 303 if (pDesc->flag) /* pointer to binding */ 304 return **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 305 else 306 return *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 307 } 308 case FC_BIND_GENERIC: /* explicit generic */ 309 { 310 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; 311 void *pObject = NULL; 312 void *pArg; 313 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; 314 315 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); 316 317 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) 318 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 319 else 320 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 321 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); 322 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; 323 return pGenPair->pfnBind(pObject); 324 } 325 case FC_BIND_CONTEXT: /* explicit context */ 326 { 327 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; 328 NDR_CCONTEXT context_handle; 329 TRACE("Explicit bind context\n"); 330 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) 331 { 332 TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); 333 context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 334 } 335 else 336 context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 337 338 if (context_handle) return NDRCContextBinding(context_handle); 339 else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) 340 { 341 ERR("null context handle isn't allowed\n"); 342 RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT); 343 return NULL; 344 } 345 /* FIXME: should we store this structure in stubMsg.pContext? */ 346 } 347 default: 348 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 349 RpcRaiseException(RPC_X_BAD_STUB_DATA); 350 } 351 break; 352 case FC_BIND_GENERIC: /* implicit generic */ 353 FIXME("FC_BIND_GENERIC\n"); 354 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ 355 break; 356 case FC_BIND_PRIMITIVE: /* implicit primitive */ 357 TRACE("Implicit primitive handle\n"); 358 return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; 359 case FC_CALLBACK_HANDLE: /* implicit callback */ 360 TRACE("FC_CALLBACK_HANDLE\n"); 361 /* server calls callback procedures only in response to remote call, and most recent 362 binding handle is used. Calling back to a client can potentially result in another 363 callback with different current handle. */ 364 return I_RpcGetCurrentCallHandle(); 365 case FC_AUTO_HANDLE: /* implicit auto handle */ 366 /* strictly speaking, it isn't necessary to set hBinding here 367 * since it isn't actually used (hence the automatic in its name), 368 * but then why does MIDL generate a valid entry in the 369 * MIDL_STUB_DESC for it? */ 370 TRACE("Implicit auto handle\n"); 371 return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; 372 default: 373 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 374 RpcRaiseException(RPC_X_BAD_STUB_DATA); 375 } 376 return NULL; 377 } 378 379 static void client_free_handle( 380 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, 381 PFORMAT_STRING pFormat, handle_t hBinding) 382 { 383 /* binding */ 384 switch (pProcHeader->handle_type) 385 { 386 /* explicit binding: parse additional section */ 387 case 0: 388 switch (*pFormat) /* handle_type */ 389 { 390 case FC_BIND_GENERIC: /* explicit generic */ 391 { 392 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; 393 void *pObject = NULL; 394 void *pArg; 395 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; 396 397 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); 398 399 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) 400 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 401 else 402 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 403 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); 404 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; 405 #ifdef __REACTOS__ 406 if (hBinding) pGenPair->pfnUnbind(pObject, hBinding); 407 #else 408 pGenPair->pfnUnbind(pObject, hBinding); 409 #endif 410 break; 411 } 412 case FC_BIND_CONTEXT: /* explicit context */ 413 case FC_BIND_PRIMITIVE: /* explicit primitive */ 414 break; 415 default: 416 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 417 RpcRaiseException(RPC_X_BAD_STUB_DATA); 418 } 419 break; 420 case FC_BIND_GENERIC: /* implicit generic */ 421 FIXME("FC_BIND_GENERIC\n"); 422 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ 423 break; 424 case FC_CALLBACK_HANDLE: /* implicit callback */ 425 case FC_BIND_PRIMITIVE: /* implicit primitive */ 426 case FC_AUTO_HANDLE: /* implicit auto handle */ 427 break; 428 default: 429 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 430 RpcRaiseException(RPC_X_BAD_STUB_DATA); 431 } 432 } 433 434 static inline BOOL param_needs_alloc( PARAM_ATTRIBUTES attr ) 435 { 436 return attr.IsOut && !attr.IsIn && !attr.IsBasetype && !attr.IsByValue; 437 } 438 439 static inline BOOL param_is_out_basetype( PARAM_ATTRIBUTES attr ) 440 { 441 return attr.IsOut && !attr.IsIn && attr.IsBasetype && attr.IsSimpleRef; 442 } 443 444 static size_t basetype_arg_size( unsigned char fc ) 445 { 446 switch (fc) 447 { 448 case FC_BYTE: 449 case FC_CHAR: 450 case FC_SMALL: 451 case FC_USMALL: 452 return sizeof(char); 453 case FC_WCHAR: 454 case FC_SHORT: 455 case FC_USHORT: 456 return sizeof(short); 457 case FC_LONG: 458 case FC_ULONG: 459 case FC_ENUM16: 460 case FC_ENUM32: 461 case FC_ERROR_STATUS_T: 462 return sizeof(int); 463 case FC_FLOAT: 464 return sizeof(float); 465 case FC_HYPER: 466 return sizeof(LONGLONG); 467 case FC_DOUBLE: 468 return sizeof(double); 469 case FC_INT3264: 470 case FC_UINT3264: 471 return sizeof(INT_PTR); 472 default: 473 FIXME("Unhandled basetype %#x.\n", fc); 474 return 0; 475 } 476 } 477 478 void client_do_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase, 479 void **fpu_args, unsigned short number_of_params, unsigned char *pRetVal ) 480 { 481 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; 482 unsigned int i; 483 484 for (i = 0; i < number_of_params; i++) 485 { 486 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; 487 PFORMAT_STRING pTypeFormat = (PFORMAT_STRING)&pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; 488 489 #ifdef __x86_64__ /* floats are passed as doubles through varargs functions */ 490 float f; 491 492 if (params[i].attr.IsBasetype && 493 params[i].u.type_format_char == FC_FLOAT && 494 !params[i].attr.IsSimpleRef && 495 !fpu_args) 496 { 497 f = *(double *)pArg; 498 pArg = (unsigned char *)&f; 499 } 500 #endif 501 502 TRACE("param[%d]: %p type %02x %s\n", i, pArg, 503 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, 504 debugstr_PROC_PF( params[i].attr )); 505 506 switch (phase) 507 { 508 case STUBLESS_INITOUT: 509 if (*(unsigned char **)pArg) 510 { 511 if (param_needs_alloc(params[i].attr)) 512 memset( *(unsigned char **)pArg, 0, calc_arg_size( pStubMsg, pTypeFormat )); 513 else if (param_is_out_basetype(params[i].attr)) 514 memset( *(unsigned char **)pArg, 0, basetype_arg_size( params[i].u.type_format_char )); 515 } 516 break; 517 case STUBLESS_CALCSIZE: 518 if (params[i].attr.IsSimpleRef && !*(unsigned char **)pArg) 519 RpcRaiseException(RPC_X_NULL_REF_POINTER); 520 if (params[i].attr.IsIn) call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); 521 break; 522 case STUBLESS_MARSHAL: 523 if (params[i].attr.IsIn) call_marshaller(pStubMsg, pArg, ¶ms[i]); 524 break; 525 case STUBLESS_UNMARSHAL: 526 if (params[i].attr.IsOut) 527 { 528 if (params[i].attr.IsReturn && pRetVal) pArg = pRetVal; 529 call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); 530 } 531 break; 532 case STUBLESS_FREE: 533 if (!params[i].attr.IsBasetype && params[i].attr.IsOut && !params[i].attr.IsByValue) 534 NdrClearOutParameters( pStubMsg, pTypeFormat, *(unsigned char **)pArg ); 535 break; 536 default: 537 RpcRaiseException(RPC_S_INTERNAL_ERROR); 538 } 539 } 540 } 541 542 static unsigned int type_stack_size(unsigned char fc) 543 { 544 switch (fc) 545 { 546 case FC_BYTE: 547 case FC_CHAR: 548 case FC_SMALL: 549 case FC_USMALL: 550 case FC_WCHAR: 551 case FC_SHORT: 552 case FC_USHORT: 553 case FC_LONG: 554 case FC_ULONG: 555 case FC_INT3264: 556 case FC_UINT3264: 557 case FC_ENUM16: 558 case FC_ENUM32: 559 case FC_FLOAT: 560 case FC_ERROR_STATUS_T: 561 case FC_IGNORE: 562 return sizeof(void *); 563 case FC_DOUBLE: 564 return sizeof(double); 565 case FC_HYPER: 566 return sizeof(ULONGLONG); 567 default: 568 ERR("invalid base type 0x%x\n", fc); 569 RpcRaiseException(RPC_S_INTERNAL_ERROR); 570 } 571 } 572 573 static BOOL is_by_value( PFORMAT_STRING format ) 574 { 575 switch (*format) 576 { 577 case FC_USER_MARSHAL: 578 case FC_STRUCT: 579 case FC_PSTRUCT: 580 case FC_CSTRUCT: 581 case FC_CPSTRUCT: 582 case FC_CVSTRUCT: 583 case FC_BOGUS_STRUCT: 584 return TRUE; 585 default: 586 return FALSE; 587 } 588 } 589 590 PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, 591 unsigned int stack_size, BOOL object_proc, 592 void *buffer, unsigned int size, unsigned int *count ) 593 { 594 NDR_PARAM_OIF *args = buffer; 595 unsigned int i, stack_offset = object_proc ? sizeof(void *) : 0; 596 597 for (i = 0; stack_offset < stack_size; i++) 598 { 599 const NDR_PARAM_OI_BASETYPE *param = (const NDR_PARAM_OI_BASETYPE *)pFormat; 600 const NDR_PARAM_OI_OTHER *other = (const NDR_PARAM_OI_OTHER *)pFormat; 601 602 if (i + 1 > size / sizeof(*args)) 603 { 604 FIXME( "%u args not supported\n", i ); 605 RpcRaiseException( RPC_S_INTERNAL_ERROR ); 606 } 607 608 args[i].stack_offset = stack_offset; 609 memset( &args[i].attr, 0, sizeof(args[i].attr) ); 610 611 switch (param->param_direction) 612 { 613 case FC_IN_PARAM_BASETYPE: 614 args[i].attr.IsIn = 1; 615 args[i].attr.IsBasetype = 1; 616 break; 617 case FC_RETURN_PARAM_BASETYPE: 618 args[i].attr.IsOut = 1; 619 args[i].attr.IsReturn = 1; 620 args[i].attr.IsBasetype = 1; 621 break; 622 case FC_IN_PARAM: 623 args[i].attr.IsIn = 1; 624 args[i].attr.MustFree = 1; 625 break; 626 case FC_IN_PARAM_NO_FREE_INST: 627 args[i].attr.IsIn = 1; 628 args[i].attr.IsDontCallFreeInst = 1; 629 break; 630 case FC_IN_OUT_PARAM: 631 args[i].attr.IsIn = 1; 632 args[i].attr.IsOut = 1; 633 args[i].attr.MustFree = 1; 634 break; 635 case FC_OUT_PARAM: 636 args[i].attr.IsOut = 1; 637 break; 638 case FC_RETURN_PARAM: 639 args[i].attr.IsOut = 1; 640 args[i].attr.IsReturn = 1; 641 break; 642 } 643 if (args[i].attr.IsBasetype) 644 { 645 args[i].u.type_format_char = param->type_format_char; 646 stack_offset += type_stack_size( param->type_format_char ); 647 pFormat += sizeof(NDR_PARAM_OI_BASETYPE); 648 } 649 else 650 { 651 args[i].u.type_offset = other->type_offset; 652 args[i].attr.IsByValue = is_by_value( &pStubMsg->StubDesc->pFormatTypes[other->type_offset] ); 653 stack_offset += other->stack_size * sizeof(void *); 654 pFormat += sizeof(NDR_PARAM_OI_OTHER); 655 } 656 } 657 *count = i; 658 return (PFORMAT_STRING)args; 659 } 660 661 struct ndr_client_call_ctx 662 { 663 MIDL_STUB_MESSAGE *stub_msg; 664 INTERPRETER_OPT_FLAGS Oif_flags; 665 INTERPRETER_OPT_FLAGS2 ext_flags; 666 const NDR_PROC_HEADER *proc_header; 667 void *This; 668 PFORMAT_STRING handle_format; 669 handle_t hbinding; 670 }; 671 672 static void CALLBACK ndr_client_call_finally(BOOL normal, void *arg) 673 { 674 struct ndr_client_call_ctx *ctx = arg; 675 676 if (ctx->ext_flags.HasNewCorrDesc) 677 { 678 /* free extra correlation package */ 679 NdrCorrelationFree(ctx->stub_msg); 680 } 681 682 if (ctx->Oif_flags.HasPipes) 683 { 684 /* NdrPipesDone(...) */ 685 } 686 687 /* free the full pointer translation tables */ 688 if (ctx->proc_header->Oi_flags & Oi_FULL_PTR_USED) 689 NdrFullPointerXlatFree(ctx->stub_msg->FullPtrXlatTables); 690 691 /* free marshalling buffer */ 692 if (ctx->proc_header->Oi_flags & Oi_OBJECT_PROC) 693 NdrProxyFreeBuffer(ctx->This, ctx->stub_msg); 694 else 695 { 696 NdrFreeBuffer(ctx->stub_msg); 697 client_free_handle(ctx->stub_msg, ctx->proc_header, ctx->handle_format, ctx->hbinding); 698 } 699 } 700 701 /* Helper for ndr_client_call, to factor out the part that may or may not be 702 * guarded by a try/except block. */ 703 static LONG_PTR do_ndr_client_call( const MIDL_STUB_DESC *stub_desc, const PFORMAT_STRING format, 704 const PFORMAT_STRING handle_format, void **stack_top, void **fpu_stack, MIDL_STUB_MESSAGE *stub_msg, 705 unsigned short procedure_number, unsigned short stack_size, unsigned int number_of_params, 706 INTERPRETER_OPT_FLAGS Oif_flags, INTERPRETER_OPT_FLAGS2 ext_flags, const NDR_PROC_HEADER *proc_header ) 707 { 708 struct ndr_client_call_ctx finally_ctx; 709 RPC_MESSAGE rpc_msg; 710 handle_t hbinding = NULL; 711 /* the value to return to the client from the remote procedure */ 712 LONG_PTR retval = 0; 713 /* the pointer to the object when in OLE mode */ 714 void *This = NULL; 715 /* correlation cache */ 716 ULONG_PTR NdrCorrCache[256]; 717 718 /* create the full pointer translation tables, if requested */ 719 if (proc_header->Oi_flags & Oi_FULL_PTR_USED) 720 stub_msg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); 721 722 if (proc_header->Oi_flags & Oi_OBJECT_PROC) 723 { 724 /* object is always the first argument */ 725 This = stack_top[0]; 726 NdrProxyInitialize(This, &rpc_msg, stub_msg, stub_desc, procedure_number); 727 } 728 729 finally_ctx.stub_msg = stub_msg; 730 finally_ctx.Oif_flags = Oif_flags; 731 finally_ctx.ext_flags = ext_flags; 732 finally_ctx.proc_header = proc_header; 733 finally_ctx.This = This; 734 finally_ctx.handle_format = handle_format; 735 finally_ctx.hbinding = hbinding; 736 737 __TRY 738 { 739 if (!(proc_header->Oi_flags & Oi_OBJECT_PROC)) 740 NdrClientInitializeNew(&rpc_msg, stub_msg, stub_desc, procedure_number); 741 742 stub_msg->StackTop = (unsigned char *)stack_top; 743 744 /* we only need a handle if this isn't an object method */ 745 if (!(proc_header->Oi_flags & Oi_OBJECT_PROC)) 746 { 747 hbinding = client_get_handle(stub_msg, proc_header, handle_format); 748 if (!hbinding) return 0; 749 } 750 751 stub_msg->BufferLength = 0; 752 753 /* store the RPC flags away */ 754 if (proc_header->Oi_flags & Oi_HAS_RPCFLAGS) 755 rpc_msg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)proc_header)->rpc_flags; 756 757 /* use alternate memory allocation routines */ 758 if (proc_header->Oi_flags & Oi_RPCSS_ALLOC_USED) 759 NdrRpcSmSetClientToOsf(stub_msg); 760 761 if (Oif_flags.HasPipes) 762 { 763 FIXME("pipes not supported yet\n"); 764 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 765 /* init pipes package */ 766 /* NdrPipesInitialize(...) */ 767 } 768 if (ext_flags.HasNewCorrDesc) 769 { 770 /* initialize extra correlation package */ 771 NdrCorrelationInitialize(stub_msg, NdrCorrCache, sizeof(NdrCorrCache), 0); 772 if (ext_flags.Unused & 0x2) /* has range on conformance */ 773 stub_msg->CorrDespIncrement = 12; 774 } 775 776 /* order of phases: 777 * 1. INITOUT - zero [out] parameters (proxies only) 778 * 2. CALCSIZE - calculate the buffer size 779 * 3. GETBUFFER - allocate the buffer 780 * 4. MARSHAL - marshal [in] params into the buffer 781 * 5. SENDRECEIVE - send/receive buffer 782 * 6. UNMARSHAL - unmarshal [out] params from buffer 783 * 7. FREE - clear [out] parameters (for proxies, and only on error) 784 */ 785 786 /* 1. INITOUT */ 787 if (proc_header->Oi_flags & Oi_OBJECT_PROC) 788 { 789 TRACE( "INITOUT\n" ); 790 client_do_args(stub_msg, format, STUBLESS_INITOUT, fpu_stack, 791 number_of_params, (unsigned char *)&retval); 792 } 793 794 /* 2. CALCSIZE */ 795 TRACE( "CALCSIZE\n" ); 796 client_do_args(stub_msg, format, STUBLESS_CALCSIZE, fpu_stack, 797 number_of_params, (unsigned char *)&retval); 798 799 /* 3. GETBUFFER */ 800 TRACE( "GETBUFFER\n" ); 801 if (proc_header->Oi_flags & Oi_OBJECT_PROC) 802 NdrProxyGetBuffer(This, stub_msg); 803 else if (Oif_flags.HasPipes) 804 FIXME("pipes not supported yet\n"); 805 else if (proc_header->handle_type == FC_AUTO_HANDLE) 806 #if 0 807 NdrNsGetBuffer(stub_msg, stub_msg->BufferLength, hBinding); 808 #else 809 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 810 #endif 811 else 812 NdrGetBuffer(stub_msg, stub_msg->BufferLength, hbinding); 813 814 /* 4. MARSHAL */ 815 TRACE( "MARSHAL\n" ); 816 client_do_args(stub_msg, format, STUBLESS_MARSHAL, fpu_stack, 817 number_of_params, (unsigned char *)&retval); 818 819 /* 5. SENDRECEIVE */ 820 TRACE( "SENDRECEIVE\n" ); 821 if (proc_header->Oi_flags & Oi_OBJECT_PROC) 822 NdrProxySendReceive(This, stub_msg); 823 else if (Oif_flags.HasPipes) 824 /* NdrPipesSendReceive(...) */ 825 FIXME("pipes not supported yet\n"); 826 else if (proc_header->handle_type == FC_AUTO_HANDLE) 827 #if 0 828 NdrNsSendReceive(stub_msg, stub_msg->Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 829 #else 830 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); 831 #endif 832 else 833 NdrSendReceive(stub_msg, stub_msg->Buffer); 834 835 /* convert strings, floating point values and endianness into our 836 * preferred format */ 837 if ((rpc_msg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 838 NdrConvert(stub_msg, format); 839 840 /* 6. UNMARSHAL */ 841 TRACE( "UNMARSHAL\n" ); 842 client_do_args(stub_msg, format, STUBLESS_UNMARSHAL, fpu_stack, 843 number_of_params, (unsigned char *)&retval); 844 } 845 __FINALLY_CTX(ndr_client_call_finally, &finally_ctx) 846 847 return retval; 848 } 849 850 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, 851 void **stack_top, void **fpu_stack ) 852 { 853 /* pointer to start of stack where arguments start */ 854 MIDL_STUB_MESSAGE stubMsg; 855 /* procedure number */ 856 unsigned short procedure_number; 857 /* size of stack */ 858 unsigned short stack_size; 859 /* number of parameters. optional for client to give it to us */ 860 unsigned int number_of_params; 861 /* cache of Oif_flags from v2 procedure header */ 862 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 863 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 864 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 865 /* header for procedure string */ 866 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 867 /* the value to return to the client from the remote procedure */ 868 LONG_PTR RetVal = 0; 869 PFORMAT_STRING pHandleFormat; 870 NDR_PARAM_OIF old_args[256]; 871 872 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); 873 874 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 875 876 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 877 { 878 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 879 stack_size = header_rpc->stack_size; 880 procedure_number = header_rpc->proc_num; 881 pFormat += sizeof(NDR_PROC_HEADER_RPC); 882 } 883 else 884 { 885 stack_size = pProcHeader->stack_size; 886 procedure_number = pProcHeader->proc_num; 887 pFormat += sizeof(NDR_PROC_HEADER); 888 } 889 TRACE("stack size: 0x%x\n", stack_size); 890 TRACE("proc num: %d\n", procedure_number); 891 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 892 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); 893 894 pHandleFormat = pFormat; 895 896 /* we only need a handle if this isn't an object method */ 897 if (!(pProcHeader->Oi_flags & Oi_OBJECT_PROC)) 898 pFormat += get_handle_desc_size(pProcHeader, pFormat); 899 900 if (is_oicf_stubdesc(pStubDesc)) /* -Oicf format */ 901 { 902 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = 903 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 904 905 Oif_flags = pOIFHeader->Oi2Flags; 906 number_of_params = pOIFHeader->number_of_params; 907 908 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 909 910 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 911 912 if (Oif_flags.HasExtensions) 913 { 914 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 915 ext_flags = pExtensions->Flags2; 916 pFormat += pExtensions->Size; 917 #ifdef __x86_64__ 918 if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack) 919 { 920 int i; 921 unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1); 922 for (i = 0; i < 4; i++, fpu_mask >>= 2) 923 switch (fpu_mask & 3) 924 { 925 case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break; 926 case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break; 927 } 928 } 929 #endif 930 } 931 } 932 else 933 { 934 pFormat = convert_old_args( &stubMsg, pFormat, stack_size, 935 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 936 old_args, sizeof(old_args), &number_of_params ); 937 } 938 939 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 940 { 941 __TRY 942 { 943 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, 944 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, 945 number_of_params, Oif_flags, ext_flags, pProcHeader); 946 } 947 __EXCEPT_ALL 948 { 949 /* 7. FREE */ 950 TRACE( "FREE\n" ); 951 client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack, 952 number_of_params, (unsigned char *)&RetVal); 953 RetVal = NdrProxyErrorHandler(GetExceptionCode()); 954 } 955 __ENDTRY 956 } 957 else if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT) 958 { 959 __TRY 960 { 961 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, 962 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, 963 number_of_params, Oif_flags, ext_flags, pProcHeader); 964 } 965 __EXCEPT_ALL 966 { 967 const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number]; 968 ULONG *comm_status; 969 ULONG *fault_status; 970 971 TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset); 972 973 if (comm_fault_offsets->CommOffset == -1) 974 comm_status = (ULONG *)&RetVal; 975 else if (comm_fault_offsets->CommOffset >= 0) 976 comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset); 977 else 978 comm_status = NULL; 979 980 if (comm_fault_offsets->FaultOffset == -1) 981 fault_status = (ULONG *)&RetVal; 982 else if (comm_fault_offsets->FaultOffset >= 0) 983 fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->FaultOffset); 984 else 985 fault_status = NULL; 986 987 NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status, 988 GetExceptionCode()); 989 } 990 __ENDTRY 991 } 992 else 993 { 994 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat, 995 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size, 996 number_of_params, Oif_flags, ext_flags, pProcHeader); 997 } 998 999 TRACE("RetVal = 0x%lx\n", RetVal); 1000 return RetVal; 1001 } 1002 1003 #ifdef __x86_64__ 1004 1005 __ASM_GLOBAL_FUNC( NdrClientCall2, 1006 "movq %r8,0x18(%rsp)\n\t" 1007 "movq %r9,0x20(%rsp)\n\t" 1008 "leaq 0x18(%rsp),%r8\n\t" 1009 "xorq %r9,%r9\n\t" 1010 "subq $0x28,%rsp\n\t" 1011 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") 1012 "call " __ASM_NAME("ndr_client_call") "\n\t" 1013 "addq $0x28,%rsp\n\t" 1014 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") 1015 "ret" ); 1016 1017 #else /* __x86_64__ */ 1018 1019 /*********************************************************************** 1020 * NdrClientCall2 [RPCRT4.@] 1021 */ 1022 CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) 1023 { 1024 __ms_va_list args; 1025 LONG_PTR ret; 1026 1027 __ms_va_start( args, format ); 1028 ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL ); 1029 __ms_va_end( args ); 1030 return *(CLIENT_CALL_RETURN *)&ret; 1031 } 1032 1033 #endif /* __x86_64__ */ 1034 1035 /* Calls a function with the specified arguments, restoring the stack 1036 * properly afterwards as we don't know the calling convention of the 1037 * function */ 1038 #if defined __i386__ && defined _MSC_VER 1039 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) 1040 { 1041 __asm 1042 { 1043 push ebp 1044 mov ebp, esp 1045 push edi ; Save registers 1046 push esi 1047 mov eax, [ebp+16] ; Get stack size 1048 sub esp, eax ; Make room in stack for arguments 1049 and esp, 0xFFFFFFF0 1050 mov edi, esp 1051 mov ecx, eax 1052 mov esi, [ebp+12] 1053 shr ecx, 2 1054 cld 1055 rep movsd ; Copy dword blocks 1056 call [ebp+8] ; Call function 1057 lea esp, [ebp-8] ; Restore stack 1058 pop esi ; Restore registers 1059 pop edi 1060 pop ebp 1061 ret 1062 } 1063 } 1064 #elif defined __i386__ && defined __GNUC__ 1065 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); 1066 __ASM_GLOBAL_FUNC(call_server_func, 1067 "pushl %ebp\n\t" 1068 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") 1069 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") 1070 "movl %esp,%ebp\n\t" 1071 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") 1072 "pushl %edi\n\t" /* Save registers */ 1073 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t") 1074 "pushl %esi\n\t" 1075 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") 1076 "movl 16(%ebp), %eax\n\t" /* Get stack size */ 1077 "subl %eax, %esp\n\t" /* Make room in stack for arguments */ 1078 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ 1079 "movl %esp, %edi\n\t" 1080 "movl %eax, %ecx\n\t" 1081 "movl 12(%ebp), %esi\n\t" 1082 "shrl $2, %ecx\n\t" /* divide by 4 */ 1083 "cld\n\t" 1084 "rep; movsl\n\t" /* Copy dword blocks */ 1085 "call *8(%ebp)\n\t" /* Call function */ 1086 "leal -8(%ebp), %esp\n\t" /* Restore stack */ 1087 "popl %esi\n\t" /* Restore registers */ 1088 __ASM_CFI(".cfi_same_value %esi\n\t") 1089 "popl %edi\n\t" 1090 __ASM_CFI(".cfi_same_value %edi\n\t") 1091 "popl %ebp\n\t" 1092 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") 1093 __ASM_CFI(".cfi_same_value %ebp\n\t") 1094 "ret" ) 1095 #elif defined __x86_64__ 1096 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); 1097 __ASM_GLOBAL_FUNC( call_server_func, 1098 "pushq %rbp\n\t" 1099 __ASM_SEH(".seh_pushreg %rbp\n\t") 1100 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") 1101 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") 1102 "movq %rsp,%rbp\n\t" 1103 __ASM_SEH(".seh_setframe %rbp,0\n\t") 1104 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") 1105 "pushq %rsi\n\t" 1106 __ASM_SEH(".seh_pushreg %rsi\n\t") 1107 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t") 1108 "pushq %rdi\n\t" 1109 __ASM_SEH(".seh_pushreg %rdi\n\t") 1110 __ASM_SEH(".seh_endprologue\n\t") 1111 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t") 1112 "movq %rcx,%rax\n\t" /* function to call */ 1113 "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */ 1114 "cmpq %rcx,%r8\n\t" 1115 "cmovgq %r8,%rcx\n\t" 1116 "subq %rcx,%rsp\n\t" 1117 "andq $~15,%rsp\n\t" 1118 "movq %r8,%rcx\n\t" 1119 "shrq $3,%rcx\n\t" 1120 "movq %rsp,%rdi\n\t" 1121 "movq %rdx,%rsi\n\t" 1122 "rep; movsq\n\t" /* copy arguments */ 1123 "movq 0(%rsp),%rcx\n\t" 1124 "movq 8(%rsp),%rdx\n\t" 1125 "movq 16(%rsp),%r8\n\t" 1126 "movq 24(%rsp),%r9\n\t" 1127 "movq 0(%rsp),%xmm0\n\t" 1128 "movq 8(%rsp),%xmm1\n\t" 1129 "movq 16(%rsp),%xmm2\n\t" 1130 "movq 24(%rsp),%xmm3\n\t" 1131 "callq *%rax\n\t" 1132 "leaq -16(%rbp),%rsp\n\t" /* restore stack */ 1133 "popq %rdi\n\t" 1134 __ASM_CFI(".cfi_same_value %rdi\n\t") 1135 "popq %rsi\n\t" 1136 __ASM_CFI(".cfi_same_value %rsi\n\t") 1137 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") 1138 "popq %rbp\n\t" 1139 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") 1140 __ASM_CFI(".cfi_same_value %rbp\n\t") 1141 "ret") 1142 #elif defined __arm__ 1143 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size); 1144 __ASM_GLOBAL_FUNC( call_server_func, 1145 ".arm\n\t" 1146 "push {r4, r5, LR}\n\t" 1147 "mov r4, r0\n\t" 1148 "mov r5, SP\n\t" 1149 "lsr r3, r2, #2\n\t" 1150 "cmp r3, #0\n\t" 1151 "beq 5f\n\t" 1152 "sub SP, SP, r2\n\t" 1153 "tst r3, #1\n\t" 1154 "subeq SP, SP, #4\n\t" 1155 "1:\tsub r2, r2, #4\n\t" 1156 "ldr r0, [r1, r2]\n\t" 1157 "str r0, [SP, r2]\n\t" 1158 "cmp r2, #0\n\t" 1159 "bgt 1b\n\t" 1160 "cmp r3, #1\n\t" 1161 "bgt 2f\n\t" 1162 "pop {r0}\n\t" 1163 "b 5f\n\t" 1164 "2:\tcmp r3, #2\n\t" 1165 "bgt 3f\n\t" 1166 "pop {r0-r1}\n\t" 1167 "b 5f\n\t" 1168 "3:\tcmp r3, #3\n\t" 1169 "bgt 4f\n\t" 1170 "pop {r0-r2}\n\t" 1171 "b 5f\n\t" 1172 "4:\tpop {r0-r3}\n\t" 1173 "5:\tblx r4\n\t" 1174 "mov SP, r5\n\t" 1175 "pop {r4, r5, PC}" ) 1176 #elif defined __aarch64__ 1177 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size); 1178 __ASM_GLOBAL_FUNC( call_server_func, 1179 "stp x29, x30, [sp, #-16]!\n\t" 1180 "mov x29, sp\n\t" 1181 "add x3, x2, #15\n\t" 1182 "lsr x3, x3, #4\n\t" 1183 "sub sp, sp, x3, lsl #4\n\t" 1184 "cbz x2, 2f\n" 1185 "1:\tsub x2, x2, #8\n\t" 1186 "ldr x4, [x1, x2]\n\t" 1187 "str x4, [sp, x2]\n\t" 1188 "cbnz x2, 1b\n" 1189 "2:\tmov x8, x0\n\t" 1190 "cbz x3, 3f\n\t" 1191 "ldp x0, x1, [sp], #16\n\t" 1192 "cmp x3, #1\n\t" 1193 "b.le 3f\n\t" 1194 "ldp x2, x3, [sp], #16\n\t" 1195 "cmp x3, #2\n\t" 1196 "b.le 3f\n\t" 1197 "ldp x4, x5, [sp], #16\n\t" 1198 "cmp x3, #3\n\t" 1199 "b.le 3f\n\t" 1200 "ldp x6, x7, [sp], #16\n" 1201 "3:\tblr x8\n\t" 1202 "mov sp, x29\n\t" 1203 "ldp x29, x30, [sp], #16\n\t" 1204 "ret" ) 1205 #else 1206 #warning call_server_func not implemented for your architecture 1207 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) 1208 { 1209 FIXME("Not implemented for your architecture\n"); 1210 return 0; 1211 } 1212 #endif 1213 1214 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, 1215 PFORMAT_STRING pFormat, enum stubless_phase phase, 1216 unsigned short number_of_params) 1217 { 1218 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; 1219 unsigned int i; 1220 LONG_PTR *retval_ptr = NULL; 1221 1222 for (i = 0; i < number_of_params; i++) 1223 { 1224 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; 1225 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; 1226 1227 TRACE("param[%d]: %p -> %p type %02x %s\n", i, 1228 pArg, *(unsigned char **)pArg, 1229 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, 1230 debugstr_PROC_PF( params[i].attr )); 1231 1232 switch (phase) 1233 { 1234 case STUBLESS_MARSHAL: 1235 if (params[i].attr.IsOut || params[i].attr.IsReturn) 1236 call_marshaller(pStubMsg, pArg, ¶ms[i]); 1237 break; 1238 case STUBLESS_MUSTFREE: 1239 if (params[i].attr.MustFree) 1240 { 1241 call_freer(pStubMsg, pArg, ¶ms[i]); 1242 } 1243 break; 1244 case STUBLESS_FREE: 1245 if (params[i].attr.ServerAllocSize) 1246 { 1247 HeapFree(GetProcessHeap(), 0, *(void **)pArg); 1248 } 1249 else if (param_needs_alloc(params[i].attr) && 1250 (!params[i].attr.MustFree || params[i].attr.IsSimpleRef)) 1251 { 1252 if (*pTypeFormat != FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg); 1253 } 1254 break; 1255 case STUBLESS_INITOUT: 1256 if (param_needs_alloc(params[i].attr) && !params[i].attr.ServerAllocSize) 1257 { 1258 if (*pTypeFormat == FC_BIND_CONTEXT) 1259 { 1260 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat); 1261 *(void **)pArg = NDRSContextValue(ctxt); 1262 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)NDRSContextValue(ctxt); 1263 } 1264 else 1265 { 1266 DWORD size = calc_arg_size(pStubMsg, pTypeFormat); 1267 if (size) 1268 { 1269 *(void **)pArg = NdrAllocate(pStubMsg, size); 1270 memset(*(void **)pArg, 0, size); 1271 } 1272 } 1273 } 1274 if (!retval_ptr && params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg; 1275 break; 1276 case STUBLESS_UNMARSHAL: 1277 if (params[i].attr.ServerAllocSize) 1278 *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1279 params[i].attr.ServerAllocSize * 8); 1280 1281 if (params[i].attr.IsIn) 1282 call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); 1283 break; 1284 case STUBLESS_CALCSIZE: 1285 if (params[i].attr.IsOut || params[i].attr.IsReturn) 1286 call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); 1287 break; 1288 default: 1289 RpcRaiseException(RPC_S_INTERNAL_ERROR); 1290 } 1291 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); 1292 } 1293 return retval_ptr; 1294 } 1295 1296 /*********************************************************************** 1297 * NdrStubCall2 [RPCRT4.@] 1298 * 1299 * Unmarshals [in] parameters, calls either a method in an object or a server 1300 * function, marshals any [out] parameters and frees any allocated data. 1301 * 1302 * NOTES 1303 * Used by stubless MIDL-generated code. 1304 */ 1305 LONG WINAPI NdrStubCall2( 1306 struct IRpcStubBuffer * pThis, 1307 struct IRpcChannelBuffer * pChannel, 1308 PRPC_MESSAGE pRpcMsg, 1309 DWORD * pdwStubPhase) 1310 { 1311 const MIDL_SERVER_INFO *pServerInfo; 1312 const MIDL_STUB_DESC *pStubDesc; 1313 PFORMAT_STRING pFormat; 1314 MIDL_STUB_MESSAGE stubMsg; 1315 /* pointer to start of stack to pass into stub implementation */ 1316 unsigned char * args; 1317 /* size of stack */ 1318 unsigned short stack_size; 1319 /* number of parameters. optional for client to give it to us */ 1320 unsigned int number_of_params; 1321 /* cache of Oif_flags from v2 procedure header */ 1322 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 1323 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 1324 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 1325 /* the type of pass we are currently doing */ 1326 enum stubless_phase phase; 1327 /* header for procedure string */ 1328 const NDR_PROC_HEADER *pProcHeader; 1329 /* location to put retval into */ 1330 LONG_PTR *retval_ptr = NULL; 1331 /* correlation cache */ 1332 ULONG_PTR NdrCorrCache[256]; 1333 1334 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); 1335 1336 if (pThis) 1337 pServerInfo = CStdStubBuffer_GetServerInfo(pThis); 1338 else 1339 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; 1340 1341 pStubDesc = pServerInfo->pStubDesc; 1342 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; 1343 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1344 1345 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 1346 1347 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1348 { 1349 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1350 stack_size = header_rpc->stack_size; 1351 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1352 1353 } 1354 else 1355 { 1356 stack_size = pProcHeader->stack_size; 1357 pFormat += sizeof(NDR_PROC_HEADER); 1358 } 1359 1360 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1361 1362 /* binding */ 1363 switch (pProcHeader->handle_type) 1364 { 1365 /* explicit binding: parse additional section */ 1366 case 0: 1367 switch (*pFormat) /* handle_type */ 1368 { 1369 case FC_BIND_PRIMITIVE: /* explicit primitive */ 1370 pFormat += sizeof(NDR_EHD_PRIMITIVE); 1371 break; 1372 case FC_BIND_GENERIC: /* explicit generic */ 1373 pFormat += sizeof(NDR_EHD_GENERIC); 1374 break; 1375 case FC_BIND_CONTEXT: /* explicit context */ 1376 pFormat += sizeof(NDR_EHD_CONTEXT); 1377 break; 1378 default: 1379 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 1380 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1381 } 1382 break; 1383 case FC_BIND_GENERIC: /* implicit generic */ 1384 case FC_BIND_PRIMITIVE: /* implicit primitive */ 1385 case FC_CALLBACK_HANDLE: /* implicit callback */ 1386 case FC_AUTO_HANDLE: /* implicit auto handle */ 1387 break; 1388 default: 1389 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 1390 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1391 } 1392 1393 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1394 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); 1395 else 1396 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); 1397 1398 /* create the full pointer translation tables, if requested */ 1399 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1400 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); 1401 1402 /* store the RPC flags away */ 1403 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1404 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 1405 1406 /* use alternate memory allocation routines */ 1407 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 1408 #if 0 1409 NdrRpcSsEnableAllocate(&stubMsg); 1410 #else 1411 FIXME("Set RPCSS memory allocation routines\n"); 1412 #endif 1413 1414 TRACE("allocating memory for stack of size %x\n", stack_size); 1415 1416 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); 1417 stubMsg.StackTop = args; /* used by conformance of top-level objects */ 1418 1419 /* add the implicit This pointer as the first arg to the function if we 1420 * are calling an object method */ 1421 if (pThis) 1422 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; 1423 1424 if (is_oicf_stubdesc(pStubDesc)) 1425 { 1426 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 1427 1428 Oif_flags = pOIFHeader->Oi2Flags; 1429 number_of_params = pOIFHeader->number_of_params; 1430 1431 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 1432 1433 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 1434 1435 if (Oif_flags.HasExtensions) 1436 { 1437 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 1438 ext_flags = pExtensions->Flags2; 1439 pFormat += pExtensions->Size; 1440 } 1441 1442 if (Oif_flags.HasPipes) 1443 { 1444 FIXME("pipes not supported yet\n"); 1445 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 1446 /* init pipes package */ 1447 /* NdrPipesInitialize(...) */ 1448 } 1449 if (ext_flags.HasNewCorrDesc) 1450 { 1451 /* initialize extra correlation package */ 1452 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0); 1453 if (ext_flags.Unused & 0x2) /* has range on conformance */ 1454 stubMsg.CorrDespIncrement = 12; 1455 } 1456 } 1457 else 1458 { 1459 pFormat = convert_old_args( &stubMsg, pFormat, stack_size, 1460 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 1461 /* reuse the correlation cache, it's not needed for v1 format */ 1462 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); 1463 } 1464 1465 /* convert strings, floating point values and endianness into our 1466 * preferred format */ 1467 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 1468 NdrConvert(&stubMsg, pFormat); 1469 1470 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) 1471 { 1472 TRACE("phase = %d\n", phase); 1473 switch (phase) 1474 { 1475 case STUBLESS_CALLSERVER: 1476 /* call the server function */ 1477 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) 1478 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); 1479 else 1480 { 1481 SERVER_ROUTINE func; 1482 LONG_PTR retval; 1483 1484 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1485 { 1486 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; 1487 func = vtbl[pRpcMsg->ProcNum]; 1488 } 1489 else 1490 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; 1491 1492 /* FIXME: what happens with return values that don't fit into a single register on x86? */ 1493 retval = call_server_func(func, args, stack_size); 1494 1495 if (retval_ptr) 1496 { 1497 TRACE("stub implementation returned 0x%lx\n", retval); 1498 *retval_ptr = retval; 1499 } 1500 else 1501 TRACE("void stub implementation\n"); 1502 } 1503 1504 stubMsg.Buffer = NULL; 1505 stubMsg.BufferLength = 0; 1506 1507 break; 1508 case STUBLESS_GETBUFFER: 1509 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1510 NdrStubGetBuffer(pThis, pChannel, &stubMsg); 1511 else 1512 { 1513 RPC_STATUS Status; 1514 1515 pRpcMsg->BufferLength = stubMsg.BufferLength; 1516 /* allocate buffer for [out] and [ret] params */ 1517 Status = I_RpcGetBuffer(pRpcMsg); 1518 if (Status) 1519 RpcRaiseException(Status); 1520 stubMsg.Buffer = pRpcMsg->Buffer; 1521 } 1522 break; 1523 case STUBLESS_UNMARSHAL: 1524 case STUBLESS_INITOUT: 1525 case STUBLESS_CALCSIZE: 1526 case STUBLESS_MARSHAL: 1527 case STUBLESS_MUSTFREE: 1528 case STUBLESS_FREE: 1529 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params); 1530 break; 1531 default: 1532 ERR("shouldn't reach here. phase %d\n", phase); 1533 break; 1534 } 1535 } 1536 1537 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); 1538 1539 if (ext_flags.HasNewCorrDesc) 1540 { 1541 /* free extra correlation package */ 1542 NdrCorrelationFree(&stubMsg); 1543 } 1544 1545 if (Oif_flags.HasPipes) 1546 { 1547 /* NdrPipesDone(...) */ 1548 } 1549 1550 /* free the full pointer translation tables */ 1551 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1552 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); 1553 1554 /* free server function stack */ 1555 HeapFree(GetProcessHeap(), 0, args); 1556 1557 return S_OK; 1558 } 1559 1560 /*********************************************************************** 1561 * NdrServerCall2 [RPCRT4.@] 1562 */ 1563 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) 1564 { 1565 DWORD dwPhase; 1566 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); 1567 } 1568 1569 /*********************************************************************** 1570 * NdrStubCall [RPCRT4.@] 1571 */ 1572 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel, 1573 PRPC_MESSAGE msg, DWORD *phase ) 1574 { 1575 return NdrStubCall2( This, channel, msg, phase ); 1576 } 1577 1578 /*********************************************************************** 1579 * NdrServerCall [RPCRT4.@] 1580 */ 1581 void WINAPI NdrServerCall( PRPC_MESSAGE msg ) 1582 { 1583 DWORD phase; 1584 NdrStubCall( NULL, NULL, msg, &phase ); 1585 } 1586 1587 /*********************************************************************** 1588 * NdrServerCallAll [RPCRT4.@] 1589 */ 1590 void WINAPI NdrServerCallAll( PRPC_MESSAGE msg ) 1591 { 1592 FIXME("%p stub\n", msg); 1593 } 1594 1595 /* Helper for ndr_async_client_call, to factor out the part that may or may not be 1596 * guarded by a try/except block. */ 1597 static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) 1598 { 1599 /* pointer to start of stack where arguments start */ 1600 PRPC_MESSAGE pRpcMsg; 1601 PMIDL_STUB_MESSAGE pStubMsg; 1602 RPC_ASYNC_STATE *pAsync; 1603 struct async_call_data *async_call_data; 1604 /* procedure number */ 1605 unsigned short procedure_number; 1606 /* cache of Oif_flags from v2 procedure header */ 1607 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 1608 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 1609 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 1610 /* header for procedure string */ 1611 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1612 RPC_STATUS status; 1613 1614 /* Later NDR language versions probably won't be backwards compatible */ 1615 if (pStubDesc->Version > 0x50002) 1616 { 1617 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); 1618 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); 1619 } 1620 1621 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); 1622 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY); 1623 async_call_data->pProcHeader = pProcHeader; 1624 1625 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); 1626 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1); 1627 1628 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1629 { 1630 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1631 async_call_data->stack_size = header_rpc->stack_size; 1632 procedure_number = header_rpc->proc_num; 1633 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1634 } 1635 else 1636 { 1637 async_call_data->stack_size = pProcHeader->stack_size; 1638 procedure_number = pProcHeader->proc_num; 1639 pFormat += sizeof(NDR_PROC_HEADER); 1640 } 1641 TRACE("stack size: 0x%x\n", async_call_data->stack_size); 1642 TRACE("proc num: %d\n", procedure_number); 1643 1644 /* create the full pointer translation tables, if requested */ 1645 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1646 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); 1647 1648 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1649 { 1650 ERR("objects not supported\n"); 1651 I_RpcFree(async_call_data); 1652 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1653 } 1654 1655 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number); 1656 1657 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1658 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); 1659 1660 /* needed for conformance of top-level objects */ 1661 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size); 1662 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size); 1663 1664 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop; 1665 pAsync->StubInfo = async_call_data; 1666 async_call_data->pHandleFormat = pFormat; 1667 1668 TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType); 1669 1670 pFormat += get_handle_desc_size(pProcHeader, pFormat); 1671 async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat); 1672 if (!async_call_data->hBinding) return; 1673 1674 if (is_oicf_stubdesc(pStubDesc)) 1675 { 1676 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = 1677 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 1678 1679 Oif_flags = pOIFHeader->Oi2Flags; 1680 async_call_data->number_of_params = pOIFHeader->number_of_params; 1681 1682 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 1683 1684 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 1685 1686 if (Oif_flags.HasExtensions) 1687 { 1688 const NDR_PROC_HEADER_EXTS *pExtensions = 1689 (const NDR_PROC_HEADER_EXTS *)pFormat; 1690 ext_flags = pExtensions->Flags2; 1691 pFormat += pExtensions->Size; 1692 } 1693 } 1694 else 1695 { 1696 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size, 1697 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 1698 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 1699 &async_call_data->number_of_params ); 1700 } 1701 1702 async_call_data->pParamFormat = pFormat; 1703 1704 pStubMsg->BufferLength = 0; 1705 1706 /* store the RPC flags away */ 1707 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1708 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 1709 1710 /* use alternate memory allocation routines */ 1711 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 1712 NdrRpcSmSetClientToOsf(pStubMsg); 1713 1714 if (Oif_flags.HasPipes) 1715 { 1716 FIXME("pipes not supported yet\n"); 1717 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 1718 /* init pipes package */ 1719 /* NdrPipesInitialize(...) */ 1720 } 1721 if (ext_flags.HasNewCorrDesc) 1722 { 1723 /* initialize extra correlation package */ 1724 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); 1725 if (ext_flags.Unused & 0x2) /* has range on conformance */ 1726 pStubMsg->CorrDespIncrement = 12; 1727 } 1728 1729 /* order of phases: 1730 * 1. CALCSIZE - calculate the buffer size 1731 * 2. GETBUFFER - allocate the buffer 1732 * 3. MARSHAL - marshal [in] params into the buffer 1733 * 4. SENDRECEIVE - send buffer 1734 * Then in NdrpCompleteAsyncClientCall: 1735 * 1. SENDRECEIVE - receive buffer 1736 * 2. UNMARSHAL - unmarshal [out] params from buffer 1737 */ 1738 1739 /* 1. CALCSIZE */ 1740 TRACE( "CALCSIZE\n" ); 1741 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL); 1742 1743 /* 2. GETBUFFER */ 1744 TRACE( "GETBUFFER\n" ); 1745 if (Oif_flags.HasPipes) 1746 /* NdrGetPipeBuffer(...) */ 1747 FIXME("pipes not supported yet\n"); 1748 else 1749 { 1750 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1751 #if 0 1752 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 1753 #else 1754 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 1755 #endif 1756 else 1757 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 1758 } 1759 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1760 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync); 1761 if (status != RPC_S_OK) 1762 RpcRaiseException(status); 1763 1764 /* 3. MARSHAL */ 1765 TRACE( "MARSHAL\n" ); 1766 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL); 1767 1768 /* 4. SENDRECEIVE */ 1769 TRACE( "SEND\n" ); 1770 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1771 /* send the [in] params only */ 1772 if (Oif_flags.HasPipes) 1773 /* NdrPipesSend(...) */ 1774 FIXME("pipes not supported yet\n"); 1775 else 1776 { 1777 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1778 #if 0 1779 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 1780 #else 1781 FIXME("using auto handle - call NdrNsSend when it gets implemented\n"); 1782 #endif 1783 else 1784 { 1785 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer; 1786 status = I_RpcSend(pStubMsg->RpcMsg); 1787 if (status != RPC_S_OK) 1788 RpcRaiseException(status); 1789 } 1790 } 1791 } 1792 1793 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, 1794 void **stack_top ) 1795 { 1796 LONG_PTR ret = 0; 1797 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1798 1799 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); 1800 1801 if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT) 1802 { 1803 __TRY 1804 { 1805 do_ndr_async_client_call( pStubDesc, pFormat, stack_top ); 1806 } 1807 __EXCEPT_ALL 1808 { 1809 FIXME("exception %x during ndr_async_client_call()\n", GetExceptionCode()); 1810 ret = GetExceptionCode(); 1811 } 1812 __ENDTRY 1813 } 1814 else 1815 do_ndr_async_client_call( pStubDesc, pFormat, stack_top); 1816 1817 TRACE("returning %ld\n", ret); 1818 return ret; 1819 } 1820 1821 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) 1822 { 1823 /* pointer to start of stack where arguments start */ 1824 PMIDL_STUB_MESSAGE pStubMsg; 1825 struct async_call_data *async_call_data; 1826 /* header for procedure string */ 1827 const NDR_PROC_HEADER * pProcHeader; 1828 RPC_STATUS status = RPC_S_OK; 1829 1830 if (!pAsync->StubInfo) 1831 return RPC_S_INVALID_ASYNC_HANDLE; 1832 1833 async_call_data = pAsync->StubInfo; 1834 pStubMsg = async_call_data->pStubMsg; 1835 pProcHeader = async_call_data->pProcHeader; 1836 1837 /* order of phases: 1838 * 1. CALCSIZE - calculate the buffer size 1839 * 2. GETBUFFER - allocate the buffer 1840 * 3. MARSHAL - marshal [in] params into the buffer 1841 * 4. SENDRECEIVE - send buffer 1842 * Then in NdrpCompleteAsyncClientCall: 1843 * 1. SENDRECEIVE - receive buffer 1844 * 2. UNMARSHAL - unmarshal [out] params from buffer 1845 */ 1846 1847 /* 1. SENDRECEIVE */ 1848 TRACE( "RECEIVE\n" ); 1849 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1850 /* receive the [out] params */ 1851 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1852 #if 0 1853 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 1854 #else 1855 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n"); 1856 #endif 1857 else 1858 { 1859 status = I_RpcReceive(pStubMsg->RpcMsg); 1860 if (status != RPC_S_OK) 1861 goto cleanup; 1862 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength; 1863 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; 1864 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; 1865 pStubMsg->Buffer = pStubMsg->BufferStart; 1866 } 1867 1868 /* convert strings, floating point values and endianness into our 1869 * preferred format */ 1870 #if 0 1871 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 1872 NdrConvert(pStubMsg, pFormat); 1873 #endif 1874 1875 /* 2. UNMARSHAL */ 1876 TRACE( "UNMARSHAL\n" ); 1877 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL, 1878 NULL, async_call_data->number_of_params, Reply); 1879 1880 cleanup: 1881 if (pStubMsg->fHasNewCorrDesc) 1882 { 1883 /* free extra correlation package */ 1884 NdrCorrelationFree(pStubMsg); 1885 } 1886 1887 /* free the full pointer translation tables */ 1888 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1889 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); 1890 1891 /* free marshalling buffer */ 1892 NdrFreeBuffer(pStubMsg); 1893 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding); 1894 1895 I_RpcFree(pStubMsg->StackTop); 1896 I_RpcFree(async_call_data); 1897 1898 TRACE("-- 0x%x\n", status); 1899 return status; 1900 } 1901 1902 #ifdef __x86_64__ 1903 1904 __ASM_GLOBAL_FUNC( NdrAsyncClientCall, 1905 "subq $0x28,%rsp\n\t" 1906 __ASM_SEH(".seh_stackalloc 0x28\n\t") 1907 __ASM_SEH(".seh_endprologue\n\t") 1908 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") 1909 "movq %r8,0x40(%rsp)\n\t" 1910 "movq %r9,0x48(%rsp)\n\t" 1911 "leaq 0x40(%rsp),%r8\n\t" 1912 "call " __ASM_NAME("ndr_async_client_call") "\n\t" 1913 "addq $0x28,%rsp\n\t" 1914 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") 1915 "ret" ); 1916 1917 #else /* __x86_64__ */ 1918 1919 /*********************************************************************** 1920 * NdrAsyncClientCall [RPCRT4.@] 1921 */ 1922 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) 1923 { 1924 __ms_va_list args; 1925 LONG_PTR ret; 1926 1927 __ms_va_start( args, format ); 1928 ret = ndr_async_client_call( desc, format, va_arg( args, void ** )); 1929 __ms_va_end( args ); 1930 return *(CLIENT_CALL_RETURN *)&ret; 1931 } 1932 1933 #endif /* __x86_64__ */ 1934 1935 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis, 1936 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, 1937 DWORD * pdwStubPhase) 1938 { 1939 FIXME("unimplemented, expect crash!\n"); 1940 return 0; 1941 } 1942 1943 void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg) 1944 { 1945 const MIDL_SERVER_INFO *pServerInfo; 1946 const MIDL_STUB_DESC *pStubDesc; 1947 PFORMAT_STRING pFormat; 1948 /* pointer to start of stack to pass into stub implementation */ 1949 unsigned char *args; 1950 /* header for procedure string */ 1951 const NDR_PROC_HEADER *pProcHeader; 1952 struct async_call_data *async_call_data; 1953 PRPC_ASYNC_STATE pAsync; 1954 RPC_STATUS status; 1955 1956 TRACE("%p\n", pRpcMsg); 1957 1958 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; 1959 1960 pStubDesc = pServerInfo->pStubDesc; 1961 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; 1962 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1963 1964 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 1965 1966 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); 1967 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY); 1968 async_call_data->pProcHeader = pProcHeader; 1969 1970 async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); 1971 *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg; 1972 1973 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1974 { 1975 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1976 async_call_data->stack_size = header_rpc->stack_size; 1977 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1978 } 1979 else 1980 { 1981 async_call_data->stack_size = pProcHeader->stack_size; 1982 pFormat += sizeof(NDR_PROC_HEADER); 1983 } 1984 1985 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1986 1987 /* binding */ 1988 switch (pProcHeader->handle_type) 1989 { 1990 /* explicit binding: parse additional section */ 1991 case 0: 1992 switch (*pFormat) /* handle_type */ 1993 { 1994 case FC_BIND_PRIMITIVE: /* explicit primitive */ 1995 pFormat += sizeof(NDR_EHD_PRIMITIVE); 1996 break; 1997 case FC_BIND_GENERIC: /* explicit generic */ 1998 pFormat += sizeof(NDR_EHD_GENERIC); 1999 break; 2000 case FC_BIND_CONTEXT: /* explicit context */ 2001 pFormat += sizeof(NDR_EHD_CONTEXT); 2002 break; 2003 default: 2004 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 2005 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2006 } 2007 break; 2008 case FC_BIND_GENERIC: /* implicit generic */ 2009 case FC_BIND_PRIMITIVE: /* implicit primitive */ 2010 case FC_CALLBACK_HANDLE: /* implicit callback */ 2011 case FC_AUTO_HANDLE: /* implicit auto handle */ 2012 break; 2013 default: 2014 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 2015 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2016 } 2017 2018 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 2019 { 2020 ERR("objects not supported\n"); 2021 I_RpcFree(async_call_data); 2022 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2023 } 2024 2025 NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc); 2026 2027 /* create the full pointer translation tables, if requested */ 2028 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 2029 async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER); 2030 2031 /* use alternate memory allocation routines */ 2032 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 2033 #if 0 2034 NdrRpcSsEnableAllocate(&stubMsg); 2035 #else 2036 FIXME("Set RPCSS memory allocation routines\n"); 2037 #endif 2038 2039 TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size); 2040 2041 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, async_call_data->stack_size); 2042 async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */ 2043 2044 pAsync = I_RpcAllocate(sizeof(*pAsync)); 2045 if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY); 2046 2047 status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync)); 2048 if (status != RPC_S_OK) 2049 RpcRaiseException(status); 2050 2051 pAsync->StubInfo = async_call_data; 2052 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); 2053 2054 /* add the implicit pAsync pointer as the first arg to the function */ 2055 *(void **)args = pAsync; 2056 2057 if (is_oicf_stubdesc(pStubDesc)) 2058 { 2059 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 2060 /* cache of Oif_flags from v2 procedure header */ 2061 INTERPRETER_OPT_FLAGS Oif_flags; 2062 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 2063 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 2064 2065 Oif_flags = pOIFHeader->Oi2Flags; 2066 async_call_data->number_of_params = pOIFHeader->number_of_params; 2067 2068 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 2069 2070 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 2071 2072 if (Oif_flags.HasExtensions) 2073 { 2074 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 2075 ext_flags = pExtensions->Flags2; 2076 pFormat += pExtensions->Size; 2077 } 2078 2079 if (Oif_flags.HasPipes) 2080 { 2081 FIXME("pipes not supported yet\n"); 2082 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 2083 /* init pipes package */ 2084 /* NdrPipesInitialize(...) */ 2085 } 2086 if (ext_flags.HasNewCorrDesc) 2087 { 2088 /* initialize extra correlation package */ 2089 NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); 2090 if (ext_flags.Unused & 0x2) /* has range on conformance */ 2091 async_call_data->pStubMsg->CorrDespIncrement = 12; 2092 } 2093 } 2094 else 2095 { 2096 pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size, 2097 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 2098 /* reuse the correlation cache, it's not needed for v1 format */ 2099 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params ); 2100 } 2101 2102 /* convert strings, floating point values and endianness into our 2103 * preferred format */ 2104 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 2105 NdrConvert(async_call_data->pStubMsg, pFormat); 2106 2107 async_call_data->pHandleFormat = pFormat; 2108 2109 /* 1. UNMARSHAL */ 2110 TRACE("UNMARSHAL\n"); 2111 stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params); 2112 2113 /* 2. INITOUT */ 2114 TRACE("INITOUT\n"); 2115 async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params); 2116 2117 /* 3. CALLSERVER */ 2118 TRACE("CALLSERVER\n"); 2119 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) 2120 pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg); 2121 else 2122 call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size); 2123 } 2124 2125 RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply) 2126 { 2127 /* pointer to start of stack where arguments start */ 2128 PMIDL_STUB_MESSAGE pStubMsg; 2129 struct async_call_data *async_call_data; 2130 /* the type of pass we are currently doing */ 2131 enum stubless_phase phase; 2132 RPC_STATUS status = RPC_S_OK; 2133 2134 if (!pAsync->StubInfo) 2135 return RPC_S_INVALID_ASYNC_HANDLE; 2136 2137 async_call_data = pAsync->StubInfo; 2138 pStubMsg = async_call_data->pStubMsg; 2139 2140 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); 2141 2142 if (async_call_data->retval_ptr) 2143 { 2144 TRACE("stub implementation returned 0x%lx\n", *(LONG_PTR *)Reply); 2145 *async_call_data->retval_ptr = *(LONG_PTR *)Reply; 2146 } 2147 else 2148 TRACE("void stub implementation\n"); 2149 2150 for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++) 2151 { 2152 TRACE("phase = %d\n", phase); 2153 switch (phase) 2154 { 2155 case STUBLESS_GETBUFFER: 2156 if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC) 2157 { 2158 ERR("objects not supported\n"); 2159 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); 2160 I_RpcFree(async_call_data); 2161 I_RpcFree(pAsync); 2162 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2163 } 2164 else 2165 { 2166 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; 2167 /* allocate buffer for [out] and [ret] params */ 2168 status = I_RpcGetBuffer(pStubMsg->RpcMsg); 2169 if (status) 2170 RpcRaiseException(status); 2171 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; 2172 } 2173 break; 2174 2175 case STUBLESS_CALCSIZE: 2176 case STUBLESS_MARSHAL: 2177 case STUBLESS_MUSTFREE: 2178 case STUBLESS_FREE: 2179 stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params); 2180 break; 2181 default: 2182 ERR("shouldn't reach here. phase %d\n", phase); 2183 break; 2184 } 2185 } 2186 2187 #if 0 /* FIXME */ 2188 if (ext_flags.HasNewCorrDesc) 2189 { 2190 /* free extra correlation package */ 2191 NdrCorrelationFree(pStubMsg); 2192 } 2193 2194 if (Oif_flags.HasPipes) 2195 { 2196 /* NdrPipesDone(...) */ 2197 } 2198 2199 /* free the full pointer translation tables */ 2200 if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 2201 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); 2202 #endif 2203 2204 /* free server function stack */ 2205 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); 2206 I_RpcFree(async_call_data); 2207 I_RpcFree(pAsync); 2208 2209 return S_OK; 2210 } 2211