wine.inf: We should not override existing associations.
[wine/hacks.git] / dlls / rpcrt4 / ndr_stubless.c
blob2e56c9810ed7159f012d824c5cc3734863854693
1 /*
2 * NDR -Oi,-Oif,-Oicf Interpreter
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003-5 Robert Shearman (for CodeWeavers)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * TODO:
22 * - Pipes
23 * - Some types of binding handles
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winreg.h"
38 #include "objbase.h"
39 #include "rpc.h"
40 #include "rpcproxy.h"
41 #include "ndrtypes.h"
43 #include "wine/debug.h"
44 #include "wine/rpcfc.h"
46 #include "ndr_misc.h"
47 #include "cpsf.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
51 #define NDR_TABLE_MASK 127
53 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
55 NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
56 if (m) m(pStubMsg, pMemory, pFormat);
57 else
59 FIXME("format type 0x%x not implemented\n", pFormat[0]);
60 RpcRaiseException(RPC_X_BAD_STUB_DATA);
64 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
66 NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
67 if (m) return m(pStubMsg, pMemory, pFormat);
68 else
70 FIXME("format type 0x%x not implemented\n", pFormat[0]);
71 RpcRaiseException(RPC_X_BAD_STUB_DATA);
72 return NULL;
76 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc)
78 NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
79 if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
80 else
82 FIXME("format type 0x%x not implemented\n", pFormat[0]);
83 RpcRaiseException(RPC_X_BAD_STUB_DATA);
84 return NULL;
88 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
90 NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
91 if (m) m(pStubMsg, pMemory, pFormat);
94 static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
96 NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK];
97 if (m) return m(pStubMsg, pFormat);
98 else
100 FIXME("format type 0x%x not implemented\n", pFormat[0]);
101 RpcRaiseException(RPC_X_BAD_STUB_DATA);
102 return 0;
106 /* there can't be any alignment with the structures in this file */
107 #include "pshpack1.h"
109 #define STUBLESS_UNMARSHAL 1
110 #define STUBLESS_CALLSERVER 2
111 #define STUBLESS_CALCSIZE 3
112 #define STUBLESS_GETBUFFER 4
113 #define STUBLESS_MARSHAL 5
115 /* From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/parameter_descriptors.asp */
116 typedef struct _NDR_PROC_HEADER
118 /* type of handle to use:
119 * RPC_FC_BIND_EXPLICIT = 0 - Explicit handle.
120 * Handle is passed as a parameter to the function.
121 * Indicates that explicit handle information follows the header,
122 * which actually describes the handle.
123 * RPC_FC_BIND_GENERIC = 31 - Implicit handle with custom binding routines
124 * (MIDL_STUB_DESC::IMPLICIT_HANDLE_INFO::pGenericBindingInfo)
125 * RPC_FC_BIND_PRIMITIVE = 32 - Implicit handle using handle_t created by
126 * calling application
127 * RPC_FC_AUTO_HANDLE = 33 - Automatic handle
128 * RPC_FC_CALLBACK_HANDLE = 34 - undocmented
130 unsigned char handle_type;
132 /* procedure flags:
133 * Oi_FULL_PTR_USED = 0x01 - A full pointer can have the value NULL and can
134 * change during the call from NULL to non-NULL and supports aliasing
135 * and cycles. Indicates that the NdrFullPointerXlatInit function
136 * should be called.
137 * Oi_RPCSS_ALLOC_USED = 0x02 - Use RpcSS allocate/free routines instead of
138 * normal allocate/free routines
139 * Oi_OBJECT_PROC = 0x04 - Indicates a procedure that is part of an OLE
140 * interface, rather than a DCE RPC interface.
141 * Oi_HAS_RPCFLAGS = 0x08 - Indicates that the rpc_flags element is
142 * present in the header.
143 * Oi_HAS_COMM_OR_FAULT = 0x20 - If Oi_OBJECT_PROC not present only then
144 * indicates that the procedure has the comm_status or fault_status
145 * MIDL attribute.
146 * Oi_OBJ_USE_V2_INTERPRETER = 0x20 - If Oi_OBJECT_PROC present only
147 * then indicates that the format string is in -Oif or -Oicf format
148 * Oi_USE_NEW_INIT_ROUTINES = 0x40 - Use NdrXInitializeNew instead of
149 * NdrXInitialize?
151 unsigned char Oi_flags;
153 /* the zero-based index of the procedure */
154 unsigned short proc_num;
156 /* total size of all parameters on the stack, including any "this"
157 * pointer and/or return value */
158 unsigned short stack_size;
159 } NDR_PROC_HEADER;
161 /* same as above struct except additional element rpc_flags */
162 typedef struct _NDR_PROC_HEADER_RPC
164 unsigned char handle_type;
165 unsigned char Oi_flags;
168 * RPCF_Idempotent = 0x0001 - [idempotent] MIDL attribute
169 * RPCF_Broadcast = 0x0002 - [broadcast] MIDL attribute
170 * RPCF_Maybe = 0x0004 - [maybe] MIDL attribute
171 * Reserved = 0x0008 - 0x0080
172 * RPCF_Message = 0x0100 - [message] MIDL attribute
173 * Reserved = 0x0200 - 0x1000
174 * RPCF_InputSynchronous = 0x2000 - unknown
175 * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
176 * Reserved = 0x8000
178 unsigned long rpc_flags;
179 unsigned short proc_num;
180 unsigned short stack_size;
182 } NDR_PROC_HEADER_RPC;
184 typedef struct _NDR_PROC_PARTIAL_OIF_HEADER
186 /* the pre-computed client buffer size so that interpreter can skip all
187 * or some (if the flag RPC_FC_PROC_OI2F_CLTMUSTSIZE is specified) of the
188 * sizing pass */
189 unsigned short constant_client_buffer_size;
191 /* the pre-computed server buffer size so that interpreter can skip all
192 * or some (if the flag RPC_FC_PROC_OI2F_SRVMUSTSIZE is specified) of the
193 * sizing pass */
194 unsigned short constant_server_buffer_size;
196 INTERPRETER_OPT_FLAGS Oi2Flags;
198 /* number of params */
199 unsigned char number_of_params;
200 } NDR_PROC_PARTIAL_OIF_HEADER;
202 typedef struct _NDR_PARAM_OI_BASETYPE
204 /* parameter direction. One of:
205 * FC_IN_PARAM_BASETYPE = 0x4e - an in param
206 * FC_RETURN_PARAM_BASETYPE = 0x53 - a return param
208 unsigned char param_direction;
210 /* One of: FC_BYTE,FC_CHAR,FC_SMALL,FC_USMALL,FC_WCHAR,FC_SHORT,FC_USHORT,
211 * FC_LONG,FC_ULONG,FC_FLOAT,FC_HYPER,FC_DOUBLE,FC_ENUM16,FC_ENUM32,
212 * FC_ERROR_STATUS_T,FC_INT3264,FC_UINT3264 */
213 unsigned char type_format_char;
214 } NDR_PARAM_OI_BASETYPE;
216 typedef struct _NDR_PARAM_OI_OTHER
218 /* One of:
219 * FC_IN_PARAM = 0x4d - An in param
220 * FC_IN_OUT_PARAM = 0x50 - An in/out param
221 * FC_OUT_PARAM = 0x51 - An out param
222 * FC_RETURN_PARAM = 0x52 - A return value
223 * FC_IN_PARAM_NO_FREE_INST = 0x4f - A param for which no freeing is done
225 unsigned char param_direction;
227 /* Size of param on stack in NUMBERS OF INTS */
228 unsigned char stack_size;
230 /* offset in the type format string table */
231 unsigned short type_offset;
232 } NDR_PARAM_OI_OTHER;
234 typedef struct _NDR_PARAM_OIF_BASETYPE
236 PARAM_ATTRIBUTES param_attributes;
238 /* the offset on the calling stack where the parameter is located */
239 unsigned short stack_offset;
241 /* see NDR_PARAM_OI_BASETYPE::type_format_char */
242 unsigned char type_format_char;
244 /* always FC_PAD */
245 unsigned char unused;
246 } NDR_PARAM_OIF_BASETYPE;
248 typedef struct _NDR_PARAM_OIF_OTHER
250 PARAM_ATTRIBUTES param_attributes;
252 /* see NDR_PARAM_OIF_BASETYPE::stack_offset */
253 unsigned short stack_offset;
255 /* offset into the provided type format string where the type for this
256 * parameter starts */
257 unsigned short type_offset;
258 } NDR_PARAM_OIF_OTHER;
260 /* explicit handle description for FC_BIND_PRIMITIVE type */
261 typedef struct _NDR_EHD_PRIMITIVE
263 /* FC_BIND_PRIMITIVE */
264 unsigned char handle_type;
266 /* is the handle passed in via a pointer? */
267 unsigned char flag;
269 /* offset from the beginning of the stack to the handle in bytes */
270 unsigned short offset;
271 } NDR_EHD_PRIMITIVE;
273 /* explicit handle description for FC_BIND_GENERIC type */
274 typedef struct _NDR_EHD_GENERIC
276 /* FC_BIND_GENERIC */
277 unsigned char handle_type;
279 /* upper 4bits is a flag indicating whether the handle is passed in
280 * via a pointer. lower 4bits is the size of the user defined generic
281 * handle type. the size must be less than or equal to the machine
282 * register size */
283 unsigned char flag_and_size;
285 /* offset from the beginning of the stack to the handle in bytes */
286 unsigned short offset;
288 /* the index into the aGenericBindingRoutinesPairs field of MIDL_STUB_DESC
289 * giving the bind and unbind routines for the handle */
290 unsigned char binding_routine_pair_index;
292 /* FC_PAD */
293 unsigned char unused;
294 } NDR_EHD_GENERIC;
296 /* explicit handle description for FC_BIND_CONTEXT type */
297 typedef struct _NDR_EHD_CONTEXT
299 /* FC_BIND_CONTEXT */
300 unsigned char handle_type;
302 /* Any of the following flags:
303 * NDR_CONTEXT_HANDLE_CANNOT_BE_NULL = 0x01
304 * NDR_CONTEXT_HANDLE_SERIALIZE = 0x02
305 * NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04
306 * NDR_STRICT_CONTEXT_HANDLE = 0x08
307 * HANDLE_PARAM_IS_OUT = 0x20
308 * HANDLE_PARAM_IS_RETURN = 0x21
309 * HANDLE_PARAM_IS_IN = 0x40
310 * HANDLE_PARAM_IS_VIA_PTR = 0x80
312 unsigned char flags;
314 /* offset from the beginning of the stack to the handle in bytes */
315 unsigned short offset;
317 /* zero-based index on rundown routine in apfnNdrRundownRoutines field
318 * of MIDL_STUB_DESC */
319 unsigned char context_rundown_routine_index;
321 /* varies depending on NDR version used.
322 * V1: zero-based index into parameters
323 * V2: zero-based index into handles that are parameters */
324 unsigned char param_num;
325 } NDR_EHD_CONTEXT;
327 #include "poppack.h"
329 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
331 #if 0 /* these functions are not defined yet */
332 pMessage->pfnAllocate = NdrRpcSmClientAllocate;
333 pMessage->pfnFree = NdrRpcSmClientFree;
334 #endif
337 static void WINAPI dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes)
339 if (param_attributes.MustSize) TRACE(" MustSize");
340 if (param_attributes.MustFree) TRACE(" MustFree");
341 if (param_attributes.IsPipe) TRACE(" IsPipe");
342 if (param_attributes.IsIn) TRACE(" IsIn");
343 if (param_attributes.IsOut) TRACE(" IsOut");
344 if (param_attributes.IsReturn) TRACE(" IsReturn");
345 if (param_attributes.IsBasetype) TRACE(" IsBasetype");
346 if (param_attributes.IsByValue) TRACE(" IsByValue");
347 if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef");
348 if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst");
349 if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish");
350 if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
353 static void WINAPI dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
355 if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize");
356 if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize");
357 if (Oi2Flags.HasReturn) TRACE(" HasReturn");
358 if (Oi2Flags.HasPipes) TRACE(" HasPipes");
359 if (Oi2Flags.Unused) TRACE(" Unused");
360 if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid");
361 if (Oi2Flags.HasExtensions) TRACE(" HasExtensions");
362 if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle");
363 TRACE("\n");
366 #define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset))
368 static PFORMAT_STRING client_get_handle(
369 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
370 PFORMAT_STRING pFormat, handle_t *phBinding)
372 /* binding */
373 switch (pProcHeader->handle_type)
375 /* explicit binding: parse additional section */
376 case RPC_FC_BIND_EXPLICIT:
377 switch (*pFormat) /* handle_type */
379 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
381 NDR_EHD_PRIMITIVE * pDesc = (NDR_EHD_PRIMITIVE *)pFormat;
383 TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
385 if (pDesc->flag) /* pointer to binding */
386 *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
387 else
388 *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
389 return pFormat + sizeof(NDR_EHD_PRIMITIVE);
391 case RPC_FC_BIND_GENERIC: /* explicit generic */
393 NDR_EHD_GENERIC * pDesc = (NDR_EHD_GENERIC *)pFormat;
394 void *pObject = NULL;
395 void *pArg;
396 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
398 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
400 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
401 pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
402 else
403 pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
404 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
405 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
406 *phBinding = pGenPair->pfnBind(pObject);
407 return pFormat + sizeof(NDR_EHD_GENERIC);
409 case RPC_FC_BIND_CONTEXT: /* explicit context */
411 NDR_EHD_CONTEXT * pDesc = (NDR_EHD_CONTEXT *)pFormat;
412 NDR_CCONTEXT context_handle;
413 TRACE("Explicit bind context\n");
414 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
416 TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
417 context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
419 else
420 context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
421 if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) &&
422 !context_handle)
424 ERR("null context handle isn't allowed\n");
425 RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);
426 return NULL;
428 *phBinding = NDRCContextBinding(context_handle);
429 /* FIXME: should we store this structure in stubMsg.pContext? */
430 return pFormat + sizeof(NDR_EHD_CONTEXT);
432 default:
433 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
434 RpcRaiseException(RPC_X_BAD_STUB_DATA);
436 break;
437 case RPC_FC_BIND_GENERIC: /* implicit generic */
438 FIXME("RPC_FC_BIND_GENERIC\n");
439 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
440 break;
441 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
442 TRACE("Implicit primitive handle\n");
443 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
444 break;
445 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
446 FIXME("RPC_FC_CALLBACK_HANDLE\n");
447 break;
448 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
449 /* strictly speaking, it isn't necessary to set hBinding here
450 * since it isn't actually used (hence the automatic in its name),
451 * but then why does MIDL generate a valid entry in the
452 * MIDL_STUB_DESC for it? */
453 TRACE("Implicit auto handle\n");
454 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
455 break;
456 default:
457 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
458 RpcRaiseException(RPC_X_BAD_STUB_DATA);
460 return pFormat;
463 static void client_free_handle(
464 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
465 PFORMAT_STRING pFormat, handle_t hBinding)
467 /* binding */
468 switch (pProcHeader->handle_type)
470 /* explicit binding: parse additional section */
471 case RPC_FC_BIND_EXPLICIT:
472 switch (*pFormat) /* handle_type */
474 case RPC_FC_BIND_GENERIC: /* explicit generic */
476 NDR_EHD_GENERIC * pDesc = (NDR_EHD_GENERIC *)pFormat;
477 void *pObject = NULL;
478 void *pArg;
479 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
481 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
483 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
484 pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
485 else
486 pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
487 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
488 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
489 pGenPair->pfnUnbind(pObject, hBinding);
490 break;
492 case RPC_FC_BIND_CONTEXT: /* explicit context */
493 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
494 break;
495 default:
496 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
497 RpcRaiseException(RPC_X_BAD_STUB_DATA);
499 break;
500 case RPC_FC_BIND_GENERIC: /* implicit generic */
501 FIXME("RPC_FC_BIND_GENERIC\n");
502 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
503 break;
504 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
505 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
506 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
507 break;
508 default:
509 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
510 RpcRaiseException(RPC_X_BAD_STUB_DATA);
514 /* the return type should be CLIENT_CALL_RETURN, but this is incompatible
515 * with the way gcc returns structures. "void *" should be the largest type
516 * that MIDL should allow you to return anyway */
517 LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...)
519 /* pointer to start of stack where arguments start */
520 RPC_MESSAGE rpcMsg;
521 MIDL_STUB_MESSAGE stubMsg;
522 handle_t hBinding = NULL;
523 /* procedure number */
524 unsigned short procedure_number;
525 /* size of stack */
526 unsigned short stack_size;
527 /* number of parameters. optional for client to give it to us */
528 unsigned char number_of_params = ~0;
529 /* cache of Oif_flags from v2 procedure header */
530 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
531 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
532 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
533 /* the type of pass we are currently doing */
534 int phase;
535 /* header for procedure string */
536 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
537 /* -Oif or -Oicf generated format */
538 BOOL bV2Format = FALSE;
539 /* the value to return to the client from the remote procedure */
540 LONG_PTR RetVal = 0;
541 /* the pointer to the object when in OLE mode */
542 void * This = NULL;
543 PFORMAT_STRING pHandleFormat;
545 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
547 /* Later NDR language versions probably won't be backwards compatible */
548 if (pStubDesc->Version > 0x50002)
550 FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
551 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
554 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
556 NDR_PROC_HEADER_RPC * pProcHeader = (NDR_PROC_HEADER_RPC *)&pFormat[0];
557 stack_size = pProcHeader->stack_size;
558 procedure_number = pProcHeader->proc_num;
559 pFormat += sizeof(NDR_PROC_HEADER_RPC);
561 else
563 stack_size = pProcHeader->stack_size;
564 procedure_number = pProcHeader->proc_num;
565 TRACE("proc num: %d\n", procedure_number);
566 pFormat += sizeof(NDR_PROC_HEADER);
569 /* create the full pointer translation tables, if requested */
570 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
571 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
573 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
575 /* object is always the first argument */
576 This = **(void ***)(&pFormat+1);
577 NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
579 else
580 NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
582 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
583 TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
585 /* needed for conformance of top-level objects */
586 #ifdef __i386__
587 stubMsg.StackTop = *(unsigned char **)(&pFormat+1);
588 #else
589 # warning Stack not retrieved for your CPU architecture
590 #endif
592 pHandleFormat = pFormat;
594 /* we only need a handle if this isn't an object method */
595 if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT))
597 pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding);
598 if (!pFormat) return 0;
601 bV2Format = (pStubDesc->Version >= 0x20000);
603 if (bV2Format)
605 NDR_PROC_PARTIAL_OIF_HEADER * pOIFHeader =
606 (NDR_PROC_PARTIAL_OIF_HEADER*)pFormat;
608 Oif_flags = pOIFHeader->Oi2Flags;
609 number_of_params = pOIFHeader->number_of_params;
611 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
614 TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
616 if (Oif_flags.HasExtensions)
618 NDR_PROC_HEADER_EXTS * pExtensions =
619 (NDR_PROC_HEADER_EXTS *)pFormat;
620 ext_flags = pExtensions->Flags2;
621 pFormat += pExtensions->Size;
624 stubMsg.BufferLength = 0;
626 /* store the RPC flags away */
627 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
628 rpcMsg.RpcFlags = ((NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
630 /* use alternate memory allocation routines */
631 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
632 NdrRpcSmSetClientToOsf(&stubMsg);
634 if (Oif_flags.HasPipes)
636 FIXME("pipes not supported yet\n");
637 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
638 /* init pipes package */
639 /* NdrPipesInitialize(...) */
641 if (ext_flags.HasNewCorrDesc)
643 /* initialize extra correlation package */
644 FIXME("new correlation description not implemented\n");
645 stubMsg.fHasNewCorrDesc = TRUE;
648 /* order of phases:
649 * 1. PROXY_CALCSIZE - calculate the buffer size
650 * 2. PROXY_GETBUFFER - allocate the buffer
651 * 3. PROXY_MARHSAL - marshal [in] params into the buffer
652 * 4. PROXY_SENDRECEIVE - send/receive buffer
653 * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
655 for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
657 /* current format string offset */
658 int current_offset;
659 /* current stack offset */
660 unsigned short current_stack_offset;
661 /* counter */
662 unsigned short i;
664 TRACE("phase = %d\n", phase);
665 switch (phase)
667 case PROXY_GETBUFFER:
668 /* allocate the buffer */
669 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
670 NdrProxyGetBuffer(This, &stubMsg);
671 else if (Oif_flags.HasPipes)
672 /* NdrGetPipeBuffer(...) */
673 FIXME("pipes not supported yet\n");
674 else
676 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
677 #if 0
678 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
679 #else
680 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
681 #endif
682 else
683 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
685 break;
686 case PROXY_SENDRECEIVE:
687 /* send the [in] params and receive the [out] and [retval]
688 * params */
689 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
690 NdrProxySendReceive(This, &stubMsg);
691 else if (Oif_flags.HasPipes)
692 /* NdrPipesSendReceive(...) */
693 FIXME("pipes not supported yet\n");
694 else
696 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
697 #if 0
698 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
699 #else
700 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
701 #endif
702 else
703 NdrSendReceive(&stubMsg, stubMsg.Buffer);
706 /* convert strings, floating point values and endianess into our
707 * preferred format */
708 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
709 NdrConvert(&stubMsg, pFormat);
711 break;
712 case PROXY_CALCSIZE:
713 case PROXY_MARSHAL:
714 case PROXY_UNMARSHAL:
715 current_offset = 0;
716 current_stack_offset = 0;
718 /* NOTE: V1 style format does't terminate on the number_of_params
719 * condition as it doesn't have this attribute. Instead it
720 * terminates when the stack size given in the header is exceeded.
722 for (i = 0; i < number_of_params; i++)
724 if (bV2Format) /* new parameter format */
726 NDR_PARAM_OIF_BASETYPE * pParam =
727 (NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
728 unsigned char * pArg;
730 current_stack_offset = pParam->stack_offset;
731 pArg = ARG_FROM_OFFSET(stubMsg, current_stack_offset);
733 TRACE("param[%d]: new format\n", i);
734 TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
735 TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
736 TRACE("\tmemory addr (before): %p\n", pArg);
738 if (pParam->param_attributes.IsBasetype)
740 const unsigned char * pTypeFormat =
741 &pParam->type_format_char;
743 if (pParam->param_attributes.IsSimpleRef)
744 pArg = *(unsigned char **)pArg;
746 TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
748 switch (phase)
750 case PROXY_CALCSIZE:
751 if (pParam->param_attributes.IsIn)
752 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
753 break;
754 case PROXY_MARSHAL:
755 if (pParam->param_attributes.IsIn)
756 call_marshaller(&stubMsg, pArg, pTypeFormat);
757 break;
758 case PROXY_UNMARSHAL:
759 if (pParam->param_attributes.IsOut)
761 unsigned char *pRetVal = (unsigned char *)&RetVal;
762 if (pParam->param_attributes.IsReturn)
763 call_unmarshaller(&stubMsg, &pRetVal, pTypeFormat, 0);
764 else
765 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
766 TRACE("pRetVal = %p\n", pRetVal);
768 break;
769 default:
770 RpcRaiseException(RPC_S_INTERNAL_ERROR);
773 current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
775 else
777 NDR_PARAM_OIF_OTHER * pParamOther =
778 (NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
780 const unsigned char * pTypeFormat =
781 &(pStubDesc->pFormatTypes[pParamOther->type_offset]);
783 /* if a simple ref pointer then we have to do the
784 * check for the pointer being non-NULL. */
785 if (pParam->param_attributes.IsSimpleRef)
787 if (!*(unsigned char **)pArg)
788 RpcRaiseException(RPC_X_NULL_REF_POINTER);
791 TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat);
793 switch (phase)
795 case PROXY_CALCSIZE:
796 if (pParam->param_attributes.IsIn)
798 if (pParam->param_attributes.IsByValue)
799 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
800 else
801 call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
803 break;
804 case PROXY_MARSHAL:
805 if (pParam->param_attributes.IsIn)
807 if (pParam->param_attributes.IsByValue)
808 call_marshaller(&stubMsg, pArg, pTypeFormat);
809 else
810 call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
812 break;
813 case PROXY_UNMARSHAL:
814 if (pParam->param_attributes.IsOut)
816 unsigned char *pRetVal = (unsigned char *)&RetVal;
817 if (pParam->param_attributes.IsReturn)
818 call_unmarshaller(&stubMsg, &pRetVal, pTypeFormat, 0);
819 else if (pParam->param_attributes.IsByValue)
820 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
821 else
822 call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
824 break;
825 default:
826 RpcRaiseException(RPC_S_INTERNAL_ERROR);
829 current_offset += sizeof(NDR_PARAM_OIF_OTHER);
831 TRACE("\tmemory addr (after): %p\n", pArg);
833 else /* old parameter format */
835 NDR_PARAM_OI_BASETYPE * pParam =
836 (NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
837 unsigned char * pArg = ARG_FROM_OFFSET(stubMsg, current_stack_offset);
839 /* no more parameters; exit loop */
840 if (current_stack_offset > stack_size)
841 break;
843 TRACE("param[%d]: old format\n", i);
844 TRACE("\tparam_direction: %x\n", pParam->param_direction);
845 TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
846 TRACE("\tmemory addr (before): %p\n", pArg);
848 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
849 pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
851 const unsigned char * pTypeFormat =
852 &pParam->type_format_char;
854 TRACE("\tbase type 0x%02x\n", *pTypeFormat);
856 switch (phase)
858 case PROXY_CALCSIZE:
859 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
860 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
861 break;
862 case PROXY_MARSHAL:
863 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
864 call_marshaller(&stubMsg, pArg, pTypeFormat);
865 break;
866 case PROXY_UNMARSHAL:
867 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
869 if (pParam->param_direction & RPC_FC_RETURN_PARAM)
870 call_unmarshaller(&stubMsg, (unsigned char **)&RetVal, pTypeFormat, 0);
871 else
872 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
874 break;
875 default:
876 RpcRaiseException(RPC_S_INTERNAL_ERROR);
879 current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat);
880 current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
882 else
884 NDR_PARAM_OI_OTHER * pParamOther =
885 (NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
887 const unsigned char *pTypeFormat =
888 &pStubDesc->pFormatTypes[pParamOther->type_offset];
890 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
892 switch (phase)
894 case PROXY_CALCSIZE:
895 if (pParam->param_direction == RPC_FC_IN_PARAM ||
896 pParam->param_direction & RPC_FC_IN_OUT_PARAM)
897 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
898 break;
899 case PROXY_MARSHAL:
900 if (pParam->param_direction == RPC_FC_IN_PARAM ||
901 pParam->param_direction & RPC_FC_IN_OUT_PARAM)
902 call_marshaller(&stubMsg, pArg, pTypeFormat);
903 break;
904 case PROXY_UNMARSHAL:
905 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
906 pParam->param_direction == RPC_FC_OUT_PARAM)
907 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
908 else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
909 call_unmarshaller(&stubMsg, (unsigned char **)&RetVal, pTypeFormat, 0);
910 break;
911 default:
912 RpcRaiseException(RPC_S_INTERNAL_ERROR);
915 current_stack_offset += pParamOther->stack_size * sizeof(INT);
916 current_offset += sizeof(NDR_PARAM_OI_OTHER);
918 TRACE("\tmemory addr (after): %p\n", pArg);
922 break;
923 default:
924 ERR("shouldn't reach here. phase %d\n", phase);
925 break;
929 if (ext_flags.HasNewCorrDesc)
931 /* free extra correlation package */
932 /* NdrCorrelationFree(&stubMsg); */
935 if (Oif_flags.HasPipes)
937 /* NdrPipesDone(...) */
940 /* free the full pointer translation tables */
941 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
942 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
944 /* free marshalling buffer */
945 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
946 NdrProxyFreeBuffer(This, &stubMsg);
947 else
949 NdrFreeBuffer(&stubMsg);
950 client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding);
953 TRACE("RetVal = 0x%lx\n", RetVal);
955 return RetVal;
958 /* calls a function with the specificed arguments, restoring the stack
959 * properly afterwards as we don't know the calling convention of the
960 * function */
961 #if defined __i386__ && defined _MSC_VER
962 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
964 __asm
966 push ebp
967 push edi ; Save registers
968 push esi
969 mov ebp, esp
970 mov eax, [ebp+16] ; Get stack size
971 sub esp, eax ; Make room in stack for arguments
972 mov edi, esp
973 mov ecx, eax
974 mov esi, [ebp+12]
975 shr ecx, 2
977 rep movsd ; Copy dword blocks
978 call [ebp+8] ; Call function
979 lea esp, [ebp-8] ; Restore stack
980 pop esi ; Restore registers
981 pop edi
982 pop ebp
986 #elif defined __i386__ && defined __GNUC__
987 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
988 __ASM_GLOBAL_FUNC(call_server_func,
989 "pushl %ebp\n\t"
990 "movl %esp, %ebp\n\t"
991 "pushl %edi\n\t" /* Save registers */
992 "pushl %esi\n\t"
993 "movl 16(%ebp), %eax\n\t" /* Get stack size */
994 "subl %eax, %esp\n\t" /* Make room in stack for arguments */
995 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for MacOS X */
996 "movl %esp, %edi\n\t"
997 "movl %eax, %ecx\n\t"
998 "movl 12(%ebp), %esi\n\t"
999 "shrl $2, %ecx\n\t" /* divide by 4 */
1000 "cld\n\t"
1001 "rep; movsl\n\t" /* Copy dword blocks */
1002 "call *8(%ebp)\n\t" /* Call function */
1003 "leal -8(%ebp), %esp\n\t" /* Restore stack */
1004 "popl %esi\n\t" /* Restore registers */
1005 "popl %edi\n\t"
1006 "popl %ebp\n\t"
1007 "ret\n" );
1008 #else
1009 #warning call_server_func not implemented for your architecture
1010 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
1012 FIXME("Not implemented for your architecture\n");
1013 return 0;
1015 #endif
1017 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
1019 DWORD size;
1020 switch(*pFormat)
1022 case RPC_FC_STRUCT:
1023 size = *(const WORD*)(pFormat + 2);
1024 break;
1025 case RPC_FC_CARRAY:
1026 size = *(const WORD*)(pFormat + 2);
1027 ComputeConformance(pStubMsg, NULL, pFormat + 4, 0);
1028 size *= pStubMsg->MaxCount;
1029 break;
1030 default:
1031 FIXME("Unhandled type %02x\n", *pFormat);
1032 /* fallthrough */
1033 case RPC_FC_RP:
1034 size = sizeof(void *);
1035 break;
1037 return size;
1040 /* FIXME: need to free some stuff in here too */
1041 long WINAPI NdrStubCall2(
1042 struct IRpcStubBuffer * pThis,
1043 struct IRpcChannelBuffer * pChannel,
1044 PRPC_MESSAGE pRpcMsg,
1045 unsigned long * pdwStubPhase)
1047 const MIDL_SERVER_INFO *pServerInfo;
1048 const MIDL_STUB_DESC *pStubDesc;
1049 PFORMAT_STRING pFormat;
1050 MIDL_STUB_MESSAGE stubMsg;
1051 /* pointer to start of stack to pass into stub implementation */
1052 unsigned char * args;
1053 /* size of stack */
1054 unsigned short stack_size;
1055 /* current stack offset */
1056 unsigned short current_stack_offset;
1057 /* number of parameters. optional for client to give it to us */
1058 unsigned char number_of_params = ~0;
1059 /* counter */
1060 unsigned short i;
1061 /* cache of Oif_flags from v2 procedure header */
1062 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1063 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1064 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1065 /* the type of pass we are currently doing */
1066 int phase;
1067 /* header for procedure string */
1068 const NDR_PROC_HEADER *pProcHeader;
1069 /* offset in format string for start of params */
1070 int parameter_start_offset;
1071 /* current format string offset */
1072 int current_offset;
1073 /* -Oif or -Oicf generated format */
1074 BOOL bV2Format = FALSE;
1075 /* location to put retval into */
1076 LONG_PTR *retval_ptr = NULL;
1078 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1080 if (pThis)
1081 pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1082 else
1083 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1085 pStubDesc = pServerInfo->pStubDesc;
1086 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1087 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1089 /* Later NDR language versions probably won't be backwards compatible */
1090 if (pStubDesc->Version > 0x50002)
1092 FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
1093 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1096 /* create the full pointer translation tables, if requested */
1097 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1098 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1100 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1102 NDR_PROC_HEADER_RPC * pProcHeader = (NDR_PROC_HEADER_RPC *)&pFormat[0];
1103 stack_size = pProcHeader->stack_size;
1104 current_offset = sizeof(NDR_PROC_HEADER_RPC);
1107 else
1109 stack_size = pProcHeader->stack_size;
1110 current_offset = sizeof(NDR_PROC_HEADER);
1113 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1115 /* binding */
1116 switch (pProcHeader->handle_type)
1118 /* explicit binding: parse additional section */
1119 case RPC_FC_BIND_EXPLICIT:
1120 switch (pFormat[current_offset]) /* handle_type */
1122 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
1123 current_offset += sizeof(NDR_EHD_PRIMITIVE);
1124 break;
1125 case RPC_FC_BIND_GENERIC: /* explicit generic */
1126 current_offset += sizeof(NDR_EHD_GENERIC);
1127 break;
1128 case RPC_FC_BIND_CONTEXT: /* explicit context */
1129 current_offset += sizeof(NDR_EHD_CONTEXT);
1130 break;
1131 default:
1132 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1133 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1135 break;
1136 case RPC_FC_BIND_GENERIC: /* implicit generic */
1137 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
1138 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
1139 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
1140 break;
1141 default:
1142 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1143 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1146 bV2Format = (pStubDesc->Version >= 0x20000);
1148 if (bV2Format)
1150 NDR_PROC_PARTIAL_OIF_HEADER * pOIFHeader =
1151 (NDR_PROC_PARTIAL_OIF_HEADER*)&pFormat[current_offset];
1153 Oif_flags = pOIFHeader->Oi2Flags;
1154 number_of_params = pOIFHeader->number_of_params;
1156 current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1159 TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
1161 if (Oif_flags.HasExtensions)
1163 NDR_PROC_HEADER_EXTS * pExtensions =
1164 (NDR_PROC_HEADER_EXTS *)&pFormat[current_offset];
1165 ext_flags = pExtensions->Flags2;
1166 current_offset += pExtensions->Size;
1169 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1170 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1171 else
1172 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1174 /* store the RPC flags away */
1175 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1176 pRpcMsg->RpcFlags = ((NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1178 /* use alternate memory allocation routines */
1179 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1180 #if 0
1181 NdrRpcSsEnableAllocate(&stubMsg);
1182 #else
1183 FIXME("Set RPCSS memory allocation routines\n");
1184 #endif
1186 if (Oif_flags.HasPipes)
1188 FIXME("pipes not supported yet\n");
1189 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1190 /* init pipes package */
1191 /* NdrPipesInitialize(...) */
1193 if (ext_flags.HasNewCorrDesc)
1195 /* initialize extra correlation package */
1196 FIXME("new correlation description not implemented\n");
1197 stubMsg.fHasNewCorrDesc = TRUE;
1200 /* convert strings, floating point values and endianess into our
1201 * preferred format */
1202 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1203 NdrConvert(&stubMsg, pFormat);
1205 parameter_start_offset = current_offset;
1207 TRACE("allocating memory for stack of size %x\n", stack_size);
1209 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size);
1210 stubMsg.StackTop = args; /* used by conformance of top-level objects */
1212 /* add the implicit This pointer as the first arg to the function if we
1213 * are calling an object method */
1214 if (pThis)
1215 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1217 /* order of phases:
1218 * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer
1219 * 2. STUBLESS_CALLSERVER - send/receive buffer
1220 * 3. STUBLESS_CALCSIZE - get [out] buffer size
1221 * 4. STUBLESS_GETBUFFER - allocate [out] buffer
1222 * 5. STUBLESS_MARHSAL - marshal [out] params to buffer
1224 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_MARSHAL; phase++)
1226 TRACE("phase = %d\n", phase);
1227 switch (phase)
1229 case STUBLESS_CALLSERVER:
1230 /* call the server function */
1231 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1232 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1233 else
1235 SERVER_ROUTINE func;
1236 LONG_PTR retval;
1238 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1240 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1241 func = vtbl[pRpcMsg->ProcNum];
1243 else
1244 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1246 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1247 retval = call_server_func(func, args, stack_size);
1249 if (retval_ptr)
1251 TRACE("stub implementation returned 0x%lx\n", retval);
1252 *retval_ptr = retval;
1254 else
1255 TRACE("void stub implementation\n");
1258 stubMsg.Buffer = NULL;
1259 stubMsg.BufferLength = 0;
1261 break;
1262 case STUBLESS_GETBUFFER:
1263 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1264 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1265 else
1267 RPC_STATUS Status;
1269 pRpcMsg->BufferLength = stubMsg.BufferLength;
1270 /* allocate buffer for [out] and [ret] params */
1271 Status = I_RpcGetBuffer(pRpcMsg);
1272 if (Status)
1273 RpcRaiseException(Status);
1274 stubMsg.BufferStart = pRpcMsg->Buffer;
1275 stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength;
1276 stubMsg.Buffer = stubMsg.BufferStart;
1278 break;
1279 case STUBLESS_MARSHAL:
1280 case STUBLESS_UNMARSHAL:
1281 case STUBLESS_CALCSIZE:
1282 current_offset = parameter_start_offset;
1283 current_stack_offset = 0;
1285 /* NOTE: V1 style format does't terminate on the number_of_params
1286 * condition as it doesn't have this attribute. Instead it
1287 * terminates when the stack size given in the header is exceeded.
1289 for (i = 0; i < number_of_params; i++)
1291 if (bV2Format) /* new parameter format */
1293 const NDR_PARAM_OIF_BASETYPE *pParam =
1294 (NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
1295 unsigned char *pArg;
1297 current_stack_offset = pParam->stack_offset;
1298 pArg = (unsigned char *)(args+current_stack_offset);
1300 TRACE("param[%d]: new format\n", i);
1301 TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
1302 TRACE("\tstack_offset: %x\n", current_stack_offset);
1303 TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
1305 if (pParam->param_attributes.ServerAllocSize)
1306 FIXME("ServerAllocSize of %d ignored for parameter %d\n",
1307 pParam->param_attributes.ServerAllocSize * 8, i);
1309 if (pParam->param_attributes.IsBasetype)
1311 const unsigned char *pTypeFormat =
1312 &pParam->type_format_char;
1314 TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
1316 switch (phase)
1318 case STUBLESS_MARSHAL:
1319 if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1321 if (pParam->param_attributes.IsSimpleRef)
1322 call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
1323 else
1324 call_marshaller(&stubMsg, pArg, pTypeFormat);
1326 /* FIXME: call call_freer here */
1327 break;
1328 case STUBLESS_UNMARSHAL:
1329 if (pParam->param_attributes.IsIn)
1331 if (pParam->param_attributes.IsSimpleRef)
1332 call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1333 else
1334 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
1337 /* make a note of the address of the return value parameter for later */
1338 if (pParam->param_attributes.IsReturn)
1339 retval_ptr = (LONG_PTR *)pArg;
1341 break;
1342 case STUBLESS_CALCSIZE:
1343 if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1345 if (pParam->param_attributes.IsSimpleRef)
1346 call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
1347 else
1348 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
1350 break;
1351 default:
1352 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1355 current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
1357 else
1359 NDR_PARAM_OIF_OTHER * pParamOther =
1360 (NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
1362 const unsigned char * pTypeFormat =
1363 &(pStubDesc->pFormatTypes[pParamOther->type_offset]);
1365 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1367 switch (phase)
1369 case STUBLESS_MARSHAL:
1370 if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1372 if (pParam->param_attributes.IsByValue)
1373 call_marshaller(&stubMsg, pArg, pTypeFormat);
1374 else
1376 call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
1377 stubMsg.pfnFree(*(void **)pArg);
1380 /* FIXME: call call_freer here for IN types */
1381 break;
1382 case STUBLESS_UNMARSHAL:
1383 if (pParam->param_attributes.IsIn)
1385 if (pParam->param_attributes.IsByValue)
1386 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
1387 else
1388 call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1390 else if (pParam->param_attributes.IsOut &&
1391 !pParam->param_attributes.IsByValue)
1393 DWORD size = calc_arg_size(&stubMsg, pTypeFormat);
1395 if(size)
1397 *(void **)pArg = NdrAllocate(&stubMsg, size);
1398 memset(*(void **)pArg, 0, size);
1401 break;
1402 case STUBLESS_CALCSIZE:
1403 if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1405 if (pParam->param_attributes.IsByValue)
1406 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
1407 else
1408 call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
1410 break;
1411 default:
1412 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1415 current_offset += sizeof(NDR_PARAM_OIF_OTHER);
1417 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1419 else /* old parameter format */
1421 NDR_PARAM_OI_BASETYPE *pParam =
1422 (NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
1423 unsigned char *pArg = (unsigned char *)(args+current_stack_offset);
1425 /* no more parameters; exit loop */
1426 if (current_stack_offset > stack_size)
1427 break;
1429 TRACE("param[%d]: old format\n\tparam_direction: 0x%x\n", i, pParam->param_direction);
1431 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
1432 pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1434 const unsigned char *pTypeFormat =
1435 &pParam->type_format_char;
1437 TRACE("\tbase type 0x%02x\n", *pTypeFormat);
1439 switch (phase)
1441 case STUBLESS_MARSHAL:
1442 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1443 call_marshaller(&stubMsg, pArg, pTypeFormat);
1444 break;
1445 case STUBLESS_UNMARSHAL:
1446 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1447 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
1448 break;
1449 case STUBLESS_CALCSIZE:
1450 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1451 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
1452 break;
1453 default:
1454 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1457 current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat);
1458 current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
1460 else
1462 NDR_PARAM_OI_OTHER * pParamOther =
1463 (NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
1465 const unsigned char * pTypeFormat =
1466 &pStubDesc->pFormatTypes[pParamOther->type_offset];
1468 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1470 switch (phase)
1472 case STUBLESS_MARSHAL:
1473 if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1474 pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1475 pParam->param_direction == RPC_FC_RETURN_PARAM)
1476 call_marshaller(&stubMsg, pArg, pTypeFormat);
1477 break;
1478 case STUBLESS_UNMARSHAL:
1479 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1480 pParam->param_direction == RPC_FC_IN_PARAM)
1481 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
1482 break;
1483 case STUBLESS_CALCSIZE:
1484 if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1485 pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1486 pParam->param_direction == RPC_FC_RETURN_PARAM)
1487 call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
1488 break;
1489 default:
1490 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1493 current_stack_offset += pParamOther->stack_size * sizeof(INT);
1494 current_offset += sizeof(NDR_PARAM_OI_OTHER);
1499 break;
1500 default:
1501 ERR("shouldn't reach here. phase %d\n", phase);
1502 break;
1506 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1508 if (ext_flags.HasNewCorrDesc)
1510 /* free extra correlation package */
1511 /* NdrCorrelationFree(&stubMsg); */
1514 if (Oif_flags.HasPipes)
1516 /* NdrPipesDone(...) */
1519 /* free the full pointer translation tables */
1520 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1521 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1523 /* free server function stack */
1524 HeapFree(GetProcessHeap(), 0, args);
1526 return S_OK;
1529 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1531 DWORD dwPhase;
1532 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);