ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ndr_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 = &param->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 = &param->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 = &param->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, &params[i]);
00447             break;
00448         case STUBLESS_MARSHAL:
00449             if (params[i].attr.IsIn) call_marshaller(pStubMsg, pArg, &params[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, &params[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, &params[i]);
01109             break;
01110         case STUBLESS_FREE:
01111             if (params[i].attr.MustFree)
01112             {
01113                 call_freer(pStubMsg, pArg, &params[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, &params[i], 0);
01157             break;
01158         case STUBLESS_CALCSIZE:
01159             if (params[i].attr.IsOut || params[i].attr.IsReturn)
01160                 call_buffer_sizer(pStubMsg, pArg, &params[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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.