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