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