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