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