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