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 unsigned short BindingHandleOffset = (USHORT)-1; 1334 1335 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); 1336 1337 if (pThis) 1338 pServerInfo = CStdStubBuffer_GetServerInfo(pThis); 1339 else 1340 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; 1341 1342 pStubDesc = pServerInfo->pStubDesc; 1343 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; 1344 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1345 1346 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 1347 1348 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1349 { 1350 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1351 stack_size = header_rpc->stack_size; 1352 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1353 1354 } 1355 else 1356 { 1357 stack_size = pProcHeader->stack_size; 1358 pFormat += sizeof(NDR_PROC_HEADER); 1359 } 1360 1361 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1362 1363 /* binding */ 1364 switch (pProcHeader->handle_type) 1365 { 1366 /* explicit binding: parse additional section */ 1367 case 0: 1368 switch (*pFormat) /* handle_type */ 1369 { 1370 case FC_BIND_PRIMITIVE: /* explicit primitive */ 1371 BindingHandleOffset = ((NDR_EHD_PRIMITIVE*)pFormat)->offset; 1372 pFormat += sizeof(NDR_EHD_PRIMITIVE); 1373 break; 1374 case FC_BIND_GENERIC: /* explicit generic */ 1375 BindingHandleOffset = ((NDR_EHD_GENERIC*)pFormat)->offset; 1376 pFormat += sizeof(NDR_EHD_GENERIC); 1377 break; 1378 case FC_BIND_CONTEXT: /* explicit context */ 1379 BindingHandleOffset = ((NDR_EHD_CONTEXT*)pFormat)->offset; 1380 pFormat += sizeof(NDR_EHD_CONTEXT); 1381 break; 1382 default: 1383 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 1384 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1385 } 1386 break; 1387 case FC_BIND_GENERIC: /* implicit generic */ 1388 case FC_BIND_PRIMITIVE: /* implicit primitive */ 1389 case FC_CALLBACK_HANDLE: /* implicit callback */ 1390 case FC_AUTO_HANDLE: /* implicit auto handle */ 1391 break; 1392 default: 1393 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 1394 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1395 } 1396 1397 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1398 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); 1399 else 1400 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); 1401 1402 /* create the full pointer translation tables, if requested */ 1403 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1404 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); 1405 1406 /* store the RPC flags away */ 1407 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1408 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 1409 1410 /* use alternate memory allocation routines */ 1411 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 1412 #if 0 1413 NdrRpcSsEnableAllocate(&stubMsg); 1414 #else 1415 FIXME("Set RPCSS memory allocation routines\n"); 1416 #endif 1417 1418 TRACE("allocating memory for stack of size %x\n", stack_size); 1419 1420 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); 1421 stubMsg.StackTop = args; /* used by conformance of top-level objects */ 1422 1423 /* add the implicit This pointer as the first arg to the function if we 1424 * are calling an object method */ 1425 if (pThis) 1426 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; 1427 1428 /* add the binding handle to the stack if we are using explicit binding handles */ 1429 if (BindingHandleOffset != (USHORT)-1) 1430 *(RPC_BINDING_HANDLE*)&(args[BindingHandleOffset]) = pRpcMsg->Handle; 1431 1432 if (is_oicf_stubdesc(pStubDesc)) 1433 { 1434 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 1435 1436 Oif_flags = pOIFHeader->Oi2Flags; 1437 number_of_params = pOIFHeader->number_of_params; 1438 1439 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 1440 1441 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 1442 1443 if (Oif_flags.HasExtensions) 1444 { 1445 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 1446 ext_flags = pExtensions->Flags2; 1447 pFormat += pExtensions->Size; 1448 } 1449 1450 if (Oif_flags.HasPipes) 1451 { 1452 FIXME("pipes not supported yet\n"); 1453 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 1454 /* init pipes package */ 1455 /* NdrPipesInitialize(...) */ 1456 } 1457 if (ext_flags.HasNewCorrDesc) 1458 { 1459 /* initialize extra correlation package */ 1460 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0); 1461 if (ext_flags.Unused & 0x2) /* has range on conformance */ 1462 stubMsg.CorrDespIncrement = 12; 1463 } 1464 } 1465 else 1466 { 1467 pFormat = convert_old_args( &stubMsg, pFormat, stack_size, 1468 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 1469 /* reuse the correlation cache, it's not needed for v1 format */ 1470 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); 1471 } 1472 1473 /* convert strings, floating point values and endianness into our 1474 * preferred format */ 1475 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 1476 NdrConvert(&stubMsg, pFormat); 1477 1478 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) 1479 { 1480 TRACE("phase = %d\n", phase); 1481 switch (phase) 1482 { 1483 case STUBLESS_CALLSERVER: 1484 /* call the server function */ 1485 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) 1486 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); 1487 else 1488 { 1489 SERVER_ROUTINE func; 1490 LONG_PTR retval; 1491 1492 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1493 { 1494 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; 1495 func = vtbl[pRpcMsg->ProcNum]; 1496 } 1497 else 1498 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; 1499 1500 /* FIXME: what happens with return values that don't fit into a single register on x86? */ 1501 retval = call_server_func(func, args, stack_size); 1502 1503 if (retval_ptr) 1504 { 1505 TRACE("stub implementation returned 0x%lx\n", retval); 1506 *retval_ptr = retval; 1507 } 1508 else 1509 TRACE("void stub implementation\n"); 1510 } 1511 1512 stubMsg.Buffer = NULL; 1513 stubMsg.BufferLength = 0; 1514 1515 break; 1516 case STUBLESS_GETBUFFER: 1517 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1518 NdrStubGetBuffer(pThis, pChannel, &stubMsg); 1519 else 1520 { 1521 RPC_STATUS Status; 1522 1523 pRpcMsg->BufferLength = stubMsg.BufferLength; 1524 /* allocate buffer for [out] and [ret] params */ 1525 Status = I_RpcGetBuffer(pRpcMsg); 1526 if (Status) 1527 RpcRaiseException(Status); 1528 stubMsg.Buffer = pRpcMsg->Buffer; 1529 } 1530 break; 1531 case STUBLESS_UNMARSHAL: 1532 case STUBLESS_INITOUT: 1533 case STUBLESS_CALCSIZE: 1534 case STUBLESS_MARSHAL: 1535 case STUBLESS_MUSTFREE: 1536 case STUBLESS_FREE: 1537 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params); 1538 break; 1539 default: 1540 ERR("shouldn't reach here. phase %d\n", phase); 1541 break; 1542 } 1543 } 1544 1545 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); 1546 1547 if (ext_flags.HasNewCorrDesc) 1548 { 1549 /* free extra correlation package */ 1550 NdrCorrelationFree(&stubMsg); 1551 } 1552 1553 if (Oif_flags.HasPipes) 1554 { 1555 /* NdrPipesDone(...) */ 1556 } 1557 1558 /* free the full pointer translation tables */ 1559 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1560 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); 1561 1562 /* free server function stack */ 1563 HeapFree(GetProcessHeap(), 0, args); 1564 1565 return S_OK; 1566 } 1567 1568 /*********************************************************************** 1569 * NdrServerCall2 [RPCRT4.@] 1570 */ 1571 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) 1572 { 1573 DWORD dwPhase; 1574 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); 1575 } 1576 1577 /*********************************************************************** 1578 * NdrStubCall [RPCRT4.@] 1579 */ 1580 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel, 1581 PRPC_MESSAGE msg, DWORD *phase ) 1582 { 1583 return NdrStubCall2( This, channel, msg, phase ); 1584 } 1585 1586 /*********************************************************************** 1587 * NdrServerCall [RPCRT4.@] 1588 */ 1589 void WINAPI NdrServerCall( PRPC_MESSAGE msg ) 1590 { 1591 DWORD phase; 1592 NdrStubCall( NULL, NULL, msg, &phase ); 1593 } 1594 1595 /*********************************************************************** 1596 * NdrServerCallAll [RPCRT4.@] 1597 */ 1598 void WINAPI NdrServerCallAll( PRPC_MESSAGE msg ) 1599 { 1600 FIXME("%p stub\n", msg); 1601 } 1602 1603 /* Helper for ndr_async_client_call, to factor out the part that may or may not be 1604 * guarded by a try/except block. */ 1605 static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) 1606 { 1607 /* pointer to start of stack where arguments start */ 1608 PRPC_MESSAGE pRpcMsg; 1609 PMIDL_STUB_MESSAGE pStubMsg; 1610 RPC_ASYNC_STATE *pAsync; 1611 struct async_call_data *async_call_data; 1612 /* procedure number */ 1613 unsigned short procedure_number; 1614 /* cache of Oif_flags from v2 procedure header */ 1615 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 1616 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 1617 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 1618 /* header for procedure string */ 1619 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1620 RPC_STATUS status; 1621 1622 /* Later NDR language versions probably won't be backwards compatible */ 1623 if (pStubDesc->Version > 0x50002) 1624 { 1625 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); 1626 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); 1627 } 1628 1629 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); 1630 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY); 1631 async_call_data->pProcHeader = pProcHeader; 1632 1633 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); 1634 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1); 1635 1636 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1637 { 1638 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1639 async_call_data->stack_size = header_rpc->stack_size; 1640 procedure_number = header_rpc->proc_num; 1641 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1642 } 1643 else 1644 { 1645 async_call_data->stack_size = pProcHeader->stack_size; 1646 procedure_number = pProcHeader->proc_num; 1647 pFormat += sizeof(NDR_PROC_HEADER); 1648 } 1649 TRACE("stack size: 0x%x\n", async_call_data->stack_size); 1650 TRACE("proc num: %d\n", procedure_number); 1651 1652 /* create the full pointer translation tables, if requested */ 1653 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1654 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); 1655 1656 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 1657 { 1658 ERR("objects not supported\n"); 1659 I_RpcFree(async_call_data); 1660 RpcRaiseException(RPC_X_BAD_STUB_DATA); 1661 } 1662 1663 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number); 1664 1665 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1666 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); 1667 1668 /* needed for conformance of top-level objects */ 1669 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size); 1670 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size); 1671 1672 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop; 1673 pAsync->StubInfo = async_call_data; 1674 async_call_data->pHandleFormat = pFormat; 1675 1676 TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType); 1677 1678 pFormat += get_handle_desc_size(pProcHeader, pFormat); 1679 async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat); 1680 if (!async_call_data->hBinding) return; 1681 1682 if (is_oicf_stubdesc(pStubDesc)) 1683 { 1684 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = 1685 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 1686 1687 Oif_flags = pOIFHeader->Oi2Flags; 1688 async_call_data->number_of_params = pOIFHeader->number_of_params; 1689 1690 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 1691 1692 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 1693 1694 if (Oif_flags.HasExtensions) 1695 { 1696 const NDR_PROC_HEADER_EXTS *pExtensions = 1697 (const NDR_PROC_HEADER_EXTS *)pFormat; 1698 ext_flags = pExtensions->Flags2; 1699 pFormat += pExtensions->Size; 1700 } 1701 } 1702 else 1703 { 1704 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size, 1705 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 1706 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 1707 &async_call_data->number_of_params ); 1708 } 1709 1710 async_call_data->pParamFormat = pFormat; 1711 1712 pStubMsg->BufferLength = 0; 1713 1714 /* store the RPC flags away */ 1715 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1716 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 1717 1718 /* use alternate memory allocation routines */ 1719 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 1720 NdrRpcSmSetClientToOsf(pStubMsg); 1721 1722 if (Oif_flags.HasPipes) 1723 { 1724 FIXME("pipes not supported yet\n"); 1725 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 1726 /* init pipes package */ 1727 /* NdrPipesInitialize(...) */ 1728 } 1729 if (ext_flags.HasNewCorrDesc) 1730 { 1731 /* initialize extra correlation package */ 1732 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); 1733 if (ext_flags.Unused & 0x2) /* has range on conformance */ 1734 pStubMsg->CorrDespIncrement = 12; 1735 } 1736 1737 /* order of phases: 1738 * 1. CALCSIZE - calculate the buffer size 1739 * 2. GETBUFFER - allocate the buffer 1740 * 3. MARSHAL - marshal [in] params into the buffer 1741 * 4. SENDRECEIVE - send buffer 1742 * Then in NdrpCompleteAsyncClientCall: 1743 * 1. SENDRECEIVE - receive buffer 1744 * 2. UNMARSHAL - unmarshal [out] params from buffer 1745 */ 1746 1747 /* 1. CALCSIZE */ 1748 TRACE( "CALCSIZE\n" ); 1749 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL); 1750 1751 /* 2. GETBUFFER */ 1752 TRACE( "GETBUFFER\n" ); 1753 if (Oif_flags.HasPipes) 1754 /* NdrGetPipeBuffer(...) */ 1755 FIXME("pipes not supported yet\n"); 1756 else 1757 { 1758 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1759 #if 0 1760 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 1761 #else 1762 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 1763 #endif 1764 else 1765 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 1766 } 1767 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1768 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync); 1769 if (status != RPC_S_OK) 1770 RpcRaiseException(status); 1771 1772 /* 3. MARSHAL */ 1773 TRACE( "MARSHAL\n" ); 1774 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL); 1775 1776 /* 4. SENDRECEIVE */ 1777 TRACE( "SEND\n" ); 1778 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1779 /* send the [in] params only */ 1780 if (Oif_flags.HasPipes) 1781 /* NdrPipesSend(...) */ 1782 FIXME("pipes not supported yet\n"); 1783 else 1784 { 1785 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1786 #if 0 1787 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 1788 #else 1789 FIXME("using auto handle - call NdrNsSend when it gets implemented\n"); 1790 #endif 1791 else 1792 { 1793 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer; 1794 status = I_RpcSend(pStubMsg->RpcMsg); 1795 if (status != RPC_S_OK) 1796 RpcRaiseException(status); 1797 } 1798 } 1799 } 1800 1801 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, 1802 void **stack_top ) 1803 { 1804 LONG_PTR ret = 0; 1805 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1806 1807 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); 1808 1809 if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT) 1810 { 1811 __TRY 1812 { 1813 do_ndr_async_client_call( pStubDesc, pFormat, stack_top ); 1814 } 1815 __EXCEPT_ALL 1816 { 1817 FIXME("exception %x during ndr_async_client_call()\n", GetExceptionCode()); 1818 ret = GetExceptionCode(); 1819 } 1820 __ENDTRY 1821 } 1822 else 1823 do_ndr_async_client_call( pStubDesc, pFormat, stack_top); 1824 1825 TRACE("returning %ld\n", ret); 1826 return ret; 1827 } 1828 1829 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) 1830 { 1831 /* pointer to start of stack where arguments start */ 1832 PMIDL_STUB_MESSAGE pStubMsg; 1833 struct async_call_data *async_call_data; 1834 /* header for procedure string */ 1835 const NDR_PROC_HEADER * pProcHeader; 1836 RPC_STATUS status = RPC_S_OK; 1837 1838 if (!pAsync->StubInfo) 1839 return RPC_S_INVALID_ASYNC_HANDLE; 1840 1841 async_call_data = pAsync->StubInfo; 1842 pStubMsg = async_call_data->pStubMsg; 1843 pProcHeader = async_call_data->pProcHeader; 1844 1845 /* order of phases: 1846 * 1. CALCSIZE - calculate the buffer size 1847 * 2. GETBUFFER - allocate the buffer 1848 * 3. MARSHAL - marshal [in] params into the buffer 1849 * 4. SENDRECEIVE - send buffer 1850 * Then in NdrpCompleteAsyncClientCall: 1851 * 1. SENDRECEIVE - receive buffer 1852 * 2. UNMARSHAL - unmarshal [out] params from buffer 1853 */ 1854 1855 /* 1. SENDRECEIVE */ 1856 TRACE( "RECEIVE\n" ); 1857 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 1858 /* receive the [out] params */ 1859 if (pProcHeader->handle_type == FC_AUTO_HANDLE) 1860 #if 0 1861 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 1862 #else 1863 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n"); 1864 #endif 1865 else 1866 { 1867 status = I_RpcReceive(pStubMsg->RpcMsg); 1868 if (status != RPC_S_OK) 1869 goto cleanup; 1870 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength; 1871 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; 1872 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; 1873 pStubMsg->Buffer = pStubMsg->BufferStart; 1874 } 1875 1876 /* convert strings, floating point values and endianness into our 1877 * preferred format */ 1878 #if 0 1879 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 1880 NdrConvert(pStubMsg, pFormat); 1881 #endif 1882 1883 /* 2. UNMARSHAL */ 1884 TRACE( "UNMARSHAL\n" ); 1885 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL, 1886 NULL, async_call_data->number_of_params, Reply); 1887 1888 cleanup: 1889 if (pStubMsg->fHasNewCorrDesc) 1890 { 1891 /* free extra correlation package */ 1892 NdrCorrelationFree(pStubMsg); 1893 } 1894 1895 /* free the full pointer translation tables */ 1896 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 1897 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); 1898 1899 /* free marshalling buffer */ 1900 NdrFreeBuffer(pStubMsg); 1901 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding); 1902 1903 I_RpcFree(pStubMsg->StackTop); 1904 I_RpcFree(async_call_data); 1905 1906 TRACE("-- 0x%x\n", status); 1907 return status; 1908 } 1909 1910 #ifdef __x86_64__ 1911 1912 __ASM_GLOBAL_FUNC( NdrAsyncClientCall, 1913 "subq $0x28,%rsp\n\t" 1914 __ASM_SEH(".seh_stackalloc 0x28\n\t") 1915 __ASM_SEH(".seh_endprologue\n\t") 1916 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") 1917 "movq %r8,0x40(%rsp)\n\t" 1918 "movq %r9,0x48(%rsp)\n\t" 1919 "leaq 0x40(%rsp),%r8\n\t" 1920 "call " __ASM_NAME("ndr_async_client_call") "\n\t" 1921 "addq $0x28,%rsp\n\t" 1922 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") 1923 "ret" ); 1924 1925 #else /* __x86_64__ */ 1926 1927 /*********************************************************************** 1928 * NdrAsyncClientCall [RPCRT4.@] 1929 */ 1930 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) 1931 { 1932 __ms_va_list args; 1933 LONG_PTR ret; 1934 1935 __ms_va_start( args, format ); 1936 ret = ndr_async_client_call( desc, format, va_arg( args, void ** )); 1937 __ms_va_end( args ); 1938 return *(CLIENT_CALL_RETURN *)&ret; 1939 } 1940 1941 #endif /* __x86_64__ */ 1942 1943 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis, 1944 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, 1945 DWORD * pdwStubPhase) 1946 { 1947 FIXME("unimplemented, expect crash!\n"); 1948 return 0; 1949 } 1950 1951 void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg) 1952 { 1953 const MIDL_SERVER_INFO *pServerInfo; 1954 const MIDL_STUB_DESC *pStubDesc; 1955 PFORMAT_STRING pFormat; 1956 /* pointer to start of stack to pass into stub implementation */ 1957 unsigned char *args; 1958 /* header for procedure string */ 1959 const NDR_PROC_HEADER *pProcHeader; 1960 struct async_call_data *async_call_data; 1961 PRPC_ASYNC_STATE pAsync; 1962 RPC_STATUS status; 1963 1964 TRACE("%p\n", pRpcMsg); 1965 1966 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; 1967 1968 pStubDesc = pServerInfo->pStubDesc; 1969 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; 1970 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 1971 1972 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 1973 1974 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); 1975 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY); 1976 async_call_data->pProcHeader = pProcHeader; 1977 1978 async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); 1979 *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg; 1980 1981 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) 1982 { 1983 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 1984 async_call_data->stack_size = header_rpc->stack_size; 1985 pFormat += sizeof(NDR_PROC_HEADER_RPC); 1986 } 1987 else 1988 { 1989 async_call_data->stack_size = pProcHeader->stack_size; 1990 pFormat += sizeof(NDR_PROC_HEADER); 1991 } 1992 1993 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 1994 1995 /* binding */ 1996 switch (pProcHeader->handle_type) 1997 { 1998 /* explicit binding: parse additional section */ 1999 case 0: 2000 switch (*pFormat) /* handle_type */ 2001 { 2002 case FC_BIND_PRIMITIVE: /* explicit primitive */ 2003 pFormat += sizeof(NDR_EHD_PRIMITIVE); 2004 break; 2005 case FC_BIND_GENERIC: /* explicit generic */ 2006 pFormat += sizeof(NDR_EHD_GENERIC); 2007 break; 2008 case FC_BIND_CONTEXT: /* explicit context */ 2009 pFormat += sizeof(NDR_EHD_CONTEXT); 2010 break; 2011 default: 2012 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 2013 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2014 } 2015 break; 2016 case FC_BIND_GENERIC: /* implicit generic */ 2017 case FC_BIND_PRIMITIVE: /* implicit primitive */ 2018 case FC_CALLBACK_HANDLE: /* implicit callback */ 2019 case FC_AUTO_HANDLE: /* implicit auto handle */ 2020 break; 2021 default: 2022 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 2023 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2024 } 2025 2026 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) 2027 { 2028 ERR("objects not supported\n"); 2029 I_RpcFree(async_call_data); 2030 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2031 } 2032 2033 NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc); 2034 2035 /* create the full pointer translation tables, if requested */ 2036 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 2037 async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER); 2038 2039 /* use alternate memory allocation routines */ 2040 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) 2041 #if 0 2042 NdrRpcSsEnableAllocate(&stubMsg); 2043 #else 2044 FIXME("Set RPCSS memory allocation routines\n"); 2045 #endif 2046 2047 TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size); 2048 2049 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, async_call_data->stack_size); 2050 async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */ 2051 2052 pAsync = I_RpcAllocate(sizeof(*pAsync)); 2053 if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY); 2054 2055 status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync)); 2056 if (status != RPC_S_OK) 2057 RpcRaiseException(status); 2058 2059 pAsync->StubInfo = async_call_data; 2060 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); 2061 2062 /* add the implicit pAsync pointer as the first arg to the function */ 2063 *(void **)args = pAsync; 2064 2065 if (is_oicf_stubdesc(pStubDesc)) 2066 { 2067 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 2068 /* cache of Oif_flags from v2 procedure header */ 2069 INTERPRETER_OPT_FLAGS Oif_flags; 2070 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 2071 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 2072 2073 Oif_flags = pOIFHeader->Oi2Flags; 2074 async_call_data->number_of_params = pOIFHeader->number_of_params; 2075 2076 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 2077 2078 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 2079 2080 if (Oif_flags.HasExtensions) 2081 { 2082 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 2083 ext_flags = pExtensions->Flags2; 2084 pFormat += pExtensions->Size; 2085 } 2086 2087 if (Oif_flags.HasPipes) 2088 { 2089 FIXME("pipes not supported yet\n"); 2090 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 2091 /* init pipes package */ 2092 /* NdrPipesInitialize(...) */ 2093 } 2094 if (ext_flags.HasNewCorrDesc) 2095 { 2096 /* initialize extra correlation package */ 2097 NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); 2098 if (ext_flags.Unused & 0x2) /* has range on conformance */ 2099 async_call_data->pStubMsg->CorrDespIncrement = 12; 2100 } 2101 } 2102 else 2103 { 2104 pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size, 2105 pProcHeader->Oi_flags & Oi_OBJECT_PROC, 2106 /* reuse the correlation cache, it's not needed for v1 format */ 2107 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params ); 2108 } 2109 2110 /* convert strings, floating point values and endianness into our 2111 * preferred format */ 2112 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 2113 NdrConvert(async_call_data->pStubMsg, pFormat); 2114 2115 async_call_data->pHandleFormat = pFormat; 2116 2117 /* 1. UNMARSHAL */ 2118 TRACE("UNMARSHAL\n"); 2119 stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params); 2120 2121 /* 2. INITOUT */ 2122 TRACE("INITOUT\n"); 2123 async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params); 2124 2125 /* 3. CALLSERVER */ 2126 TRACE("CALLSERVER\n"); 2127 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) 2128 pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg); 2129 else 2130 call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size); 2131 } 2132 2133 RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply) 2134 { 2135 /* pointer to start of stack where arguments start */ 2136 PMIDL_STUB_MESSAGE pStubMsg; 2137 struct async_call_data *async_call_data; 2138 /* the type of pass we are currently doing */ 2139 enum stubless_phase phase; 2140 RPC_STATUS status = RPC_S_OK; 2141 2142 if (!pAsync->StubInfo) 2143 return RPC_S_INVALID_ASYNC_HANDLE; 2144 2145 async_call_data = pAsync->StubInfo; 2146 pStubMsg = async_call_data->pStubMsg; 2147 2148 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); 2149 2150 if (async_call_data->retval_ptr) 2151 { 2152 TRACE("stub implementation returned 0x%lx\n", *(LONG_PTR *)Reply); 2153 *async_call_data->retval_ptr = *(LONG_PTR *)Reply; 2154 } 2155 else 2156 TRACE("void stub implementation\n"); 2157 2158 for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++) 2159 { 2160 TRACE("phase = %d\n", phase); 2161 switch (phase) 2162 { 2163 case STUBLESS_GETBUFFER: 2164 if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC) 2165 { 2166 ERR("objects not supported\n"); 2167 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); 2168 I_RpcFree(async_call_data); 2169 I_RpcFree(pAsync); 2170 RpcRaiseException(RPC_X_BAD_STUB_DATA); 2171 } 2172 else 2173 { 2174 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; 2175 /* allocate buffer for [out] and [ret] params */ 2176 status = I_RpcGetBuffer(pStubMsg->RpcMsg); 2177 if (status) 2178 RpcRaiseException(status); 2179 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; 2180 } 2181 break; 2182 2183 case STUBLESS_CALCSIZE: 2184 case STUBLESS_MARSHAL: 2185 case STUBLESS_MUSTFREE: 2186 case STUBLESS_FREE: 2187 stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params); 2188 break; 2189 default: 2190 ERR("shouldn't reach here. phase %d\n", phase); 2191 break; 2192 } 2193 } 2194 2195 #if 0 /* FIXME */ 2196 if (ext_flags.HasNewCorrDesc) 2197 { 2198 /* free extra correlation package */ 2199 NdrCorrelationFree(pStubMsg); 2200 } 2201 2202 if (Oif_flags.HasPipes) 2203 { 2204 /* NdrPipesDone(...) */ 2205 } 2206 2207 /* free the full pointer translation tables */ 2208 if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED) 2209 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); 2210 #endif 2211 2212 /* free server function stack */ 2213 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop); 2214 I_RpcFree(async_call_data); 2215 I_RpcFree(pAsync); 2216 2217 return S_OK; 2218 } 2219