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
32 #include "ndr_stubless.h"
34 #include "wine/debug.h"
35 #include "wine/rpcfc.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 static inline void init_MIDL_ES_MESSAGE(MIDL_ES_MESSAGE *pEsMsg)
41 memset(pEsMsg, 0, sizeof(*pEsMsg));
42 /* even if we are unmarshalling, as we don't want pointers to be pointed
44 pEsMsg->StubMsg.IsClient = TRUE;
47 /***********************************************************************
48 * MesEncodeIncrementalHandleCreate [RPCRT4.@]
50 RPC_STATUS WINAPI MesEncodeIncrementalHandleCreate(
51 void *UserState, MIDL_ES_ALLOC AllocFn, MIDL_ES_WRITE WriteFn,
54 MIDL_ES_MESSAGE *pEsMsg;
56 TRACE("(%p, %p, %p, %p)\n", UserState, AllocFn, WriteFn, pHandle);
58 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
60 return ERROR_OUTOFMEMORY;
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;
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));
87 return ERROR_OUTOFMEMORY;
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;
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 = (MIDL_ES_MESSAGE *)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;
125 /***********************************************************************
126 * MesHandleFree [RPCRT4.@]
128 RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
130 TRACE("(%p)\n", Handle);
131 HeapFree(GetProcessHeap(), 0, Handle);
135 /***********************************************************************
136 * MesEncodeFixedBufferHandleCreate [RPCRT4.@]
138 RPC_STATUS RPC_ENTRY MesEncodeFixedBufferHandleCreate(
139 char *Buffer, ULONG BufferSize, ULONG *pEncodedSize, handle_t *pHandle)
141 MIDL_ES_MESSAGE *pEsMsg;
143 TRACE("(%p, %d, %p, %p)\n", Buffer, BufferSize, pEncodedSize, pHandle);
145 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
147 return ERROR_OUTOFMEMORY;
149 init_MIDL_ES_MESSAGE(pEsMsg);
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;
157 *pHandle = (handle_t)pEsMsg;
161 /***********************************************************************
162 * MesDecodeBufferHandleCreate [RPCRT4.@]
164 RPC_STATUS RPC_ENTRY MesDecodeBufferHandleCreate(
165 char *Buffer, ULONG BufferSize, handle_t *pHandle)
167 MIDL_ES_MESSAGE *pEsMsg;
169 TRACE("(%p, %d, %p)\n", Buffer, BufferSize, pHandle);
171 pEsMsg = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg));
173 return ERROR_OUTOFMEMORY;
175 init_MIDL_ES_MESSAGE(pEsMsg);
177 pEsMsg->Operation = MES_DECODE;
178 pEsMsg->HandleStyle = MES_FIXED_BUFFER_HANDLE;
179 pEsMsg->Buffer = (unsigned char *)Buffer;
180 pEsMsg->BufferSize = BufferSize;
182 *pHandle = (handle_t)pEsMsg;
187 static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
189 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
191 unsigned int tmpsize = size;
192 TRACE("%d with incremental handle\n", size);
193 pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
196 ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
197 RpcRaiseException(ERROR_OUTOFMEMORY);
200 else if (pEsMsg->HandleStyle == MES_FIXED_BUFFER_HANDLE)
202 TRACE("%d with fixed buffer handle\n", size);
203 pEsMsg->StubMsg.Buffer = pEsMsg->Buffer;
205 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
208 static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
210 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
212 unsigned int tmpsize = size;
213 TRACE("%d from incremental handle\n", size);
214 pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
217 ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
218 RpcRaiseException(ERROR_OUTOFMEMORY);
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;
229 pEsMsg->StubMsg.BufferLength = size;
230 pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
231 pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
234 static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
236 if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
238 TRACE("%d to incremental handle\n", size);
239 pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
243 TRACE("%d to dynamic or fixed buffer handle\n", size);
244 *pEsMsg->pEncodedSize += size;
248 static inline ULONG mes_proc_header_buffer_size(void)
250 return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
253 static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
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;
272 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
274 const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
276 es_data_read(pEsMsg, mes_proc_header_buffer_size());
278 if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
280 FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
281 RpcRaiseException(RPC_X_WRONG_ES_VERSION);
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)))
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);
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);
309 /***********************************************************************
310 * NdrMesProcEncodeDecode [RPCRT4.@]
312 void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
314 /* pointer to start of stack where arguments start */
316 MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
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 */
323 const RPC_CLIENT_INTERFACE *client_interface;
325 TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, pStubDesc, pFormat);
327 /* Later NDR language versions probably won't be backwards compatible */
328 if (pStubDesc->Version > 0x50002)
330 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
331 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
334 client_interface = pStubDesc->RpcInterfaceInformation;
335 pEsMsg->InterfaceId = client_interface->InterfaceId;
337 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
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);
346 stack_size = pProcHeader->stack_size;
347 pEsMsg->ProcNumber = pProcHeader->proc_num;
348 pFormat += sizeof(NDR_PROC_HEADER);
351 if (pProcHeader->handle_type == RPC_FC_BIND_EXPLICIT)
353 switch (*pFormat) /* handle_type */
355 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
356 pFormat += sizeof(NDR_EHD_PRIMITIVE);
358 case RPC_FC_BIND_GENERIC: /* explicit generic */
359 pFormat += sizeof(NDR_EHD_GENERIC);
361 case RPC_FC_BIND_CONTEXT: /* explicit context */
362 pFormat += sizeof(NDR_EHD_CONTEXT);
365 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
366 RpcRaiseException(RPC_X_BAD_STUB_DATA);
370 TRACE("stack size: 0x%x\n", stack_size);
371 TRACE("proc num: %d\n", pEsMsg->ProcNumber);
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;
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);
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);
387 /* needed for conformance of top-level objects */
389 pEsMsg->StubMsg.StackTop = *(unsigned char **)(&pFormat+1);
391 # warning Stack not retrieved for your CPU architecture
394 switch (pEsMsg->Operation)
397 pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
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 */);
403 pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
404 es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
406 mes_proc_header_marshal(pEsMsg);
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 */);
412 es_data_write(pEsMsg, pEsMsg->ByteCount);
415 mes_proc_header_unmarshal(pEsMsg);
417 es_data_read(pEsMsg, pEsMsg->ByteCount);
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 */);
424 RpcRaiseException(RPC_S_INTERNAL_ERROR);
427 /* free the full pointer translation tables */
428 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
429 NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);