Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenndr_stubless.c
Go to the documentation of this file.
00001 /* 00002 * NDR -Oi,-Oif,-Oicf Interpreter 00003 * 00004 * Copyright 2001 Ove Kåven, TransGaming Technologies 00005 * Copyright 2003-5 Robert Shearman (for CodeWeavers) 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 * 00021 * TODO: 00022 * - Pipes 00023 * - Some types of binding handles 00024 */ 00025 00026 #include "config.h" 00027 #include "wine/port.h" 00028 00029 #include <stdarg.h> 00030 #include <stdio.h> 00031 #include <string.h> 00032 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winerror.h" 00036 00037 #include "objbase.h" 00038 #include "rpc.h" 00039 #include "rpcproxy.h" 00040 00041 #include "wine/exception.h" 00042 #include "wine/debug.h" 00043 #include "wine/rpcfc.h" 00044 00045 #include "cpsf.h" 00046 #include "ndr_misc.h" 00047 #include "ndr_stubless.h" 00048 00049 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 00050 00051 #define NDR_TABLE_MASK 127 00052 00053 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 00054 const NDR_PARAM_OIF *param) 00055 { 00056 PFORMAT_STRING pFormat; 00057 NDR_BUFFERSIZE m; 00058 00059 if (param->attr.IsBasetype) 00060 { 00061 pFormat = ¶m->u.type_format_char; 00062 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; 00063 } 00064 else 00065 { 00066 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 00067 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 00068 } 00069 00070 m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; 00071 if (m) m(pStubMsg, pMemory, pFormat); 00072 else 00073 { 00074 FIXME("format type 0x%x not implemented\n", pFormat[0]); 00075 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00076 } 00077 } 00078 00079 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 00080 const NDR_PARAM_OIF *param) 00081 { 00082 PFORMAT_STRING pFormat; 00083 NDR_MARSHALL m; 00084 00085 if (param->attr.IsBasetype) 00086 { 00087 pFormat = ¶m->u.type_format_char; 00088 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; 00089 } 00090 else 00091 { 00092 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 00093 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 00094 } 00095 00096 m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; 00097 if (m) return m(pStubMsg, pMemory, pFormat); 00098 else 00099 { 00100 FIXME("format type 0x%x not implemented\n", pFormat[0]); 00101 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00102 return NULL; 00103 } 00104 } 00105 00106 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, 00107 const NDR_PARAM_OIF *param, unsigned char fMustAlloc) 00108 { 00109 PFORMAT_STRING pFormat; 00110 NDR_UNMARSHALL m; 00111 00112 if (param->attr.IsBasetype) 00113 { 00114 pFormat = ¶m->u.type_format_char; 00115 if (param->attr.IsSimpleRef) ppMemory = (unsigned char **)*ppMemory; 00116 } 00117 else 00118 { 00119 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 00120 if (!param->attr.IsByValue) ppMemory = (unsigned char **)*ppMemory; 00121 } 00122 00123 m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; 00124 if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); 00125 else 00126 { 00127 FIXME("format type 0x%x not implemented\n", pFormat[0]); 00128 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00129 return NULL; 00130 } 00131 } 00132 00133 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, 00134 const NDR_PARAM_OIF *param) 00135 { 00136 PFORMAT_STRING pFormat; 00137 NDR_FREE m; 00138 00139 if (param->attr.IsBasetype) return; /* nothing to do */ 00140 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; 00141 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; 00142 00143 m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; 00144 if (m) m(pStubMsg, pMemory, pFormat); 00145 } 00146 00147 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) 00148 { 00149 DWORD size; 00150 switch(*pFormat) 00151 { 00152 case RPC_FC_STRUCT: 00153 case RPC_FC_PSTRUCT: 00154 size = *(const WORD*)(pFormat + 2); 00155 break; 00156 case RPC_FC_BOGUS_STRUCT: 00157 size = *(const WORD*)(pFormat + 2); 00158 if(*(const WORD*)(pFormat + 4)) 00159 FIXME("Unhandled conformant description\n"); 00160 break; 00161 case RPC_FC_CARRAY: 00162 case RPC_FC_CVARRAY: 00163 size = *(const WORD*)(pFormat + 2); 00164 ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); 00165 size *= pStubMsg->MaxCount; 00166 break; 00167 case RPC_FC_SMFARRAY: 00168 case RPC_FC_SMVARRAY: 00169 size = *(const WORD*)(pFormat + 2); 00170 break; 00171 case RPC_FC_LGFARRAY: 00172 case RPC_FC_LGVARRAY: 00173 size = *(const DWORD*)(pFormat + 2); 00174 break; 00175 case RPC_FC_BOGUS_ARRAY: 00176 pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]); 00177 TRACE("conformance = %ld\n", pStubMsg->MaxCount); 00178 pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount); 00179 size = ComplexStructSize(pStubMsg, pFormat); 00180 size *= pStubMsg->MaxCount; 00181 break; 00182 case RPC_FC_USER_MARSHAL: 00183 size = *(const WORD*)(pFormat + 4); 00184 break; 00185 case RPC_FC_CSTRING: 00186 size = *(const WORD*)(pFormat + 2); 00187 break; 00188 case RPC_FC_WSTRING: 00189 size = *(const WORD*)(pFormat + 2) * sizeof(WCHAR); 00190 break; 00191 case RPC_FC_C_CSTRING: 00192 case RPC_FC_C_WSTRING: 00193 if (*pFormat == RPC_FC_C_CSTRING) 00194 size = sizeof(CHAR); 00195 else 00196 size = sizeof(WCHAR); 00197 if (pFormat[1] == RPC_FC_STRING_SIZED) 00198 ComputeConformance(pStubMsg, NULL, pFormat + 2, 0); 00199 else 00200 pStubMsg->MaxCount = 0; 00201 size *= pStubMsg->MaxCount; 00202 break; 00203 default: 00204 FIXME("Unhandled type %02x\n", *pFormat); 00205 /* fallthrough */ 00206 case RPC_FC_RP: 00207 size = sizeof(void *); 00208 break; 00209 } 00210 return size; 00211 } 00212 00213 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) 00214 { 00215 #if 0 /* these functions are not defined yet */ 00216 pMessage->pfnAllocate = NdrRpcSmClientAllocate; 00217 pMessage->pfnFree = NdrRpcSmClientFree; 00218 #endif 00219 } 00220 00221 static const char *debugstr_PROC_PF(PARAM_ATTRIBUTES param_attributes) 00222 { 00223 char buffer[160]; 00224 00225 buffer[0] = 0; 00226 if (param_attributes.MustSize) strcat(buffer, " MustSize"); 00227 if (param_attributes.MustFree) strcat(buffer, " MustFree"); 00228 if (param_attributes.IsPipe) strcat(buffer, " IsPipe"); 00229 if (param_attributes.IsIn) strcat(buffer, " IsIn"); 00230 if (param_attributes.IsOut) strcat(buffer, " IsOut"); 00231 if (param_attributes.IsReturn) strcat(buffer, " IsReturn"); 00232 if (param_attributes.IsBasetype) strcat(buffer, " IsBasetype"); 00233 if (param_attributes.IsByValue) strcat(buffer, " IsByValue"); 00234 if (param_attributes.IsSimpleRef) strcat(buffer, " IsSimpleRef"); 00235 if (param_attributes.IsDontCallFreeInst) strcat(buffer, " IsDontCallFreeInst"); 00236 if (param_attributes.SaveForAsyncFinish) strcat(buffer, " SaveForAsyncFinish"); 00237 if (param_attributes.ServerAllocSize) 00238 sprintf( buffer + strlen(buffer), " ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); 00239 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; 00240 } 00241 00242 static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) 00243 { 00244 char buffer[160]; 00245 00246 buffer[0] = 0; 00247 if (Oi2Flags.ServerMustSize) strcat(buffer, " ServerMustSize"); 00248 if (Oi2Flags.ClientMustSize) strcat(buffer, " ClientMustSize"); 00249 if (Oi2Flags.HasReturn) strcat(buffer, " HasReturn"); 00250 if (Oi2Flags.HasPipes) strcat(buffer, " HasPipes"); 00251 if (Oi2Flags.Unused) strcat(buffer, " Unused"); 00252 if (Oi2Flags.HasAsyncUuid) strcat(buffer, " HasAsyncUuid"); 00253 if (Oi2Flags.HasExtensions) strcat(buffer, " HasExtensions"); 00254 if (Oi2Flags.HasAsyncHandle) strcat(buffer, " HasAsyncHandle"); 00255 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; 00256 } 00257 00258 #define ARG_FROM_OFFSET(args, offset) ((args) + (offset)) 00259 00260 static PFORMAT_STRING client_get_handle( 00261 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, 00262 PFORMAT_STRING pFormat, handle_t *phBinding) 00263 { 00264 /* binding */ 00265 switch (pProcHeader->handle_type) 00266 { 00267 /* explicit binding: parse additional section */ 00268 case RPC_FC_BIND_EXPLICIT: 00269 switch (*pFormat) /* handle_type */ 00270 { 00271 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ 00272 { 00273 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; 00274 00275 TRACE("Explicit primitive handle @ %d\n", pDesc->offset); 00276 00277 if (pDesc->flag) /* pointer to binding */ 00278 *phBinding = **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00279 else 00280 *phBinding = *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00281 return pFormat + sizeof(NDR_EHD_PRIMITIVE); 00282 } 00283 case RPC_FC_BIND_GENERIC: /* explicit generic */ 00284 { 00285 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; 00286 void *pObject = NULL; 00287 void *pArg; 00288 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; 00289 00290 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); 00291 00292 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) 00293 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00294 else 00295 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00296 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); 00297 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; 00298 *phBinding = pGenPair->pfnBind(pObject); 00299 return pFormat + sizeof(NDR_EHD_GENERIC); 00300 } 00301 case RPC_FC_BIND_CONTEXT: /* explicit context */ 00302 { 00303 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; 00304 NDR_CCONTEXT context_handle; 00305 TRACE("Explicit bind context\n"); 00306 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) 00307 { 00308 TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); 00309 context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00310 } 00311 else 00312 context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00313 00314 if (context_handle) *phBinding = NDRCContextBinding(context_handle); 00315 else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) 00316 { 00317 ERR("null context handle isn't allowed\n"); 00318 RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT); 00319 return NULL; 00320 } 00321 /* FIXME: should we store this structure in stubMsg.pContext? */ 00322 return pFormat + sizeof(NDR_EHD_CONTEXT); 00323 } 00324 default: 00325 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 00326 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00327 } 00328 break; 00329 case RPC_FC_BIND_GENERIC: /* implicit generic */ 00330 FIXME("RPC_FC_BIND_GENERIC\n"); 00331 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ 00332 break; 00333 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ 00334 TRACE("Implicit primitive handle\n"); 00335 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; 00336 break; 00337 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ 00338 FIXME("RPC_FC_CALLBACK_HANDLE\n"); 00339 break; 00340 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ 00341 /* strictly speaking, it isn't necessary to set hBinding here 00342 * since it isn't actually used (hence the automatic in its name), 00343 * but then why does MIDL generate a valid entry in the 00344 * MIDL_STUB_DESC for it? */ 00345 TRACE("Implicit auto handle\n"); 00346 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; 00347 break; 00348 default: 00349 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 00350 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00351 } 00352 return pFormat; 00353 } 00354 00355 static void client_free_handle( 00356 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, 00357 PFORMAT_STRING pFormat, handle_t hBinding) 00358 { 00359 /* binding */ 00360 switch (pProcHeader->handle_type) 00361 { 00362 /* explicit binding: parse additional section */ 00363 case RPC_FC_BIND_EXPLICIT: 00364 switch (*pFormat) /* handle_type */ 00365 { 00366 case RPC_FC_BIND_GENERIC: /* explicit generic */ 00367 { 00368 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; 00369 void *pObject = NULL; 00370 void *pArg; 00371 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; 00372 00373 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); 00374 00375 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) 00376 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00377 else 00378 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); 00379 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); 00380 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; 00381 pGenPair->pfnUnbind(pObject, hBinding); 00382 break; 00383 } 00384 case RPC_FC_BIND_CONTEXT: /* explicit context */ 00385 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ 00386 break; 00387 default: 00388 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 00389 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00390 } 00391 break; 00392 case RPC_FC_BIND_GENERIC: /* implicit generic */ 00393 FIXME("RPC_FC_BIND_GENERIC\n"); 00394 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ 00395 break; 00396 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ 00397 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ 00398 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ 00399 break; 00400 default: 00401 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 00402 RpcRaiseException(RPC_X_BAD_STUB_DATA); 00403 } 00404 } 00405 00406 void client_do_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase, 00407 void **fpu_args, unsigned short number_of_params, unsigned char *pRetVal ) 00408 { 00409 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; 00410 unsigned int i; 00411 00412 for (i = 0; i < number_of_params; i++) 00413 { 00414 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; 00415 PFORMAT_STRING pTypeFormat = (PFORMAT_STRING)&pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; 00416 00417 #ifdef __x86_64__ /* floats are passed as doubles through varargs functions */ 00418 float f; 00419 00420 if (params[i].attr.IsBasetype && 00421 params[i].u.type_format_char == RPC_FC_FLOAT && 00422 !params[i].attr.IsSimpleRef && 00423 !fpu_args) 00424 { 00425 f = *(double *)pArg; 00426 pArg = (unsigned char *)&f; 00427 } 00428 #endif 00429 00430 TRACE("param[%d]: %p type %02x %s\n", i, pArg, 00431 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, 00432 debugstr_PROC_PF( params[i].attr )); 00433 00434 switch (phase) 00435 { 00436 case STUBLESS_INITOUT: 00437 if (!params[i].attr.IsBasetype && params[i].attr.IsOut && 00438 !params[i].attr.IsIn && !params[i].attr.IsByValue) 00439 { 00440 memset( *(unsigned char **)pArg, 0, calc_arg_size( pStubMsg, pTypeFormat )); 00441 } 00442 break; 00443 case STUBLESS_CALCSIZE: 00444 if (params[i].attr.IsSimpleRef && !*(unsigned char **)pArg) 00445 RpcRaiseException(RPC_X_NULL_REF_POINTER); 00446 if (params[i].attr.IsIn) call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); 00447 break; 00448 case STUBLESS_MARSHAL: 00449 if (params[i].attr.IsIn) call_marshaller(pStubMsg, pArg, ¶ms[i]); 00450 break; 00451 case STUBLESS_UNMARSHAL: 00452 if (params[i].attr.IsOut) 00453 { 00454 if (params[i].attr.IsReturn && pRetVal) pArg = pRetVal; 00455 call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); 00456 } 00457 break; 00458 case STUBLESS_FREE: 00459 if (!params[i].attr.IsBasetype && params[i].attr.IsOut && !params[i].attr.IsByValue) 00460 NdrClearOutParameters( pStubMsg, pTypeFormat, *(unsigned char **)pArg ); 00461 break; 00462 default: 00463 RpcRaiseException(RPC_S_INTERNAL_ERROR); 00464 } 00465 } 00466 } 00467 00468 static unsigned int type_stack_size(unsigned char fc) 00469 { 00470 switch (fc) 00471 { 00472 case RPC_FC_BYTE: 00473 case RPC_FC_CHAR: 00474 case RPC_FC_SMALL: 00475 case RPC_FC_USMALL: 00476 case RPC_FC_WCHAR: 00477 case RPC_FC_SHORT: 00478 case RPC_FC_USHORT: 00479 case RPC_FC_LONG: 00480 case RPC_FC_ULONG: 00481 case RPC_FC_INT3264: 00482 case RPC_FC_UINT3264: 00483 case RPC_FC_ENUM16: 00484 case RPC_FC_ENUM32: 00485 case RPC_FC_FLOAT: 00486 case RPC_FC_ERROR_STATUS_T: 00487 case RPC_FC_IGNORE: 00488 return sizeof(void *); 00489 case RPC_FC_DOUBLE: 00490 return sizeof(double); 00491 case RPC_FC_HYPER: 00492 return sizeof(ULONGLONG); 00493 default: 00494 ERR("invalid base type 0x%x\n", fc); 00495 RpcRaiseException(RPC_S_INTERNAL_ERROR); 00496 } 00497 } 00498 00499 static BOOL is_by_value( PFORMAT_STRING format ) 00500 { 00501 switch (*format) 00502 { 00503 case RPC_FC_USER_MARSHAL: 00504 case RPC_FC_STRUCT: 00505 case RPC_FC_PSTRUCT: 00506 case RPC_FC_CSTRUCT: 00507 case RPC_FC_CPSTRUCT: 00508 case RPC_FC_CVSTRUCT: 00509 case RPC_FC_BOGUS_STRUCT: 00510 return TRUE; 00511 default: 00512 return FALSE; 00513 } 00514 } 00515 00516 PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, 00517 unsigned int stack_size, BOOL object_proc, 00518 void *buffer, unsigned int size, unsigned int *count ) 00519 { 00520 NDR_PARAM_OIF *args = buffer; 00521 unsigned int i, stack_offset = object_proc ? sizeof(void *) : 0; 00522 00523 for (i = 0; stack_offset < stack_size; i++) 00524 { 00525 const NDR_PARAM_OI_BASETYPE *param = (const NDR_PARAM_OI_BASETYPE *)pFormat; 00526 const NDR_PARAM_OI_OTHER *other = (const NDR_PARAM_OI_OTHER *)pFormat; 00527 00528 if (i + 1 > size / sizeof(*args)) 00529 { 00530 FIXME( "%u args not supported\n", i ); 00531 RpcRaiseException( RPC_S_INTERNAL_ERROR ); 00532 } 00533 00534 args[i].stack_offset = stack_offset; 00535 memset( &args[i].attr, 0, sizeof(args[i].attr) ); 00536 00537 switch (param->param_direction) 00538 { 00539 case RPC_FC_IN_PARAM_BASETYPE: 00540 args[i].attr.IsIn = 1; 00541 args[i].attr.IsBasetype = 1; 00542 break; 00543 case RPC_FC_RETURN_PARAM_BASETYPE: 00544 args[i].attr.IsOut = 1; 00545 args[i].attr.IsReturn = 1; 00546 args[i].attr.IsBasetype = 1; 00547 break; 00548 case RPC_FC_IN_PARAM: 00549 args[i].attr.IsIn = 1; 00550 args[i].attr.MustFree = 1; 00551 break; 00552 case RPC_FC_IN_PARAM_NO_FREE_INST: 00553 args[i].attr.IsIn = 1; 00554 args[i].attr.IsDontCallFreeInst = 1; 00555 break; 00556 case RPC_FC_IN_OUT_PARAM: 00557 args[i].attr.IsIn = 1; 00558 args[i].attr.IsOut = 1; 00559 args[i].attr.MustFree = 1; 00560 break; 00561 case RPC_FC_OUT_PARAM: 00562 args[i].attr.IsOut = 1; 00563 break; 00564 case RPC_FC_RETURN_PARAM: 00565 args[i].attr.IsOut = 1; 00566 args[i].attr.IsReturn = 1; 00567 break; 00568 } 00569 if (args[i].attr.IsBasetype) 00570 { 00571 args[i].u.type_format_char = param->type_format_char; 00572 stack_offset += type_stack_size( param->type_format_char ); 00573 pFormat += sizeof(NDR_PARAM_OI_BASETYPE); 00574 } 00575 else 00576 { 00577 args[i].u.type_offset = other->type_offset; 00578 args[i].attr.IsByValue = is_by_value( &pStubMsg->StubDesc->pFormatTypes[other->type_offset] ); 00579 stack_offset += other->stack_size * sizeof(void *); 00580 pFormat += sizeof(NDR_PARAM_OI_OTHER); 00581 } 00582 } 00583 *count = i; 00584 return (PFORMAT_STRING)args; 00585 } 00586 00587 LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, 00588 void **stack_top, void **fpu_stack ) 00589 { 00590 /* pointer to start of stack where arguments start */ 00591 RPC_MESSAGE rpcMsg; 00592 MIDL_STUB_MESSAGE stubMsg; 00593 handle_t hBinding = NULL; 00594 /* procedure number */ 00595 unsigned short procedure_number; 00596 /* size of stack */ 00597 unsigned short stack_size; 00598 /* number of parameters. optional for client to give it to us */ 00599 unsigned int number_of_params; 00600 /* cache of Oif_flags from v2 procedure header */ 00601 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 00602 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 00603 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 00604 /* header for procedure string */ 00605 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 00606 /* the value to return to the client from the remote procedure */ 00607 LONG_PTR RetVal = 0; 00608 /* the pointer to the object when in OLE mode */ 00609 void * This = NULL; 00610 PFORMAT_STRING pHandleFormat; 00611 /* correlation cache */ 00612 ULONG_PTR NdrCorrCache[256]; 00613 00614 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); 00615 00616 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 00617 00618 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 00619 { 00620 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 00621 stack_size = pProcHeader->stack_size; 00622 procedure_number = pProcHeader->proc_num; 00623 pFormat += sizeof(NDR_PROC_HEADER_RPC); 00624 } 00625 else 00626 { 00627 stack_size = pProcHeader->stack_size; 00628 procedure_number = pProcHeader->proc_num; 00629 pFormat += sizeof(NDR_PROC_HEADER); 00630 } 00631 TRACE("stack size: 0x%x\n", stack_size); 00632 TRACE("proc num: %d\n", procedure_number); 00633 00634 /* create the full pointer translation tables, if requested */ 00635 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 00636 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); 00637 00638 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00639 { 00640 /* object is always the first argument */ 00641 This = stack_top[0]; 00642 NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); 00643 } 00644 else 00645 NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); 00646 00647 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 00648 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); 00649 00650 stubMsg.StackTop = (unsigned char *)stack_top; 00651 pHandleFormat = pFormat; 00652 00653 /* we only need a handle if this isn't an object method */ 00654 if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)) 00655 { 00656 pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding); 00657 if (!pFormat) goto done; 00658 } 00659 00660 if (pStubDesc->Version >= 0x20000) /* -Oicf format */ 00661 { 00662 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = 00663 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 00664 00665 Oif_flags = pOIFHeader->Oi2Flags; 00666 number_of_params = pOIFHeader->number_of_params; 00667 00668 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 00669 00670 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 00671 00672 if (Oif_flags.HasExtensions) 00673 { 00674 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 00675 ext_flags = pExtensions->Flags2; 00676 pFormat += pExtensions->Size; 00677 #ifdef __x86_64__ 00678 if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack) 00679 { 00680 int i; 00681 unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1); 00682 for (i = 0; i < 4; i++, fpu_mask >>= 2) 00683 switch (fpu_mask & 3) 00684 { 00685 case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break; 00686 case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break; 00687 } 00688 } 00689 #endif 00690 } 00691 } 00692 else 00693 { 00694 pFormat = convert_old_args( &stubMsg, pFormat, stack_size, 00695 pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, 00696 /* reuse the correlation cache, it's not needed for v1 format */ 00697 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); 00698 } 00699 00700 stubMsg.BufferLength = 0; 00701 00702 /* store the RPC flags away */ 00703 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 00704 rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 00705 00706 /* use alternate memory allocation routines */ 00707 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) 00708 NdrRpcSmSetClientToOsf(&stubMsg); 00709 00710 if (Oif_flags.HasPipes) 00711 { 00712 FIXME("pipes not supported yet\n"); 00713 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 00714 /* init pipes package */ 00715 /* NdrPipesInitialize(...) */ 00716 } 00717 if (ext_flags.HasNewCorrDesc) 00718 { 00719 /* initialize extra correlation package */ 00720 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0); 00721 } 00722 00723 /* order of phases: 00724 * 1. INITOUT - zero [out] parameters (proxies only) 00725 * 2. CALCSIZE - calculate the buffer size 00726 * 3. GETBUFFER - allocate the buffer 00727 * 4. MARSHAL - marshal [in] params into the buffer 00728 * 5. SENDRECEIVE - send/receive buffer 00729 * 6. UNMARSHAL - unmarshal [out] params from buffer 00730 * 7. FREE - clear [out] parameters (for proxies, and only on error) 00731 */ 00732 if ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) || 00733 (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_HAS_COMM_OR_FAULT)) 00734 { 00735 /* 1. INITOUT */ 00736 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00737 { 00738 TRACE( "INITOUT\n" ); 00739 client_do_args(&stubMsg, pFormat, STUBLESS_INITOUT, fpu_stack, 00740 number_of_params, (unsigned char *)&RetVal); 00741 } 00742 00743 __TRY 00744 { 00745 /* 2. CALCSIZE */ 00746 TRACE( "CALCSIZE\n" ); 00747 client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, 00748 number_of_params, (unsigned char *)&RetVal); 00749 00750 /* 3. GETBUFFER */ 00751 TRACE( "GETBUFFER\n" ); 00752 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00753 { 00754 /* allocate the buffer */ 00755 NdrProxyGetBuffer(This, &stubMsg); 00756 } 00757 else 00758 { 00759 /* allocate the buffer */ 00760 if (Oif_flags.HasPipes) 00761 /* NdrGetPipeBuffer(...) */ 00762 FIXME("pipes not supported yet\n"); 00763 else 00764 { 00765 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 00766 #if 0 00767 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); 00768 #else 00769 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 00770 #endif 00771 else 00772 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); 00773 } 00774 } 00775 00776 /* 4. MARSHAL */ 00777 TRACE( "MARSHAL\n" ); 00778 client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, 00779 number_of_params, (unsigned char *)&RetVal); 00780 00781 /* 5. SENDRECEIVE */ 00782 TRACE( "SENDRECEIVE\n" ); 00783 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00784 { 00785 /* send the [in] params and receive the [out] and [retval] 00786 * params */ 00787 NdrProxySendReceive(This, &stubMsg); 00788 } 00789 else 00790 { 00791 /* send the [in] params and receive the [out] and [retval] 00792 * params */ 00793 if (Oif_flags.HasPipes) 00794 /* NdrPipesSendReceive(...) */ 00795 FIXME("pipes not supported yet\n"); 00796 else 00797 { 00798 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 00799 #if 0 00800 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 00801 #else 00802 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); 00803 #endif 00804 else 00805 NdrSendReceive(&stubMsg, stubMsg.Buffer); 00806 } 00807 } 00808 00809 /* convert strings, floating point values and endianess into our 00810 * preferred format */ 00811 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 00812 NdrConvert(&stubMsg, pFormat); 00813 00814 /* 6. UNMARSHAL */ 00815 TRACE( "UNMARSHAL\n" ); 00816 client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, 00817 number_of_params, (unsigned char *)&RetVal); 00818 } 00819 __EXCEPT_ALL 00820 { 00821 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00822 { 00823 /* 7. FREE */ 00824 TRACE( "FREE\n" ); 00825 client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack, 00826 number_of_params, (unsigned char *)&RetVal); 00827 RetVal = NdrProxyErrorHandler(GetExceptionCode()); 00828 } 00829 else 00830 { 00831 const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number]; 00832 ULONG *comm_status; 00833 ULONG *fault_status; 00834 00835 TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset); 00836 00837 if (comm_fault_offsets->CommOffset == -1) 00838 comm_status = (ULONG *)&RetVal; 00839 else if (comm_fault_offsets->CommOffset >= 0) 00840 comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset); 00841 else 00842 comm_status = NULL; 00843 00844 if (comm_fault_offsets->FaultOffset == -1) 00845 fault_status = (ULONG *)&RetVal; 00846 else if (comm_fault_offsets->FaultOffset >= 0) 00847 fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset); 00848 else 00849 fault_status = NULL; 00850 00851 NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status, 00852 GetExceptionCode()); 00853 } 00854 } 00855 __ENDTRY 00856 } 00857 else 00858 { 00859 /* 2. CALCSIZE */ 00860 TRACE( "CALCSIZE\n" ); 00861 client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, 00862 number_of_params, (unsigned char *)&RetVal); 00863 00864 /* 3. GETBUFFER */ 00865 TRACE( "GETBUFFER\n" ); 00866 if (Oif_flags.HasPipes) 00867 /* NdrGetPipeBuffer(...) */ 00868 FIXME("pipes not supported yet\n"); 00869 else 00870 { 00871 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 00872 #if 0 00873 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); 00874 #else 00875 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 00876 #endif 00877 else 00878 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); 00879 } 00880 00881 /* 4. MARSHAL */ 00882 TRACE( "MARSHAL\n" ); 00883 client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, 00884 number_of_params, (unsigned char *)&RetVal); 00885 00886 /* 5. SENDRECEIVE */ 00887 TRACE( "SENDRECEIVE\n" ); 00888 if (Oif_flags.HasPipes) 00889 /* NdrPipesSendReceive(...) */ 00890 FIXME("pipes not supported yet\n"); 00891 else 00892 { 00893 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 00894 #if 0 00895 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 00896 #else 00897 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); 00898 #endif 00899 else 00900 NdrSendReceive(&stubMsg, stubMsg.Buffer); 00901 } 00902 00903 /* convert strings, floating point values and endianness into our 00904 * preferred format */ 00905 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 00906 NdrConvert(&stubMsg, pFormat); 00907 00908 /* 6. UNMARSHAL */ 00909 TRACE( "UNMARSHAL\n" ); 00910 client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, 00911 number_of_params, (unsigned char *)&RetVal); 00912 } 00913 00914 if (ext_flags.HasNewCorrDesc) 00915 { 00916 /* free extra correlation package */ 00917 NdrCorrelationFree(&stubMsg); 00918 } 00919 00920 if (Oif_flags.HasPipes) 00921 { 00922 /* NdrPipesDone(...) */ 00923 } 00924 00925 /* free the full pointer translation tables */ 00926 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 00927 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); 00928 00929 /* free marshalling buffer */ 00930 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 00931 NdrProxyFreeBuffer(This, &stubMsg); 00932 else 00933 { 00934 NdrFreeBuffer(&stubMsg); 00935 client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); 00936 } 00937 00938 done: 00939 TRACE("RetVal = 0x%lx\n", RetVal); 00940 return RetVal; 00941 } 00942 00943 #ifdef __x86_64__ 00944 00945 __ASM_GLOBAL_FUNC( NdrClientCall2, 00946 "movq %r8,0x18(%rsp)\n\t" 00947 "movq %r9,0x20(%rsp)\n\t" 00948 "leaq 0x18(%rsp),%r8\n\t" 00949 "xorq %r9,%r9\n\t" 00950 "subq $0x28,%rsp\n\t" 00951 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") 00952 "call " __ASM_NAME("ndr_client_call") "\n\t" 00953 "addq $0x28,%rsp\n\t" 00954 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") 00955 "ret" ); 00956 00957 #else /* __x86_64__ */ 00958 00959 /*********************************************************************** 00960 * NdrClientCall2 [RPCRT4.@] 00961 */ 00962 CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) 00963 { 00964 __ms_va_list args; 00965 LONG_PTR ret; 00966 00967 __ms_va_start( args, format ); 00968 ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL ); 00969 __ms_va_end( args ); 00970 return *(CLIENT_CALL_RETURN *)&ret; 00971 } 00972 00973 #endif /* __x86_64__ */ 00974 00975 /* Calls a function with the specified arguments, restoring the stack 00976 * properly afterwards as we don't know the calling convention of the 00977 * function */ 00978 #if defined __i386__ && defined _MSC_VER 00979 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) 00980 { 00981 __asm 00982 { 00983 push ebp 00984 mov ebp, esp 00985 push edi ; Save registers 00986 push esi 00987 mov eax, [ebp+16] ; Get stack size 00988 sub esp, eax ; Make room in stack for arguments 00989 and esp, 0xFFFFFFF0 00990 mov edi, esp 00991 mov ecx, eax 00992 mov esi, [ebp+12] 00993 shr ecx, 2 00994 cld 00995 rep movsd ; Copy dword blocks 00996 call [ebp+8] ; Call function 00997 lea esp, [ebp-8] ; Restore stack 00998 pop esi ; Restore registers 00999 pop edi 01000 pop ebp 01001 ret 01002 } 01003 } 01004 #elif defined __i386__ && defined __GNUC__ 01005 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); 01006 __ASM_GLOBAL_FUNC(call_server_func, 01007 "pushl %ebp\n\t" 01008 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") 01009 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") 01010 "movl %esp,%ebp\n\t" 01011 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") 01012 "pushl %edi\n\t" /* Save registers */ 01013 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t") 01014 "pushl %esi\n\t" 01015 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") 01016 "movl 16(%ebp), %eax\n\t" /* Get stack size */ 01017 "subl %eax, %esp\n\t" /* Make room in stack for arguments */ 01018 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ 01019 "movl %esp, %edi\n\t" 01020 "movl %eax, %ecx\n\t" 01021 "movl 12(%ebp), %esi\n\t" 01022 "shrl $2, %ecx\n\t" /* divide by 4 */ 01023 "cld\n\t" 01024 "rep; movsl\n\t" /* Copy dword blocks */ 01025 "call *8(%ebp)\n\t" /* Call function */ 01026 "leal -8(%ebp), %esp\n\t" /* Restore stack */ 01027 "popl %esi\n\t" /* Restore registers */ 01028 __ASM_CFI(".cfi_same_value %esi\n\t") 01029 "popl %edi\n\t" 01030 __ASM_CFI(".cfi_same_value %edi\n\t") 01031 "popl %ebp\n\t" 01032 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") 01033 __ASM_CFI(".cfi_same_value %ebp\n\t") 01034 "ret" ) 01035 #elif defined __x86_64__ 01036 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); 01037 __ASM_GLOBAL_FUNC( call_server_func, 01038 "pushq %rbp\n\t" 01039 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") 01040 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") 01041 "movq %rsp,%rbp\n\t" 01042 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") 01043 "pushq %rsi\n\t" 01044 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t") 01045 "pushq %rdi\n\t" 01046 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t") 01047 "movq %rcx,%rax\n\t" /* function to call */ 01048 "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */ 01049 "cmpq %rcx,%r8\n\t" 01050 "cmovgq %r8,%rcx\n\t" 01051 "subq %rcx,%rsp\n\t" 01052 "andq $~15,%rsp\n\t" 01053 "movq %r8,%rcx\n\t" 01054 "shrq $3,%rcx\n\t" 01055 "movq %rsp,%rdi\n\t" 01056 "movq %rdx,%rsi\n\t" 01057 "rep; movsq\n\t" /* copy arguments */ 01058 "movq 0(%rsp),%rcx\n\t" 01059 "movq 8(%rsp),%rdx\n\t" 01060 "movq 16(%rsp),%r8\n\t" 01061 "movq 24(%rsp),%r9\n\t" 01062 "movq %rcx,%xmm0\n\t" 01063 "movq %rdx,%xmm1\n\t" 01064 "movq %r8,%xmm2\n\t" 01065 "movq %r9,%xmm3\n\t" 01066 "callq *%rax\n\t" 01067 "leaq -16(%rbp),%rsp\n\t" /* restore stack */ 01068 "popq %rdi\n\t" 01069 __ASM_CFI(".cfi_same_value %rdi\n\t") 01070 "popq %rsi\n\t" 01071 __ASM_CFI(".cfi_same_value %rsi\n\t") 01072 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") 01073 "popq %rbp\n\t" 01074 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") 01075 __ASM_CFI(".cfi_same_value %rbp\n\t") 01076 "ret") 01077 #else 01078 #warning call_server_func not implemented for your architecture 01079 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) 01080 { 01081 FIXME("Not implemented for your architecture\n"); 01082 return 0; 01083 } 01084 #endif 01085 01086 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, 01087 PFORMAT_STRING pFormat, enum stubless_phase phase, 01088 unsigned short number_of_params) 01089 { 01090 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; 01091 unsigned int i; 01092 LONG_PTR *retval_ptr = NULL; 01093 01094 for (i = 0; i < number_of_params; i++) 01095 { 01096 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; 01097 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; 01098 01099 TRACE("param[%d]: %p -> %p type %02x %s\n", i, 01100 pArg, *(unsigned char **)pArg, 01101 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, 01102 debugstr_PROC_PF( params[i].attr )); 01103 01104 switch (phase) 01105 { 01106 case STUBLESS_MARSHAL: 01107 if (params[i].attr.IsOut || params[i].attr.IsReturn) 01108 call_marshaller(pStubMsg, pArg, ¶ms[i]); 01109 break; 01110 case STUBLESS_FREE: 01111 if (params[i].attr.MustFree) 01112 { 01113 call_freer(pStubMsg, pArg, ¶ms[i]); 01114 } 01115 else if (params[i].attr.ServerAllocSize) 01116 { 01117 HeapFree(GetProcessHeap(), 0, *(void **)pArg); 01118 } 01119 else if (params[i].attr.IsOut && 01120 !params[i].attr.IsIn && 01121 !params[i].attr.IsBasetype && 01122 !params[i].attr.IsByValue) 01123 { 01124 if (*pTypeFormat != RPC_FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg); 01125 } 01126 break; 01127 case STUBLESS_INITOUT: 01128 if (!params[i].attr.IsIn && 01129 params[i].attr.IsOut && 01130 !params[i].attr.IsBasetype && 01131 !params[i].attr.ServerAllocSize && 01132 !params[i].attr.IsByValue) 01133 { 01134 if (*pTypeFormat == RPC_FC_BIND_CONTEXT) 01135 { 01136 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat); 01137 *(void **)pArg = NDRSContextValue(ctxt); 01138 } 01139 else 01140 { 01141 DWORD size = calc_arg_size(pStubMsg, pTypeFormat); 01142 if (size) 01143 { 01144 *(void **)pArg = NdrAllocate(pStubMsg, size); 01145 memset(*(void **)pArg, 0, size); 01146 } 01147 } 01148 } 01149 break; 01150 case STUBLESS_UNMARSHAL: 01151 if (params[i].attr.ServerAllocSize) 01152 *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 01153 params[i].attr.ServerAllocSize * 8); 01154 01155 if (params[i].attr.IsIn) 01156 call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); 01157 break; 01158 case STUBLESS_CALCSIZE: 01159 if (params[i].attr.IsOut || params[i].attr.IsReturn) 01160 call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); 01161 break; 01162 default: 01163 RpcRaiseException(RPC_S_INTERNAL_ERROR); 01164 } 01165 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); 01166 01167 /* make a note of the address of the return value parameter for later */ 01168 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg; 01169 } 01170 return retval_ptr; 01171 } 01172 01173 /*********************************************************************** 01174 * NdrStubCall2 [RPCRT4.@] 01175 * 01176 * Unmarshals [in] parameters, calls either a method in an object or a server 01177 * function, marshals any [out] parameters and frees any allocated data. 01178 * 01179 * NOTES 01180 * Used by stubless MIDL-generated code. 01181 */ 01182 LONG WINAPI NdrStubCall2( 01183 struct IRpcStubBuffer * pThis, 01184 struct IRpcChannelBuffer * pChannel, 01185 PRPC_MESSAGE pRpcMsg, 01186 DWORD * pdwStubPhase) 01187 { 01188 const MIDL_SERVER_INFO *pServerInfo; 01189 const MIDL_STUB_DESC *pStubDesc; 01190 PFORMAT_STRING pFormat; 01191 MIDL_STUB_MESSAGE stubMsg; 01192 /* pointer to start of stack to pass into stub implementation */ 01193 unsigned char * args; 01194 /* size of stack */ 01195 unsigned short stack_size; 01196 /* number of parameters. optional for client to give it to us */ 01197 unsigned int number_of_params; 01198 /* cache of Oif_flags from v2 procedure header */ 01199 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 01200 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 01201 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 01202 /* the type of pass we are currently doing */ 01203 enum stubless_phase phase; 01204 /* header for procedure string */ 01205 const NDR_PROC_HEADER *pProcHeader; 01206 /* location to put retval into */ 01207 LONG_PTR *retval_ptr = NULL; 01208 /* correlation cache */ 01209 ULONG_PTR NdrCorrCache[256]; 01210 01211 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); 01212 01213 if (pThis) 01214 pServerInfo = CStdStubBuffer_GetServerInfo(pThis); 01215 else 01216 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; 01217 01218 pStubDesc = pServerInfo->pStubDesc; 01219 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; 01220 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 01221 01222 TRACE("NDR Version: 0x%x\n", pStubDesc->Version); 01223 01224 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 01225 { 01226 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 01227 stack_size = pProcHeader->stack_size; 01228 pFormat += sizeof(NDR_PROC_HEADER_RPC); 01229 01230 } 01231 else 01232 { 01233 stack_size = pProcHeader->stack_size; 01234 pFormat += sizeof(NDR_PROC_HEADER); 01235 } 01236 01237 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 01238 01239 /* binding */ 01240 switch (pProcHeader->handle_type) 01241 { 01242 /* explicit binding: parse additional section */ 01243 case RPC_FC_BIND_EXPLICIT: 01244 switch (*pFormat) /* handle_type */ 01245 { 01246 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ 01247 pFormat += sizeof(NDR_EHD_PRIMITIVE); 01248 break; 01249 case RPC_FC_BIND_GENERIC: /* explicit generic */ 01250 pFormat += sizeof(NDR_EHD_GENERIC); 01251 break; 01252 case RPC_FC_BIND_CONTEXT: /* explicit context */ 01253 pFormat += sizeof(NDR_EHD_CONTEXT); 01254 break; 01255 default: 01256 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 01257 RpcRaiseException(RPC_X_BAD_STUB_DATA); 01258 } 01259 break; 01260 case RPC_FC_BIND_GENERIC: /* implicit generic */ 01261 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ 01262 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ 01263 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ 01264 break; 01265 default: 01266 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); 01267 RpcRaiseException(RPC_X_BAD_STUB_DATA); 01268 } 01269 01270 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 01271 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); 01272 else 01273 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); 01274 01275 /* create the full pointer translation tables, if requested */ 01276 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 01277 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); 01278 01279 /* store the RPC flags away */ 01280 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 01281 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 01282 01283 /* use alternate memory allocation routines */ 01284 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) 01285 #if 0 01286 NdrRpcSsEnableAllocate(&stubMsg); 01287 #else 01288 FIXME("Set RPCSS memory allocation routines\n"); 01289 #endif 01290 01291 TRACE("allocating memory for stack of size %x\n", stack_size); 01292 01293 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); 01294 stubMsg.StackTop = args; /* used by conformance of top-level objects */ 01295 01296 /* add the implicit This pointer as the first arg to the function if we 01297 * are calling an object method */ 01298 if (pThis) 01299 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; 01300 01301 if (pStubDesc->Version >= 0x20000) /* -Oicf format */ 01302 { 01303 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 01304 01305 Oif_flags = pOIFHeader->Oi2Flags; 01306 number_of_params = pOIFHeader->number_of_params; 01307 01308 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 01309 01310 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 01311 01312 if (Oif_flags.HasExtensions) 01313 { 01314 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat; 01315 ext_flags = pExtensions->Flags2; 01316 pFormat += pExtensions->Size; 01317 } 01318 01319 if (Oif_flags.HasPipes) 01320 { 01321 FIXME("pipes not supported yet\n"); 01322 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 01323 /* init pipes package */ 01324 /* NdrPipesInitialize(...) */ 01325 } 01326 if (ext_flags.HasNewCorrDesc) 01327 { 01328 /* initialize extra correlation package */ 01329 FIXME("new correlation description not implemented\n"); 01330 stubMsg.fHasNewCorrDesc = TRUE; 01331 } 01332 } 01333 else 01334 { 01335 pFormat = convert_old_args( &stubMsg, pFormat, stack_size, 01336 pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, 01337 /* reuse the correlation cache, it's not needed for v1 format */ 01338 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); 01339 } 01340 01341 /* convert strings, floating point values and endianess into our 01342 * preferred format */ 01343 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 01344 NdrConvert(&stubMsg, pFormat); 01345 01346 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) 01347 { 01348 TRACE("phase = %d\n", phase); 01349 switch (phase) 01350 { 01351 case STUBLESS_CALLSERVER: 01352 /* call the server function */ 01353 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) 01354 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); 01355 else 01356 { 01357 SERVER_ROUTINE func; 01358 LONG_PTR retval; 01359 01360 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 01361 { 01362 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; 01363 func = vtbl[pRpcMsg->ProcNum]; 01364 } 01365 else 01366 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; 01367 01368 /* FIXME: what happens with return values that don't fit into a single register on x86? */ 01369 retval = call_server_func(func, args, stack_size); 01370 01371 if (retval_ptr) 01372 { 01373 TRACE("stub implementation returned 0x%lx\n", retval); 01374 *retval_ptr = retval; 01375 } 01376 else 01377 TRACE("void stub implementation\n"); 01378 } 01379 01380 stubMsg.Buffer = NULL; 01381 stubMsg.BufferLength = 0; 01382 01383 break; 01384 case STUBLESS_GETBUFFER: 01385 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 01386 NdrStubGetBuffer(pThis, pChannel, &stubMsg); 01387 else 01388 { 01389 RPC_STATUS Status; 01390 01391 pRpcMsg->BufferLength = stubMsg.BufferLength; 01392 /* allocate buffer for [out] and [ret] params */ 01393 Status = I_RpcGetBuffer(pRpcMsg); 01394 if (Status) 01395 RpcRaiseException(Status); 01396 stubMsg.Buffer = pRpcMsg->Buffer; 01397 } 01398 break; 01399 case STUBLESS_UNMARSHAL: 01400 case STUBLESS_INITOUT: 01401 case STUBLESS_CALCSIZE: 01402 case STUBLESS_MARSHAL: 01403 case STUBLESS_FREE: 01404 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params); 01405 break; 01406 default: 01407 ERR("shouldn't reach here. phase %d\n", phase); 01408 break; 01409 } 01410 } 01411 01412 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); 01413 01414 if (ext_flags.HasNewCorrDesc) 01415 { 01416 /* free extra correlation package */ 01417 /* NdrCorrelationFree(&stubMsg); */ 01418 } 01419 01420 if (Oif_flags.HasPipes) 01421 { 01422 /* NdrPipesDone(...) */ 01423 } 01424 01425 /* free the full pointer translation tables */ 01426 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 01427 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); 01428 01429 /* free server function stack */ 01430 HeapFree(GetProcessHeap(), 0, args); 01431 01432 return S_OK; 01433 } 01434 01435 /*********************************************************************** 01436 * NdrServerCall2 [RPCRT4.@] 01437 */ 01438 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) 01439 { 01440 DWORD dwPhase; 01441 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); 01442 } 01443 01444 /*********************************************************************** 01445 * NdrStubCall [RPCRT4.@] 01446 */ 01447 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel, 01448 PRPC_MESSAGE msg, DWORD *phase ) 01449 { 01450 return NdrStubCall2( This, channel, msg, phase ); 01451 } 01452 01453 /*********************************************************************** 01454 * NdrServerCall [RPCRT4.@] 01455 */ 01456 void WINAPI NdrServerCall( PRPC_MESSAGE msg ) 01457 { 01458 DWORD phase; 01459 NdrStubCall( NULL, NULL, msg, &phase ); 01460 } 01461 01462 struct async_call_data 01463 { 01464 MIDL_STUB_MESSAGE *pStubMsg; 01465 const NDR_PROC_HEADER *pProcHeader; 01466 PFORMAT_STRING pHandleFormat; 01467 PFORMAT_STRING pParamFormat; 01468 RPC_BINDING_HANDLE hBinding; 01469 /* size of stack */ 01470 unsigned short stack_size; 01471 /* number of parameters. optional for client to give it to us */ 01472 unsigned int number_of_params; 01473 /* correlation cache */ 01474 ULONG_PTR NdrCorrCache[256]; 01475 }; 01476 01477 LONG_PTR CDECL ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) 01478 { 01479 /* pointer to start of stack where arguments start */ 01480 PRPC_MESSAGE pRpcMsg; 01481 PMIDL_STUB_MESSAGE pStubMsg; 01482 RPC_ASYNC_STATE *pAsync; 01483 struct async_call_data *async_call_data; 01484 /* procedure number */ 01485 unsigned short procedure_number; 01486 /* cache of Oif_flags from v2 procedure header */ 01487 INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; 01488 /* cache of extension flags from NDR_PROC_HEADER_EXTS */ 01489 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; 01490 /* header for procedure string */ 01491 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; 01492 /* -Oif or -Oicf generated format */ 01493 BOOL bV2Format = FALSE; 01494 RPC_STATUS status; 01495 01496 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); 01497 01498 /* Later NDR language versions probably won't be backwards compatible */ 01499 if (pStubDesc->Version > 0x50002) 01500 { 01501 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); 01502 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); 01503 } 01504 01505 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE)); 01506 if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY); 01507 async_call_data->pProcHeader = pProcHeader; 01508 01509 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1); 01510 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1); 01511 01512 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 01513 { 01514 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; 01515 async_call_data->stack_size = pProcHeader->stack_size; 01516 procedure_number = pProcHeader->proc_num; 01517 pFormat += sizeof(NDR_PROC_HEADER_RPC); 01518 } 01519 else 01520 { 01521 async_call_data->stack_size = pProcHeader->stack_size; 01522 procedure_number = pProcHeader->proc_num; 01523 pFormat += sizeof(NDR_PROC_HEADER); 01524 } 01525 TRACE("stack size: 0x%x\n", async_call_data->stack_size); 01526 TRACE("proc num: %d\n", procedure_number); 01527 01528 /* create the full pointer translation tables, if requested */ 01529 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 01530 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); 01531 01532 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) 01533 { 01534 ERR("objects not supported\n"); 01535 I_RpcFree(async_call_data); 01536 RpcRaiseException(RPC_X_BAD_STUB_DATA); 01537 } 01538 01539 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number); 01540 01541 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); 01542 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); 01543 01544 /* needed for conformance of top-level objects */ 01545 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size); 01546 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size); 01547 01548 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop; 01549 pAsync->StubInfo = async_call_data; 01550 async_call_data->pHandleFormat = pFormat; 01551 01552 pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding); 01553 if (!pFormat) goto done; 01554 01555 bV2Format = (pStubDesc->Version >= 0x20000); 01556 01557 if (bV2Format) 01558 { 01559 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = 01560 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; 01561 01562 Oif_flags = pOIFHeader->Oi2Flags; 01563 async_call_data->number_of_params = pOIFHeader->number_of_params; 01564 01565 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); 01566 01567 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) ); 01568 01569 if (Oif_flags.HasExtensions) 01570 { 01571 const NDR_PROC_HEADER_EXTS *pExtensions = 01572 (const NDR_PROC_HEADER_EXTS *)pFormat; 01573 ext_flags = pExtensions->Flags2; 01574 pFormat += pExtensions->Size; 01575 } 01576 } 01577 else 01578 { 01579 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size, 01580 pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, 01581 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 01582 &async_call_data->number_of_params ); 01583 } 01584 01585 async_call_data->pParamFormat = pFormat; 01586 01587 pStubMsg->BufferLength = 0; 01588 01589 /* store the RPC flags away */ 01590 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) 01591 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; 01592 01593 /* use alternate memory allocation routines */ 01594 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) 01595 NdrRpcSmSetClientToOsf(pStubMsg); 01596 01597 if (Oif_flags.HasPipes) 01598 { 01599 FIXME("pipes not supported yet\n"); 01600 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ 01601 /* init pipes package */ 01602 /* NdrPipesInitialize(...) */ 01603 } 01604 if (ext_flags.HasNewCorrDesc) 01605 { 01606 /* initialize extra correlation package */ 01607 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0); 01608 } 01609 01610 /* order of phases: 01611 * 1. CALCSIZE - calculate the buffer size 01612 * 2. GETBUFFER - allocate the buffer 01613 * 3. MARSHAL - marshal [in] params into the buffer 01614 * 4. SENDRECEIVE - send buffer 01615 * Then in NdrpCompleteAsyncClientCall: 01616 * 1. SENDRECEIVE - receive buffer 01617 * 2. UNMARSHAL - unmarshal [out] params from buffer 01618 */ 01619 01620 /* 1. CALCSIZE */ 01621 TRACE( "CALCSIZE\n" ); 01622 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL); 01623 01624 /* 2. GETBUFFER */ 01625 TRACE( "GETBUFFER\n" ); 01626 if (Oif_flags.HasPipes) 01627 /* NdrGetPipeBuffer(...) */ 01628 FIXME("pipes not supported yet\n"); 01629 else 01630 { 01631 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 01632 #if 0 01633 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 01634 #else 01635 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); 01636 #endif 01637 else 01638 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding); 01639 } 01640 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 01641 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync); 01642 if (status != RPC_S_OK) 01643 RpcRaiseException(status); 01644 01645 /* 3. MARSHAL */ 01646 TRACE( "MARSHAL\n" ); 01647 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL); 01648 01649 /* 4. SENDRECEIVE */ 01650 TRACE( "SEND\n" ); 01651 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 01652 /* send the [in] params only */ 01653 if (Oif_flags.HasPipes) 01654 /* NdrPipesSend(...) */ 01655 FIXME("pipes not supported yet\n"); 01656 else 01657 { 01658 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 01659 #if 0 01660 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 01661 #else 01662 FIXME("using auto handle - call NdrNsSend when it gets implemented\n"); 01663 #endif 01664 else 01665 { 01666 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer; 01667 status = I_RpcSend(pStubMsg->RpcMsg); 01668 if (status != RPC_S_OK) 01669 RpcRaiseException(status); 01670 } 01671 } 01672 01673 done: 01674 TRACE("returning 0\n"); 01675 return 0; 01676 } 01677 01678 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) 01679 { 01680 /* pointer to start of stack where arguments start */ 01681 PMIDL_STUB_MESSAGE pStubMsg; 01682 struct async_call_data *async_call_data; 01683 /* header for procedure string */ 01684 const NDR_PROC_HEADER * pProcHeader; 01685 RPC_STATUS status = RPC_S_OK; 01686 01687 if (!pAsync->StubInfo) 01688 return RPC_S_INVALID_ASYNC_HANDLE; 01689 01690 async_call_data = pAsync->StubInfo; 01691 pStubMsg = async_call_data->pStubMsg; 01692 pProcHeader = async_call_data->pProcHeader; 01693 01694 /* order of phases: 01695 * 1. CALCSIZE - calculate the buffer size 01696 * 2. GETBUFFER - allocate the buffer 01697 * 3. MARSHAL - marshal [in] params into the buffer 01698 * 4. SENDRECEIVE - send buffer 01699 * Then in NdrpCompleteAsyncClientCall: 01700 * 1. SENDRECEIVE - receive buffer 01701 * 2. UNMARSHAL - unmarshal [out] params from buffer 01702 */ 01703 01704 /* 1. SENDRECEIVE */ 01705 TRACE( "RECEIVE\n" ); 01706 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC; 01707 /* receive the [out] params */ 01708 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) 01709 #if 0 01710 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); 01711 #else 01712 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n"); 01713 #endif 01714 else 01715 { 01716 status = I_RpcReceive(pStubMsg->RpcMsg); 01717 if (status != RPC_S_OK) 01718 goto cleanup; 01719 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength; 01720 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; 01721 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; 01722 pStubMsg->Buffer = pStubMsg->BufferStart; 01723 } 01724 01725 /* convert strings, floating point values and endianness into our 01726 * preferred format */ 01727 #if 0 01728 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) 01729 NdrConvert(pStubMsg, pFormat); 01730 #endif 01731 01732 /* 2. UNMARSHAL */ 01733 TRACE( "UNMARSHAL\n" ); 01734 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL, 01735 NULL, async_call_data->number_of_params, Reply); 01736 01737 cleanup: 01738 if (pStubMsg->fHasNewCorrDesc) 01739 { 01740 /* free extra correlation package */ 01741 NdrCorrelationFree(pStubMsg); 01742 } 01743 01744 /* free the full pointer translation tables */ 01745 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) 01746 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); 01747 01748 /* free marshalling buffer */ 01749 NdrFreeBuffer(pStubMsg); 01750 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding); 01751 01752 I_RpcFree(pStubMsg->StackTop); 01753 I_RpcFree(async_call_data); 01754 01755 TRACE("-- 0x%x\n", status); 01756 return status; 01757 } 01758 01759 #ifdef __x86_64__ 01760 01761 __ASM_GLOBAL_FUNC( NdrAsyncClientCall, 01762 "movq %r8,0x18(%rsp)\n\t" 01763 "movq %r9,0x20(%rsp)\n\t" 01764 "leaq 0x18(%rsp),%r8\n\t" 01765 "subq $0x28,%rsp\n\t" 01766 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") 01767 "call " __ASM_NAME("ndr_async_client_call") "\n\t" 01768 "addq $0x28,%rsp\n\t" 01769 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") 01770 "ret" ); 01771 01772 #else /* __x86_64__ */ 01773 01774 /*********************************************************************** 01775 * NdrAsyncClientCall [RPCRT4.@] 01776 */ 01777 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) 01778 { 01779 __ms_va_list args; 01780 LONG_PTR ret; 01781 01782 __ms_va_start( args, format ); 01783 ret = ndr_async_client_call( desc, format, va_arg( args, void ** )); 01784 __ms_va_end( args ); 01785 return *(CLIENT_CALL_RETURN *)&ret; 01786 } 01787 01788 #endif /* __x86_64__ */ 01789 01790 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis, 01791 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, 01792 DWORD * pdwStubPhase) 01793 { 01794 FIXME("unimplemented, expect crash!\n"); 01795 return 0; 01796 } Generated on Sun May 27 2012 04:26:03 for ReactOS by
1.7.6.1
|