Sync with trunk r62754.
[reactos.git] / dll / win32 / 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 "precomp.h"
22
23 #include <midles.h>
24
25 WINE_DEFAULT_DEBUG_CHANNEL(ole);
26
27 static inline void init_MIDL_ES_MESSAGE(MIDL_ES_MESSAGE *pEsMsg)
28 {
29 memset(pEsMsg, 0, sizeof(*pEsMsg));
30 /* even if we are unmarshalling, as we don't want pointers to be pointed
31 * to buffer memory */
32 pEsMsg->StubMsg.IsClient = TRUE;
33 }
34
35 /***********************************************************************
36 * MesEncodeIncrementalHandleCreate [RPCRT4.@]
37 */
38 RPC_STATUS WINAPI MesEncodeIncrementalHandleCreate(
39 void *UserState, MIDL_ES_ALLOC AllocFn, MIDL_ES_WRITE WriteFn,
40 handle_t *pHandle)
41 {
42 MIDL_ES_MESSAGE *pEsMsg;
43
44 TRACE("(%p, %p, %p, %p)\n", UserState, AllocFn, WriteFn, pHandle);
45
46 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
47 if (!pEsMsg)
48 return ERROR_OUTOFMEMORY;
49
50 init_MIDL_ES_MESSAGE(pEsMsg);
51
52 pEsMsg->Operation = MES_ENCODE;
53 pEsMsg->UserState = UserState;
54 pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
55 pEsMsg->Alloc = AllocFn;
56 pEsMsg->Write = WriteFn;
57
58 *pHandle = (handle_t)pEsMsg;
59
60 return RPC_S_OK;
61 }
62
63 /***********************************************************************
64 * MesDecodeIncrementalHandleCreate [RPCRT4.@]
65 */
66 RPC_STATUS WINAPI MesDecodeIncrementalHandleCreate(
67 void *UserState, MIDL_ES_READ ReadFn, handle_t *pHandle)
68 {
69 MIDL_ES_MESSAGE *pEsMsg;
70
71 TRACE("(%p, %p, %p)\n", UserState, ReadFn, pHandle);
72
73 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
74 if (!pEsMsg)
75 return ERROR_OUTOFMEMORY;
76
77 init_MIDL_ES_MESSAGE(pEsMsg);
78
79 pEsMsg->Operation = MES_DECODE;
80 pEsMsg->UserState = UserState;
81 pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
82 pEsMsg->Read = ReadFn;
83
84 *pHandle = (handle_t)pEsMsg;
85
86 return RPC_S_OK;
87 }
88
89 /***********************************************************************
90 * MesIncrementalHandleReset [RPCRT4.@]
91 */
92 RPC_STATUS WINAPI MesIncrementalHandleReset(
93 handle_t Handle, void *UserState, MIDL_ES_ALLOC AllocFn,
94 MIDL_ES_WRITE WriteFn, MIDL_ES_READ ReadFn, MIDL_ES_CODE Operation)
95 {
96 MIDL_ES_MESSAGE *pEsMsg = Handle;
97
98 TRACE("(%p, %p, %p, %p, %p, %d)\n", Handle, UserState, AllocFn,
99 WriteFn, ReadFn, Operation);
100
101 init_MIDL_ES_MESSAGE(pEsMsg);
102
103 pEsMsg->Operation = Operation;
104 pEsMsg->UserState = UserState;
105 pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
106 pEsMsg->Alloc = AllocFn;
107 pEsMsg->Write = WriteFn;
108 pEsMsg->Read = ReadFn;
109
110 return RPC_S_OK;
111 }
112
113 /***********************************************************************
114 * MesHandleFree [RPCRT4.@]
115 */
116 RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
117 {
118 TRACE("(%p)\n", Handle);
119 HeapFree(GetProcessHeap(), 0, Handle);
120 return RPC_S_OK;
121 }
122
123 /***********************************************************************
124 * MesEncodeFixedBufferHandleCreate [RPCRT4.@]
125 */
126 RPC_STATUS RPC_ENTRY MesEncodeFixedBufferHandleCreate(
127 char *Buffer, ULONG BufferSize, ULONG *pEncodedSize, handle_t *pHandle)
128 {
129 MIDL_ES_MESSAGE *pEsMsg;
130
131 TRACE("(%p, %d, %p, %p)\n", Buffer, BufferSize, pEncodedSize, pHandle);
132
133 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
134 if (!pEsMsg)
135 return ERROR_OUTOFMEMORY;
136
137 init_MIDL_ES_MESSAGE(pEsMsg);
138
139 pEsMsg->Operation = MES_ENCODE;
140 pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
141 pEsMsg->Buffer = (unsigned char *)Buffer;
142 pEsMsg->BufferSize = BufferSize;
143 pEsMsg->pEncodedSize = pEncodedSize;
144
145 *pHandle = (handle_t)pEsMsg;
146
147 return RPC_S_OK;
148 }
149
150 /***********************************************************************
151 * MesEncodeDynBufferHandleCreate [RPCRT4.@]
152 */
153 RPC_STATUS RPC_ENTRY MesEncodeDynBufferHandleCreate(char **ppBuffer,
154 ULONG *pEncodedSize, handle_t *pHandle)
155 {
156 FIXME("%p %p %p stub\n", ppBuffer, pEncodedSize, pHandle);
157 return RPC_S_OK;
158 }
159
160 /***********************************************************************
161 * MesDecodeBufferHandleCreate [RPCRT4.@]
162 */
163 RPC_STATUS RPC_ENTRY MesDecodeBufferHandleCreate(
164 char *Buffer, ULONG BufferSize, handle_t *pHandle)
165 {
166 MIDL_ES_MESSAGE *pEsMsg;
167
168 TRACE("(%p, %d, %p)\n", Buffer, BufferSize, pHandle);
169
170 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
171 if (!pEsMsg)
172 return ERROR_OUTOFMEMORY;
173
174 init_MIDL_ES_MESSAGE(pEsMsg);
175
176 pEsMsg->Operation = MES_DECODE;
177 pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
178 pEsMsg->Buffer = (unsigned char *)Buffer;
179 pEsMsg->BufferSize = BufferSize;
180
181 *pHandle = (handle_t)pEsMsg;
182
183 return RPC_S_OK;
184 }
185
186 static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
187 {
188 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
189 {
190 unsigned int tmpsize = size;
191 TRACE("%d with incremental handle\n", size);
192 pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
193 if (tmpsize < size)
194 {
195 ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
196 RpcRaiseException(ERROR_OUTOFMEMORY);
197 }
198 }
199 else if (pEsMsg->HandleStyle == MES_FIXED_BUFFER_HANDLE)
200 {
201 TRACE("%d with fixed buffer handle\n", size);
202 pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
203 }
204 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
205 }
206
207 static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
208 {
209 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
210 {
211 unsigned int tmpsize = size;
212 TRACE("%d from incremental handle\n", size);
213 pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
214 if (tmpsize < size)
215 {
216 ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
217 RpcRaiseException(ERROR_OUTOFMEMORY);
218 }
219 }
220 else
221 {
222 TRACE("%d from fixed or dynamic buffer handle\n", size);
223 /* FIXME: validate BufferSize? */
224 pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
225 pEsMsg->Buffer += size;
226 pEsMsg->BufferSize -= size;
227 }
228 pEsMsg->StubMsg.BufferLength = size;
229 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
230 pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
231 }
232
233 static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
234 {
235 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
236 {
237 TRACE("%d to incremental handle\n", size);
238 pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
239 }
240 else
241 {
242 TRACE("%d to dynamic or fixed buffer handle\n", size);
243 *pEsMsg->pEncodedSize += size;
244 }
245 }
246
247 static inline ULONG mes_proc_header_buffer_size(void)
248 {
249 return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
250 }
251
252 static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
253 {
254 const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
255 *(WORD *)pEsMsg->StubMsg.Buffer = 0x0101;
256 pEsMsg->StubMsg.Buffer += 2;
257 *(WORD *)pEsMsg->StubMsg.Buffer = 0xcccc;
258 pEsMsg->StubMsg.Buffer += 2;
259 memcpy(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER));
260 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
261 memcpy(pEsMsg->StubMsg.Buffer, &pEsMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER));
262 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
263 *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ProcNumber;
264 pEsMsg->StubMsg.Buffer += 4;
265 *(DWORD *)pEsMsg->StubMsg.Buffer = 0x00000001;
266 pEsMsg->StubMsg.Buffer += 4;
267 *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ByteCount;
268 pEsMsg->StubMsg.Buffer += 4;
269 }
270
271 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
272 {
273 const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
274
275 es_data_read(pEsMsg, mes_proc_header_buffer_size());
276
277 if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
278 {
279 FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
280 RpcRaiseException(RPC_X_WRONG_ES_VERSION);
281 }
282 pEsMsg->StubMsg.Buffer += 2;
283 if (*(WORD *)pEsMsg->StubMsg.Buffer != 0xcccc)
284 FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
285 pEsMsg->StubMsg.Buffer += 2;
286 if (memcmp(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER)))
287 {
288 const RPC_SYNTAX_IDENTIFIER *AlienTransferSyntax = (const RPC_SYNTAX_IDENTIFIER *)pEsMsg->StubMsg.Buffer;
289 ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax->SyntaxGUID),
290 AlienTransferSyntax->SyntaxVersion.MajorVersion,
291 AlienTransferSyntax->SyntaxVersion.MinorVersion);
292 RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN);
293 }
294 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
295 memcpy(&pEsMsg->InterfaceId, pEsMsg->StubMsg.Buffer, sizeof(RPC_SYNTAX_IDENTIFIER));
296 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
297 pEsMsg->ProcNumber = *(DWORD *)pEsMsg->StubMsg.Buffer;
298 pEsMsg->StubMsg.Buffer += 4;
299 if (*(DWORD *)pEsMsg->StubMsg.Buffer != 0x00000001)
300 FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD *)pEsMsg->StubMsg.Buffer);
301 pEsMsg->StubMsg.Buffer += 4;
302 pEsMsg->ByteCount = *(DWORD *)pEsMsg->StubMsg.Buffer;
303 pEsMsg->StubMsg.Buffer += 4;
304 if (pEsMsg->ByteCount + mes_proc_header_buffer_size() < pEsMsg->ByteCount)
305 RpcRaiseException(RPC_S_INVALID_BOUND);
306 }
307
308 /***********************************************************************
309 * NdrMesProcEncodeDecode [RPCRT4.@]
310 */
311 void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
312 {
313 /* pointer to start of stack where arguments start */
314 RPC_MESSAGE rpcMsg;
315 MIDL_ES_MESSAGE *pEsMsg = Handle;
316 /* size of stack */
317 unsigned short stack_size;
318 /* header for procedure string */
319 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
320 const RPC_CLIENT_INTERFACE *client_interface;
321 __ms_va_list args;
322 unsigned int number_of_params;
323 ULONG_PTR arg_buffer[256];
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 *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
340 stack_size = header_rpc->stack_size;
341 pEsMsg->ProcNumber = header_rpc->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 __ms_va_start( args, pFormat );
389 pEsMsg->StubMsg.StackTop = va_arg( args, unsigned char * );
390 __ms_va_end( args );
391
392 pFormat = convert_old_args( &pEsMsg->StubMsg, pFormat, stack_size, FALSE,
393 arg_buffer, sizeof(arg_buffer), &number_of_params );
394
395 switch (pEsMsg->Operation)
396 {
397 case MES_ENCODE:
398 pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
399
400 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_CALCSIZE, NULL, number_of_params, NULL );
401
402 pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
403 es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
404
405 mes_proc_header_marshal(pEsMsg);
406
407 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_MARSHAL, NULL, number_of_params, NULL );
408
409 es_data_write(pEsMsg, pEsMsg->ByteCount);
410 break;
411 case MES_DECODE:
412 mes_proc_header_unmarshal(pEsMsg);
413
414 es_data_read(pEsMsg, pEsMsg->ByteCount);
415
416 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_UNMARSHAL, NULL, number_of_params, NULL );
417 break;
418 default:
419 RpcRaiseException(RPC_S_INTERNAL_ERROR);
420 return;
421 }
422 /* free the full pointer translation tables */
423 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
424 NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);
425 }
426
427 void RPC_ENTRY NdrMesTypeDecode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
428 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
429 {
430 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
431 }
432
433 void RPC_ENTRY NdrMesTypeEncode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
434 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, const void *pObject)
435 {
436 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
437 }
438
439 void RPC_ENTRY NdrMesTypeFree2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
440 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
441 {
442 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
443 }