xref: /reactos/dll/win32/rpcrt4/ndr_es.c (revision 845faec4)
1 /*
2  * NDR Serialization Services
3  *
4  * Copyright (c) 2007 Robert Shearman for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 #include <stdio.h>
23 
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "rpc.h"
28 #include "midles.h"
29 #include "ndrtypes.h"
30 
31 #include "ndr_misc.h"
32 #include "ndr_stubless.h"
33 
34 #include "wine/debug.h"
35 #include "wine/rpcfc.h"
36 
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 
39 static inline void init_MIDL_ES_MESSAGE(MIDL_ES_MESSAGE *pEsMsg)
40 {
41     memset(pEsMsg, 0, sizeof(*pEsMsg));
42     /* even if we are unmarshalling, as we don't want pointers to be pointed
43      * to buffer memory */
44     pEsMsg->StubMsg.IsClient = TRUE;
45     pEsMsg->MesVersion = 1;
46 }
47 
48 /***********************************************************************
49  *            MesEncodeIncrementalHandleCreate [RPCRT4.@]
50  */
51 RPC_STATUS WINAPI MesEncodeIncrementalHandleCreate(
52     void *UserState, MIDL_ES_ALLOC AllocFn, MIDL_ES_WRITE WriteFn,
53     handle_t *pHandle)
54 {
55     MIDL_ES_MESSAGE *pEsMsg;
56 
57     TRACE("(%p, %p, %p, %p)\n", UserState, AllocFn, WriteFn, pHandle);
58 
59     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
60     if (!pEsMsg)
61         return RPC_S_OUT_OF_MEMORY;
62 
63     init_MIDL_ES_MESSAGE(pEsMsg);
64 
65     pEsMsg->Operation = MES_ENCODE;
66     pEsMsg->UserState = UserState;
67     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
68     pEsMsg->Alloc = AllocFn;
69     pEsMsg->Write = WriteFn;
70 
71     *pHandle = (handle_t)pEsMsg;
72 
73     return RPC_S_OK;
74 }
75 
76 /***********************************************************************
77  *            MesDecodeIncrementalHandleCreate [RPCRT4.@]
78  */
79 RPC_STATUS WINAPI MesDecodeIncrementalHandleCreate(
80     void *UserState, MIDL_ES_READ ReadFn, handle_t *pHandle)
81 {
82     MIDL_ES_MESSAGE *pEsMsg;
83 
84     TRACE("(%p, %p, %p)\n", UserState, ReadFn, pHandle);
85 
86     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
87     if (!pEsMsg)
88         return RPC_S_OUT_OF_MEMORY;
89 
90     init_MIDL_ES_MESSAGE(pEsMsg);
91 
92     pEsMsg->Operation = MES_DECODE;
93     pEsMsg->UserState = UserState;
94     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
95     pEsMsg->Read = ReadFn;
96 
97     *pHandle = (handle_t)pEsMsg;
98 
99     return RPC_S_OK;
100 }
101 
102 /***********************************************************************
103  *            MesIncrementalHandleReset [RPCRT4.@]
104  */
105 RPC_STATUS WINAPI MesIncrementalHandleReset(
106     handle_t Handle, void *UserState, MIDL_ES_ALLOC AllocFn,
107     MIDL_ES_WRITE WriteFn, MIDL_ES_READ ReadFn, MIDL_ES_CODE Operation)
108 {
109     MIDL_ES_MESSAGE *pEsMsg = Handle;
110 
111     TRACE("(%p, %p, %p, %p, %p, %d)\n", Handle, UserState, AllocFn,
112         WriteFn, ReadFn, Operation);
113 
114     init_MIDL_ES_MESSAGE(pEsMsg);
115 
116     pEsMsg->Operation = Operation;
117     pEsMsg->UserState = UserState;
118     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
119     pEsMsg->Alloc = AllocFn;
120     pEsMsg->Write = WriteFn;
121     pEsMsg->Read = ReadFn;
122 
123     return RPC_S_OK;
124 }
125 
126 /***********************************************************************
127  *            MesBufferHandleReset [RPCRT4.@]
128  */
129 RPC_STATUS WINAPI MesBufferHandleReset(handle_t Handle, ULONG HandleStyle,
130     MIDL_ES_CODE Operation, char **Buffer, ULONG BufferSize, ULONG *EncodedSize)
131 {
132     MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
133 
134     TRACE("(%p, %u, %d, %p, %u, %p)\n", Handle, HandleStyle, Operation, Buffer,
135         BufferSize, EncodedSize);
136 
137     if (!Handle || !Buffer || !EncodedSize)
138         return RPC_S_INVALID_ARG;
139 
140     if (Operation != MES_ENCODE && Operation != MES_DECODE && Operation != MES_ENCODE_NDR64)
141         return RPC_S_INVALID_ARG;
142 
143     if (HandleStyle != MES_FIXED_BUFFER_HANDLE && HandleStyle != MES_DYNAMIC_BUFFER_HANDLE)
144         return RPC_S_INVALID_ARG;
145 
146     init_MIDL_ES_MESSAGE(pEsMsg);
147 
148     pEsMsg->Operation = Operation;
149     pEsMsg->HandleStyle = HandleStyle;
150     if (HandleStyle == MES_FIXED_BUFFER_HANDLE)
151         pEsMsg->Buffer = (unsigned char*)*Buffer;
152     else
153         pEsMsg->pDynBuffer = (unsigned char**)Buffer;
154     pEsMsg->BufferSize = BufferSize;
155     pEsMsg->pEncodedSize = EncodedSize;
156 
157     return RPC_S_OK;
158 }
159 
160 /***********************************************************************
161  *            MesHandleFree [RPCRT4.@]
162  */
163 RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
164 {
165     TRACE("(%p)\n", Handle);
166     HeapFree(GetProcessHeap(), 0, Handle);
167     return RPC_S_OK;
168 }
169 
170 static RPC_STATUS validate_mes_buffer_pointer(const char *Buffer)
171 {
172     if (!Buffer)
173         return RPC_S_INVALID_ARG;
174 
175     if (((ULONG_PTR)Buffer & 7) != 0)
176         return RPC_X_INVALID_BUFFER;
177 
178     return RPC_S_OK;
179 }
180 
181 /***********************************************************************
182  *            MesEncodeFixedBufferHandleCreate [RPCRT4.@]
183  */
184 RPC_STATUS RPC_ENTRY MesEncodeFixedBufferHandleCreate(
185     char *Buffer, ULONG BufferSize, ULONG *pEncodedSize, handle_t *pHandle)
186 {
187     MIDL_ES_MESSAGE *pEsMsg;
188     RPC_STATUS status;
189 
190     TRACE("(%p, %d, %p, %p)\n", Buffer, BufferSize, pEncodedSize, pHandle);
191 
192     if ((status = validate_mes_buffer_pointer(Buffer)))
193         return status;
194 
195     if (!pEncodedSize)
196         return RPC_S_INVALID_ARG;
197 
198     /* FIXME: check BufferSize too */
199 
200     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
201     if (!pEsMsg)
202         return RPC_S_OUT_OF_MEMORY;
203 
204     init_MIDL_ES_MESSAGE(pEsMsg);
205 
206     pEsMsg->Operation = MES_ENCODE;
207     pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
208     pEsMsg->Buffer = (unsigned char *)Buffer;
209     pEsMsg->BufferSize = BufferSize;
210     pEsMsg->pEncodedSize = pEncodedSize;
211 
212     *pHandle = (handle_t)pEsMsg;
213 
214     return RPC_S_OK;
215 }
216 
217 /***********************************************************************
218  *            MesEncodeDynBufferHandleCreate [RPCRT4.@]
219  */
220 RPC_STATUS RPC_ENTRY MesEncodeDynBufferHandleCreate(char **Buffer,
221         ULONG *pEncodedSize, handle_t *pHandle)
222 {
223     MIDL_ES_MESSAGE *pEsMsg;
224 
225     TRACE("(%p, %p, %p)\n", Buffer, pEncodedSize, pHandle);
226 
227     if (!pEncodedSize)
228         return RPC_S_INVALID_ARG;
229 
230     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
231     if (!pEsMsg)
232         return RPC_S_OUT_OF_MEMORY;
233 
234     init_MIDL_ES_MESSAGE(pEsMsg);
235 
236     pEsMsg->Operation = MES_ENCODE;
237     pEsMsg->HandleStyle = MES_DYNAMIC_BUFFER_HANDLE;
238     pEsMsg->pDynBuffer = (unsigned char **)Buffer;
239     pEsMsg->pEncodedSize = pEncodedSize;
240 
241     *pHandle = (handle_t)pEsMsg;
242 
243     return RPC_S_OK;
244 }
245 
246 /***********************************************************************
247  *            MesDecodeBufferHandleCreate [RPCRT4.@]
248  */
249 RPC_STATUS RPC_ENTRY MesDecodeBufferHandleCreate(
250     char *Buffer, ULONG BufferSize, handle_t *pHandle)
251 {
252     MIDL_ES_MESSAGE *pEsMsg;
253     RPC_STATUS status;
254 
255     TRACE("(%p, %d, %p)\n", Buffer, BufferSize, pHandle);
256 
257     if ((status = validate_mes_buffer_pointer(Buffer)))
258         return status;
259 
260     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
261     if (!pEsMsg)
262         return RPC_S_OUT_OF_MEMORY;
263 
264     init_MIDL_ES_MESSAGE(pEsMsg);
265 
266     pEsMsg->Operation = MES_DECODE;
267     pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
268     pEsMsg->Buffer = (unsigned char *)Buffer;
269     pEsMsg->BufferSize = BufferSize;
270 
271     *pHandle = (handle_t)pEsMsg;
272 
273     return RPC_S_OK;
274 }
275 
276 static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
277 {
278     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
279     {
280         unsigned int tmpsize = size;
281         TRACE("%d with incremental handle\n", size);
282         pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
283         if (tmpsize < size)
284         {
285             ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
286             RpcRaiseException(RPC_S_OUT_OF_MEMORY);
287         }
288     }
289     else if (pEsMsg->HandleStyle == MES_FIXED_BUFFER_HANDLE)
290     {
291         TRACE("%d with fixed buffer handle\n", size);
292         pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
293     }
294     pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
295 }
296 
297 static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
298 {
299     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
300     {
301         unsigned int tmpsize = size;
302         TRACE("%d from incremental handle\n", size);
303         pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
304         if (tmpsize < size)
305         {
306             ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
307             RpcRaiseException(RPC_S_OUT_OF_MEMORY);
308         }
309     }
310     else
311     {
312         TRACE("%d from fixed or dynamic buffer handle\n", size);
313         /* FIXME: validate BufferSize? */
314         pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
315         pEsMsg->Buffer += size;
316         pEsMsg->BufferSize -= size;
317     }
318     pEsMsg->StubMsg.BufferLength = size;
319     pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
320     pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
321 }
322 
323 static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
324 {
325     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
326     {
327         TRACE("%d to incremental handle\n", size);
328         pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
329     }
330     else
331     {
332         TRACE("%d to dynamic or fixed buffer handle\n", size);
333         *pEsMsg->pEncodedSize += size;
334     }
335 }
336 
337 static inline ULONG mes_proc_header_buffer_size(void)
338 {
339     return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
340 }
341 
342 static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
343 {
344     const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
345     *(WORD *)pEsMsg->StubMsg.Buffer = 0x0101;
346     pEsMsg->StubMsg.Buffer += 2;
347     *(WORD *)pEsMsg->StubMsg.Buffer = 0xcccc;
348     pEsMsg->StubMsg.Buffer += 2;
349     memcpy(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER));
350     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
351     memcpy(pEsMsg->StubMsg.Buffer, &pEsMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER));
352     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
353     *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ProcNumber;
354     pEsMsg->StubMsg.Buffer += 4;
355     *(DWORD *)pEsMsg->StubMsg.Buffer = 0x00000001;
356     pEsMsg->StubMsg.Buffer += 4;
357     *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ByteCount;
358     pEsMsg->StubMsg.Buffer += 4;
359 }
360 
361 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
362 {
363     const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
364 
365     es_data_read(pEsMsg, mes_proc_header_buffer_size());
366 
367     if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
368     {
369         FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
370         RpcRaiseException(RPC_X_WRONG_ES_VERSION);
371     }
372     pEsMsg->StubMsg.Buffer += 2;
373     if (*(WORD *)pEsMsg->StubMsg.Buffer != 0xcccc)
374         FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
375     pEsMsg->StubMsg.Buffer += 2;
376     if (memcmp(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER)))
377     {
378         const RPC_SYNTAX_IDENTIFIER *AlienTransferSyntax = (const RPC_SYNTAX_IDENTIFIER *)pEsMsg->StubMsg.Buffer;
379         ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax->SyntaxGUID),
380             AlienTransferSyntax->SyntaxVersion.MajorVersion,
381             AlienTransferSyntax->SyntaxVersion.MinorVersion);
382         RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN);
383     }
384     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
385     memcpy(&pEsMsg->InterfaceId, pEsMsg->StubMsg.Buffer, sizeof(RPC_SYNTAX_IDENTIFIER));
386     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
387     pEsMsg->ProcNumber = *(DWORD *)pEsMsg->StubMsg.Buffer;
388     pEsMsg->StubMsg.Buffer += 4;
389     if (*(DWORD *)pEsMsg->StubMsg.Buffer != 0x00000001)
390         FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD *)pEsMsg->StubMsg.Buffer);
391     pEsMsg->StubMsg.Buffer += 4;
392     pEsMsg->ByteCount = *(DWORD *)pEsMsg->StubMsg.Buffer;
393     pEsMsg->StubMsg.Buffer += 4;
394     if (pEsMsg->ByteCount + mes_proc_header_buffer_size() < pEsMsg->ByteCount)
395         RpcRaiseException(RPC_S_INVALID_BOUND);
396 }
397 
398 /***********************************************************************
399  *            NdrMesProcEncodeDecode [RPCRT4.@]
400  */
401 void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
402 {
403     /* pointer to start of stack where arguments start */
404     RPC_MESSAGE rpcMsg;
405     MIDL_ES_MESSAGE *pEsMsg = Handle;
406     /* size of stack */
407     unsigned short stack_size;
408     /* header for procedure string */
409     const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
410     const RPC_CLIENT_INTERFACE *client_interface;
411     __ms_va_list args;
412     unsigned int number_of_params;
413     ULONG_PTR arg_buffer[256];
414 
415     TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, pStubDesc, pFormat);
416 
417     /* Later NDR language versions probably won't be backwards compatible */
418     if (pStubDesc->Version > 0x50002)
419     {
420         FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
421         RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
422     }
423 
424     client_interface = pStubDesc->RpcInterfaceInformation;
425     pEsMsg->InterfaceId = client_interface->InterfaceId;
426 
427     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
428     {
429         const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
430         stack_size = header_rpc->stack_size;
431         pEsMsg->ProcNumber = header_rpc->proc_num;
432         pFormat += sizeof(NDR_PROC_HEADER_RPC);
433     }
434     else
435     {
436         stack_size = pProcHeader->stack_size;
437         pEsMsg->ProcNumber = pProcHeader->proc_num;
438         pFormat += sizeof(NDR_PROC_HEADER);
439     }
440 
441     if (pProcHeader->handle_type == RPC_FC_BIND_EXPLICIT)
442     {
443         switch (*pFormat) /* handle_type */
444         {
445         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
446             pFormat += sizeof(NDR_EHD_PRIMITIVE);
447             break;
448         case RPC_FC_BIND_GENERIC: /* explicit generic */
449             pFormat += sizeof(NDR_EHD_GENERIC);
450             break;
451         case RPC_FC_BIND_CONTEXT: /* explicit context */
452             pFormat += sizeof(NDR_EHD_CONTEXT);
453             break;
454         default:
455             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
456             RpcRaiseException(RPC_X_BAD_STUB_DATA);
457         }
458     }
459 
460     TRACE("stack size: 0x%x\n", stack_size);
461     TRACE("proc num: %d\n", pEsMsg->ProcNumber);
462 
463     memset(&rpcMsg, 0, sizeof(rpcMsg));
464     pEsMsg->StubMsg.RpcMsg = &rpcMsg;
465     pEsMsg->StubMsg.StubDesc = pStubDesc;
466     pEsMsg->StubMsg.pfnAllocate = pStubDesc->pfnAllocate;
467     pEsMsg->StubMsg.pfnFree = pStubDesc->pfnFree;
468 
469     /* create the full pointer translation tables, if requested */
470     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
471         pEsMsg->StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
472 
473     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
474     TRACE("stubdesc version = 0x%x\n", pStubDesc->Version);
475     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
476 
477     /* needed for conformance of top-level objects */
478     __ms_va_start( args, pFormat );
479     pEsMsg->StubMsg.StackTop = va_arg( args, unsigned char * );
480     __ms_va_end( args );
481 
482     pFormat = convert_old_args( &pEsMsg->StubMsg, pFormat, stack_size, FALSE,
483                                 arg_buffer, sizeof(arg_buffer), &number_of_params );
484 
485     switch (pEsMsg->Operation)
486     {
487     case MES_ENCODE:
488         pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
489 
490         client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_CALCSIZE, NULL, number_of_params, NULL );
491 
492         pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
493         es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
494 
495         mes_proc_header_marshal(pEsMsg);
496 
497         client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_MARSHAL, NULL, number_of_params, NULL );
498 
499         es_data_write(pEsMsg, pEsMsg->ByteCount);
500         break;
501     case MES_DECODE:
502         mes_proc_header_unmarshal(pEsMsg);
503 
504         es_data_read(pEsMsg, pEsMsg->ByteCount);
505 
506         client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_UNMARSHAL, NULL, number_of_params, NULL );
507         break;
508     default:
509         RpcRaiseException(RPC_S_INTERNAL_ERROR);
510         return;
511     }
512     /* free the full pointer translation tables */
513     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
514         NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);
515 }
516 
517 void RPC_ENTRY NdrMesTypeDecode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
518     const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
519 {
520     FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
521 }
522 
523 void RPC_ENTRY NdrMesTypeEncode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
524     const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, const void *pObject)
525 {
526     FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
527 }
528 
529 void RPC_ENTRY NdrMesTypeFree2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
530     const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
531 {
532     FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
533 }
534