rpcrt4: Ignore the return value of functions when unmarshalling a pickled procedure.
[wine] / dlls / rpcrt4 / ndr_es.c
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 }
46
47 /***********************************************************************
48  *            MesEncodeIncrementalHandleCreate [RPCRT4.@]
49  */
50 RPC_STATUS WINAPI MesEncodeIncrementalHandleCreate(
51     void *UserState, MIDL_ES_ALLOC AllocFn, MIDL_ES_WRITE WriteFn,
52     handle_t *pHandle)
53 {
54     MIDL_ES_MESSAGE *pEsMsg;
55
56     TRACE("(%p, %p, %p, %p)\n", UserState, AllocFn, WriteFn, pHandle);
57
58     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
59     if (!pEsMsg)
60         return ERROR_OUTOFMEMORY;
61
62     init_MIDL_ES_MESSAGE(pEsMsg);
63
64     pEsMsg->Operation = MES_ENCODE;
65     pEsMsg->UserState = UserState;
66     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
67     pEsMsg->Alloc = AllocFn;
68     pEsMsg->Write = WriteFn;
69
70     *pHandle = (handle_t)pEsMsg;
71
72     return RPC_S_OK;
73 }
74
75 /***********************************************************************
76  *            MesDecodeIncrementalHandleCreate [RPCRT4.@]
77  */
78 RPC_STATUS WINAPI MesDecodeIncrementalHandleCreate(
79     void *UserState, MIDL_ES_READ ReadFn, handle_t *pHandle)
80 {
81     MIDL_ES_MESSAGE *pEsMsg;
82
83     TRACE("(%p, %p, %p)\n", UserState, ReadFn, pHandle);
84
85     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
86     if (!pEsMsg)
87         return ERROR_OUTOFMEMORY;
88
89     init_MIDL_ES_MESSAGE(pEsMsg);
90
91     pEsMsg->Operation = MES_DECODE;
92     pEsMsg->UserState = UserState;
93     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
94     pEsMsg->Read = ReadFn;
95
96     *pHandle = (handle_t)pEsMsg;
97
98     return RPC_S_OK;
99 }
100
101 /***********************************************************************
102  *            MesIncrementalHandleReset [RPCRT4.@]
103  */
104 RPC_STATUS WINAPI MesIncrementalHandleReset(
105     handle_t Handle, void *UserState, MIDL_ES_ALLOC AllocFn,
106     MIDL_ES_WRITE WriteFn, MIDL_ES_READ ReadFn, MIDL_ES_CODE Operation)
107 {
108     MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
109
110     TRACE("(%p, %p, %p, %p, %p, %d)\n", Handle, UserState, AllocFn,
111         WriteFn, ReadFn, Operation);
112
113     init_MIDL_ES_MESSAGE(pEsMsg);
114
115     pEsMsg->Operation = Operation;
116     pEsMsg->UserState = UserState;
117     pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
118     pEsMsg->Alloc = AllocFn;
119     pEsMsg->Write = WriteFn;
120     pEsMsg->Read = ReadFn;
121
122     return RPC_S_OK;
123 }
124
125 /***********************************************************************
126  *            MesHandleFree [RPCRT4.@]
127  */
128 RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
129 {
130     TRACE("(%p)\n", Handle);
131     HeapFree(GetProcessHeap(), 0, Handle);
132     return RPC_S_OK;
133 }
134
135 /***********************************************************************
136  *            MesEncodeFixedBufferHandleCreate [RPCRT4.@]
137  */
138 RPC_STATUS RPC_ENTRY MesEncodeFixedBufferHandleCreate(
139     char *Buffer, ULONG BufferSize, ULONG *pEncodedSize, handle_t *pHandle)
140 {
141     MIDL_ES_MESSAGE *pEsMsg;
142
143     TRACE("(%p, %d, %p, %p)\n", Buffer, BufferSize, pEncodedSize, pHandle);
144
145     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
146     if (!pEsMsg)
147         return ERROR_OUTOFMEMORY;
148
149     init_MIDL_ES_MESSAGE(pEsMsg);
150
151     pEsMsg->Operation = MES_ENCODE;
152     pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
153     pEsMsg->Buffer = (unsigned char *)Buffer;
154     pEsMsg->BufferSize = BufferSize;
155     pEsMsg->pEncodedSize = pEncodedSize;
156
157     *pHandle = (handle_t)pEsMsg;
158
159     return RPC_S_OK;}
160
161 /***********************************************************************
162  *            MesDecodeBufferHandleCreate [RPCRT4.@]
163  */
164 RPC_STATUS RPC_ENTRY MesDecodeBufferHandleCreate(
165     char *Buffer, ULONG BufferSize, handle_t *pHandle)
166 {
167     MIDL_ES_MESSAGE *pEsMsg;
168
169     TRACE("(%p, %d, %p)\n", Buffer, BufferSize, pHandle);
170
171     pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
172     if (!pEsMsg)
173         return ERROR_OUTOFMEMORY;
174
175     init_MIDL_ES_MESSAGE(pEsMsg);
176
177     pEsMsg->Operation = MES_DECODE;
178     pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
179     pEsMsg->Buffer = (unsigned char *)Buffer;
180     pEsMsg->BufferSize = BufferSize;
181
182     *pHandle = (handle_t)pEsMsg;
183
184     return RPC_S_OK;
185 }
186
187 static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
188 {
189     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
190     {
191         unsigned int tmpsize = size;
192         TRACE("%d with incremental handle\n", size);
193         pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
194         if (tmpsize < size)
195         {
196             ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
197             RpcRaiseException(ERROR_OUTOFMEMORY);
198         }
199     }
200     else if (pEsMsg->HandleStyle == MES_FIXED_BUFFER_HANDLE)
201     {
202         TRACE("%d with fixed buffer handle\n", size);
203         pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
204     }
205     pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
206 }
207
208 static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
209 {
210     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
211     {
212         unsigned int tmpsize = size;
213         TRACE("%d from incremental handle\n", size);
214         pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
215         if (tmpsize < size)
216         {
217             ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
218             RpcRaiseException(ERROR_OUTOFMEMORY);
219         }
220     }
221     else
222     {
223         TRACE("%d from fixed or dynamic buffer handle\n", size);
224         /* FIXME: validate BufferSize? */
225         pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
226         pEsMsg->Buffer += size;
227         pEsMsg->BufferSize -= size;
228     }
229     pEsMsg->StubMsg.BufferLength = size;
230     pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
231     pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
232 }
233
234 static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
235 {
236     if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
237     {
238         TRACE("%d to incremental handle\n", size);
239         pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
240     }
241     else
242     {
243         TRACE("%d to dynamic or fixed buffer handle\n", size);
244         *pEsMsg->pEncodedSize += size;
245     }
246 }
247
248 static inline ULONG mes_proc_header_buffer_size(void)
249 {
250     return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
251 }
252
253 static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
254 {
255     const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
256     *(WORD *)pEsMsg->StubMsg.Buffer = 0x0101;
257     pEsMsg->StubMsg.Buffer += 2;
258     *(WORD *)pEsMsg->StubMsg.Buffer = 0xcccc;
259     pEsMsg->StubMsg.Buffer += 2;
260     memcpy(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER));
261     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
262     memcpy(pEsMsg->StubMsg.Buffer, &pEsMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER));
263     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
264     *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ProcNumber;
265     pEsMsg->StubMsg.Buffer += 4;
266     *(DWORD *)pEsMsg->StubMsg.Buffer = 0x00000001;
267     pEsMsg->StubMsg.Buffer += 4;
268     *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ByteCount;
269     pEsMsg->StubMsg.Buffer += 4;
270 }
271
272 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
273 {
274     const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
275
276     es_data_read(pEsMsg, mes_proc_header_buffer_size());
277
278     if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
279     {
280         FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
281         RpcRaiseException(RPC_X_WRONG_ES_VERSION);
282     }
283     pEsMsg->StubMsg.Buffer += 2;
284     if (*(WORD *)pEsMsg->StubMsg.Buffer != 0xcccc)
285         FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
286     pEsMsg->StubMsg.Buffer += 2;
287     if (memcmp(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER)))
288     {
289         const RPC_SYNTAX_IDENTIFIER *AlienTransferSyntax = (const RPC_SYNTAX_IDENTIFIER *)pEsMsg->StubMsg.Buffer;
290         ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax->SyntaxGUID),
291             AlienTransferSyntax->SyntaxVersion.MajorVersion,
292             AlienTransferSyntax->SyntaxVersion.MinorVersion);
293         RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN);
294     }
295     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
296     memcpy(&pEsMsg->InterfaceId, pEsMsg->StubMsg.Buffer, sizeof(RPC_SYNTAX_IDENTIFIER));
297     pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
298     pEsMsg->ProcNumber = *(DWORD *)pEsMsg->StubMsg.Buffer;
299     pEsMsg->StubMsg.Buffer += 4;
300     if (*(DWORD *)pEsMsg->StubMsg.Buffer != 0x00000001)
301         FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD *)pEsMsg->StubMsg.Buffer);
302     pEsMsg->StubMsg.Buffer += 4;
303     pEsMsg->ByteCount = *(DWORD *)pEsMsg->StubMsg.Buffer;
304     pEsMsg->StubMsg.Buffer += 4;
305     if (pEsMsg->ByteCount + mes_proc_header_buffer_size() < pEsMsg->ByteCount)
306         RpcRaiseException(RPC_S_INVALID_BOUND);
307 }
308
309 /***********************************************************************
310  *            NdrMesProcEncodeDecode [RPCRT4.@]
311  */
312 void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
313 {
314     /* pointer to start of stack where arguments start */
315     RPC_MESSAGE rpcMsg;
316     MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
317     /* size of stack */
318     unsigned short stack_size;
319     /* header for procedure string */
320     const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
321     /* the value to return to the client from the remote procedure */
322     LONG_PTR RetVal = 0;
323     const RPC_CLIENT_INTERFACE *client_interface;
324
325     TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, pStubDesc, pFormat);
326
327     /* Later NDR language versions probably won't be backwards compatible */
328     if (pStubDesc->Version > 0x50002)
329     {
330         FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
331         RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
332     }
333
334     client_interface = pStubDesc->RpcInterfaceInformation;
335     pEsMsg->InterfaceId = client_interface->InterfaceId;
336
337     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
338     {
339         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
340         stack_size = pProcHeader->stack_size;
341         pEsMsg->ProcNumber = pProcHeader->proc_num;
342         pFormat += sizeof(NDR_PROC_HEADER_RPC);
343     }
344     else
345     {
346         stack_size = pProcHeader->stack_size;
347         pEsMsg->ProcNumber = pProcHeader->proc_num;
348         pFormat += sizeof(NDR_PROC_HEADER);
349     }
350
351     if (pProcHeader->handle_type == RPC_FC_BIND_EXPLICIT)
352     {
353         switch (*pFormat) /* handle_type */
354         {
355         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
356             pFormat += sizeof(NDR_EHD_PRIMITIVE);
357             break;
358         case RPC_FC_BIND_GENERIC: /* explicit generic */
359             pFormat += sizeof(NDR_EHD_GENERIC);
360             break;
361         case RPC_FC_BIND_CONTEXT: /* explicit context */
362             pFormat += sizeof(NDR_EHD_CONTEXT);
363             break;
364         default:
365             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
366             RpcRaiseException(RPC_X_BAD_STUB_DATA);
367         }
368     }
369
370     TRACE("stack size: 0x%x\n", stack_size);
371     TRACE("proc num: %d\n", pEsMsg->ProcNumber);
372
373     memset(&rpcMsg, 0, sizeof(rpcMsg));
374     pEsMsg->StubMsg.RpcMsg = &rpcMsg;
375     pEsMsg->StubMsg.StubDesc = pStubDesc;
376     pEsMsg->StubMsg.pfnAllocate = pStubDesc->pfnAllocate;
377     pEsMsg->StubMsg.pfnFree = pStubDesc->pfnFree;
378
379     /* create the full pointer translation tables, if requested */
380     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
381         pEsMsg->StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
382
383     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
384     TRACE("stubdesc version = 0x%x\n", pStubDesc->Version);
385     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
386
387     /* needed for conformance of top-level objects */
388 #ifdef __i386__
389     pEsMsg->StubMsg.StackTop = *(unsigned char **)(&pFormat+1);
390 #else
391 # warning Stack not retrieved for your CPU architecture
392 #endif
393
394     switch (pEsMsg->Operation)
395     {
396     case MES_ENCODE:
397         pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
398
399         client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_CALCSIZE,
400             pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
401             FALSE /* object_proc */, TRUE /* ignore_retval */);
402
403         pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
404         es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
405
406         mes_proc_header_marshal(pEsMsg);
407
408         client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_MARSHAL,
409             pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
410             FALSE /* object_proc */, TRUE /* ignore_retval */);
411
412         es_data_write(pEsMsg, pEsMsg->ByteCount);
413         break;
414     case MES_DECODE:
415         mes_proc_header_unmarshal(pEsMsg);
416
417         es_data_read(pEsMsg, pEsMsg->ByteCount);
418
419         client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_UNMARSHAL,
420             pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
421             FALSE /* object_proc */, TRUE /* ignore_retval */);
422         break;
423     default:
424         RpcRaiseException(RPC_S_INTERNAL_ERROR);
425         return;
426     }
427     /* free the full pointer translation tables */
428     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
429         NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);
430 }