ntdll: Move retrieving the startup info to the Unix library.
[wine.git] / dlls / rpcrt4 / ndr_es.c
blob158bc7cda2ad9a5a27cd1bf94a596a90e4e183ae
1 /*
2 * NDR Serialization Services
4 * Copyright (c) 2007 Robert Shearman for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "rpc.h"
28 #include "midles.h"
29 #include "ndrtypes.h"
31 #include "ndr_misc.h"
32 #include "ndr_stubless.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 static inline void init_MIDL_ES_MESSAGE(MIDL_ES_MESSAGE *pEsMsg)
40 memset(pEsMsg, 0, sizeof(*pEsMsg));
41 /* even if we are unmarshalling, as we don't want pointers to be pointed
42 * to buffer memory */
43 pEsMsg->StubMsg.IsClient = TRUE;
44 pEsMsg->MesVersion = 1;
47 /***********************************************************************
48 * MesEncodeIncrementalHandleCreate [RPCRT4.@]
50 RPC_STATUS WINAPI MesEncodeIncrementalHandleCreate(
51 void *UserState, MIDL_ES_ALLOC AllocFn, MIDL_ES_WRITE WriteFn,
52 handle_t *pHandle)
54 MIDL_ES_MESSAGE *pEsMsg;
56 TRACE("(%p, %p, %p, %p)\n", UserState, AllocFn, WriteFn, pHandle);
58 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
59 if (!pEsMsg)
60 return RPC_S_OUT_OF_MEMORY;
62 init_MIDL_ES_MESSAGE(pEsMsg);
64 pEsMsg->Operation = MES_ENCODE;
65 pEsMsg->UserState = UserState;
66 pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
67 pEsMsg->Alloc = AllocFn;
68 pEsMsg->Write = WriteFn;
70 *pHandle = (handle_t)pEsMsg;
72 return RPC_S_OK;
75 /***********************************************************************
76 * MesDecodeIncrementalHandleCreate [RPCRT4.@]
78 RPC_STATUS WINAPI MesDecodeIncrementalHandleCreate(
79 void *UserState, MIDL_ES_READ ReadFn, handle_t *pHandle)
81 MIDL_ES_MESSAGE *pEsMsg;
83 TRACE("(%p, %p, %p)\n", UserState, ReadFn, pHandle);
85 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
86 if (!pEsMsg)
87 return RPC_S_OUT_OF_MEMORY;
89 init_MIDL_ES_MESSAGE(pEsMsg);
91 pEsMsg->Operation = MES_DECODE;
92 pEsMsg->UserState = UserState;
93 pEsMsg->HandleStyle = MES_INCREMENTAL_HANDLE;
94 pEsMsg->Read = ReadFn;
96 *pHandle = (handle_t)pEsMsg;
98 return RPC_S_OK;
101 /***********************************************************************
102 * MesIncrementalHandleReset [RPCRT4.@]
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)
108 MIDL_ES_MESSAGE *pEsMsg = Handle;
110 TRACE("(%p, %p, %p, %p, %p, %d)\n", Handle, UserState, AllocFn,
111 WriteFn, ReadFn, Operation);
113 init_MIDL_ES_MESSAGE(pEsMsg);
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;
122 return RPC_S_OK;
125 /***********************************************************************
126 * MesBufferHandleReset [RPCRT4.@]
128 RPC_STATUS WINAPI MesBufferHandleReset(handle_t Handle, ULONG HandleStyle,
129 MIDL_ES_CODE Operation, char **Buffer, ULONG BufferSize, ULONG *EncodedSize)
131 MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
133 TRACE("(%p, %u, %d, %p, %u, %p)\n", Handle, HandleStyle, Operation, Buffer,
134 BufferSize, EncodedSize);
136 if (!Handle || !Buffer || !EncodedSize)
137 return RPC_S_INVALID_ARG;
139 if (Operation != MES_ENCODE && Operation != MES_DECODE && Operation != MES_ENCODE_NDR64)
140 return RPC_S_INVALID_ARG;
142 if (HandleStyle != MES_FIXED_BUFFER_HANDLE && HandleStyle != MES_DYNAMIC_BUFFER_HANDLE)
143 return RPC_S_INVALID_ARG;
145 init_MIDL_ES_MESSAGE(pEsMsg);
147 pEsMsg->Operation = Operation;
148 pEsMsg->HandleStyle = HandleStyle;
149 if (HandleStyle == MES_FIXED_BUFFER_HANDLE)
150 pEsMsg->Buffer = (unsigned char*)*Buffer;
151 else
152 pEsMsg->pDynBuffer = (unsigned char**)Buffer;
153 pEsMsg->BufferSize = BufferSize;
154 pEsMsg->pEncodedSize = EncodedSize;
156 return RPC_S_OK;
159 /***********************************************************************
160 * MesHandleFree [RPCRT4.@]
162 RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
164 TRACE("(%p)\n", Handle);
165 HeapFree(GetProcessHeap(), 0, Handle);
166 return RPC_S_OK;
169 static RPC_STATUS validate_mes_buffer_pointer(const char *Buffer)
171 if (!Buffer)
172 return RPC_S_INVALID_ARG;
174 if (((ULONG_PTR)Buffer & 7) != 0)
175 return RPC_X_INVALID_BUFFER;
177 return RPC_S_OK;
180 /***********************************************************************
181 * MesEncodeFixedBufferHandleCreate [RPCRT4.@]
183 RPC_STATUS RPC_ENTRY MesEncodeFixedBufferHandleCreate(
184 char *Buffer, ULONG BufferSize, ULONG *pEncodedSize, handle_t *pHandle)
186 MIDL_ES_MESSAGE *pEsMsg;
187 RPC_STATUS status;
189 TRACE("(%p, %d, %p, %p)\n", Buffer, BufferSize, pEncodedSize, pHandle);
191 if ((status = validate_mes_buffer_pointer(Buffer)))
192 return status;
194 if (!pEncodedSize)
195 return RPC_S_INVALID_ARG;
197 /* FIXME: check BufferSize too */
199 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
200 if (!pEsMsg)
201 return RPC_S_OUT_OF_MEMORY;
203 init_MIDL_ES_MESSAGE(pEsMsg);
205 pEsMsg->Operation = MES_ENCODE;
206 pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
207 pEsMsg->Buffer = (unsigned char *)Buffer;
208 pEsMsg->BufferSize = BufferSize;
209 pEsMsg->pEncodedSize = pEncodedSize;
211 *pHandle = (handle_t)pEsMsg;
213 return RPC_S_OK;
216 /***********************************************************************
217 * MesEncodeDynBufferHandleCreate [RPCRT4.@]
219 RPC_STATUS RPC_ENTRY MesEncodeDynBufferHandleCreate(char **Buffer,
220 ULONG *pEncodedSize, handle_t *pHandle)
222 MIDL_ES_MESSAGE *pEsMsg;
224 TRACE("(%p, %p, %p)\n", Buffer, pEncodedSize, pHandle);
226 if (!pEncodedSize)
227 return RPC_S_INVALID_ARG;
229 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
230 if (!pEsMsg)
231 return RPC_S_OUT_OF_MEMORY;
233 init_MIDL_ES_MESSAGE(pEsMsg);
235 pEsMsg->Operation = MES_ENCODE;
236 pEsMsg->HandleStyle = MES_DYNAMIC_BUFFER_HANDLE;
237 pEsMsg->pDynBuffer = (unsigned char **)Buffer;
238 pEsMsg->pEncodedSize = pEncodedSize;
240 *pHandle = (handle_t)pEsMsg;
242 return RPC_S_OK;
245 /***********************************************************************
246 * MesDecodeBufferHandleCreate [RPCRT4.@]
248 RPC_STATUS RPC_ENTRY MesDecodeBufferHandleCreate(
249 char *Buffer, ULONG BufferSize, handle_t *pHandle)
251 MIDL_ES_MESSAGE *pEsMsg;
252 RPC_STATUS status;
254 TRACE("(%p, %d, %p)\n", Buffer, BufferSize, pHandle);
256 if ((status = validate_mes_buffer_pointer(Buffer)))
257 return status;
259 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
260 if (!pEsMsg)
261 return RPC_S_OUT_OF_MEMORY;
263 init_MIDL_ES_MESSAGE(pEsMsg);
265 pEsMsg->Operation = MES_DECODE;
266 pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
267 pEsMsg->Buffer = (unsigned char *)Buffer;
268 pEsMsg->BufferSize = BufferSize;
270 *pHandle = (handle_t)pEsMsg;
272 return RPC_S_OK;
275 static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
277 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
279 unsigned int tmpsize = size;
280 TRACE("%d with incremental handle\n", size);
281 pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
282 if (tmpsize < size)
284 ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
285 RpcRaiseException(RPC_S_OUT_OF_MEMORY);
288 else if (pEsMsg->HandleStyle == MES_FIXED_BUFFER_HANDLE)
290 TRACE("%d with fixed buffer handle\n", size);
291 pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
293 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
296 static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
298 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
300 unsigned int tmpsize = size;
301 TRACE("%d from incremental handle\n", size);
302 pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
303 if (tmpsize < size)
305 ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
306 RpcRaiseException(RPC_S_OUT_OF_MEMORY);
309 else
311 TRACE("%d from fixed or dynamic buffer handle\n", size);
312 /* FIXME: validate BufferSize? */
313 pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
314 pEsMsg->Buffer += size;
315 pEsMsg->BufferSize -= size;
317 pEsMsg->StubMsg.BufferLength = size;
318 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
319 pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
322 static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
324 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
326 TRACE("%d to incremental handle\n", size);
327 pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
329 else
331 TRACE("%d to dynamic or fixed buffer handle\n", size);
332 *pEsMsg->pEncodedSize += size;
336 static inline ULONG mes_proc_header_buffer_size(void)
338 return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
341 static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
343 const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
344 *(WORD *)pEsMsg->StubMsg.Buffer = 0x0101;
345 pEsMsg->StubMsg.Buffer += 2;
346 *(WORD *)pEsMsg->StubMsg.Buffer = 0xcccc;
347 pEsMsg->StubMsg.Buffer += 2;
348 memcpy(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER));
349 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
350 memcpy(pEsMsg->StubMsg.Buffer, &pEsMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER));
351 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
352 *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ProcNumber;
353 pEsMsg->StubMsg.Buffer += 4;
354 *(DWORD *)pEsMsg->StubMsg.Buffer = 0x00000001;
355 pEsMsg->StubMsg.Buffer += 4;
356 *(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ByteCount;
357 pEsMsg->StubMsg.Buffer += 4;
360 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
362 const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
364 es_data_read(pEsMsg, mes_proc_header_buffer_size());
366 if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
368 FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
369 RpcRaiseException(RPC_X_WRONG_ES_VERSION);
371 pEsMsg->StubMsg.Buffer += 2;
372 if (*(WORD *)pEsMsg->StubMsg.Buffer != 0xcccc)
373 FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
374 pEsMsg->StubMsg.Buffer += 2;
375 if (memcmp(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER)))
377 const RPC_SYNTAX_IDENTIFIER *AlienTransferSyntax = (const RPC_SYNTAX_IDENTIFIER *)pEsMsg->StubMsg.Buffer;
378 ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax->SyntaxGUID),
379 AlienTransferSyntax->SyntaxVersion.MajorVersion,
380 AlienTransferSyntax->SyntaxVersion.MinorVersion);
381 RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN);
383 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
384 memcpy(&pEsMsg->InterfaceId, pEsMsg->StubMsg.Buffer, sizeof(RPC_SYNTAX_IDENTIFIER));
385 pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
386 pEsMsg->ProcNumber = *(DWORD *)pEsMsg->StubMsg.Buffer;
387 pEsMsg->StubMsg.Buffer += 4;
388 if (*(DWORD *)pEsMsg->StubMsg.Buffer != 0x00000001)
389 FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD *)pEsMsg->StubMsg.Buffer);
390 pEsMsg->StubMsg.Buffer += 4;
391 pEsMsg->ByteCount = *(DWORD *)pEsMsg->StubMsg.Buffer;
392 pEsMsg->StubMsg.Buffer += 4;
393 if (pEsMsg->ByteCount + mes_proc_header_buffer_size() < pEsMsg->ByteCount)
394 RpcRaiseException(RPC_S_INVALID_BOUND);
397 /***********************************************************************
398 * NdrMesProcEncodeDecode [RPCRT4.@]
400 void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
402 /* pointer to start of stack where arguments start */
403 RPC_MESSAGE rpcMsg;
404 MIDL_ES_MESSAGE *pEsMsg = Handle;
405 /* size of stack */
406 unsigned short stack_size;
407 /* header for procedure string */
408 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
409 const RPC_CLIENT_INTERFACE *client_interface;
410 __ms_va_list args;
411 unsigned int number_of_params;
412 ULONG_PTR arg_buffer[256];
414 TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, pStubDesc, pFormat);
416 /* Later NDR language versions probably won't be backwards compatible */
417 if (pStubDesc->Version > 0x50002)
419 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
420 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
423 client_interface = pStubDesc->RpcInterfaceInformation;
424 pEsMsg->InterfaceId = client_interface->InterfaceId;
426 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
428 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
429 stack_size = header_rpc->stack_size;
430 pEsMsg->ProcNumber = header_rpc->proc_num;
431 pFormat += sizeof(NDR_PROC_HEADER_RPC);
433 else
435 stack_size = pProcHeader->stack_size;
436 pEsMsg->ProcNumber = pProcHeader->proc_num;
437 pFormat += sizeof(NDR_PROC_HEADER);
440 if (pProcHeader->handle_type == 0)
442 switch (*pFormat) /* handle_type */
444 case FC_BIND_PRIMITIVE: /* explicit primitive */
445 pFormat += sizeof(NDR_EHD_PRIMITIVE);
446 break;
447 case FC_BIND_GENERIC: /* explicit generic */
448 pFormat += sizeof(NDR_EHD_GENERIC);
449 break;
450 case FC_BIND_CONTEXT: /* explicit context */
451 pFormat += sizeof(NDR_EHD_CONTEXT);
452 break;
453 default:
454 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
455 RpcRaiseException(RPC_X_BAD_STUB_DATA);
459 TRACE("stack size: 0x%x\n", stack_size);
460 TRACE("proc num: %d\n", pEsMsg->ProcNumber);
462 memset(&rpcMsg, 0, sizeof(rpcMsg));
463 pEsMsg->StubMsg.RpcMsg = &rpcMsg;
464 pEsMsg->StubMsg.StubDesc = pStubDesc;
465 pEsMsg->StubMsg.pfnAllocate = pStubDesc->pfnAllocate;
466 pEsMsg->StubMsg.pfnFree = pStubDesc->pfnFree;
468 /* create the full pointer translation tables, if requested */
469 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
470 pEsMsg->StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
472 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
473 TRACE("stubdesc version = 0x%x\n", pStubDesc->Version);
474 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
476 /* needed for conformance of top-level objects */
477 __ms_va_start( args, pFormat );
478 pEsMsg->StubMsg.StackTop = va_arg( args, unsigned char * );
479 __ms_va_end( args );
481 pFormat = convert_old_args( &pEsMsg->StubMsg, pFormat, stack_size, FALSE,
482 arg_buffer, sizeof(arg_buffer), &number_of_params );
484 switch (pEsMsg->Operation)
486 case MES_ENCODE:
487 pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
489 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_CALCSIZE, NULL, number_of_params, NULL );
491 pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
492 es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
494 mes_proc_header_marshal(pEsMsg);
496 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_MARSHAL, NULL, number_of_params, NULL );
498 es_data_write(pEsMsg, pEsMsg->ByteCount);
499 break;
500 case MES_DECODE:
501 mes_proc_header_unmarshal(pEsMsg);
503 es_data_read(pEsMsg, pEsMsg->ByteCount);
505 client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_UNMARSHAL, NULL, number_of_params, NULL );
506 break;
507 default:
508 RpcRaiseException(RPC_S_INTERNAL_ERROR);
509 return;
511 /* free the full pointer translation tables */
512 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
513 NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);
516 void RPC_ENTRY NdrMesTypeDecode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
517 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
519 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
522 void RPC_ENTRY NdrMesTypeEncode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
523 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, const void *pObject)
525 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);
528 void RPC_ENTRY NdrMesTypeFree2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo,
529 const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject)
531 FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject);