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 #define WIN32_NO_STATUS
29 //#include "winerror.h"
32 //#include "ndrtypes.h"
34 //#include "ndr_misc.h"
35 #include "ndr_stubless.h"
37 #include <wine/debug.h>
38 #include <wine/rpcfc.h>
40 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
42 static inline void init_MIDL_ES_MESSAGE(MIDL_ES_MESSAGE
*pEsMsg
)
44 memset(pEsMsg
, 0, sizeof(*pEsMsg
));
45 /* even if we are unmarshalling, as we don't want pointers to be pointed
47 pEsMsg
->StubMsg
.IsClient
= TRUE
;
50 /***********************************************************************
51 * MesEncodeIncrementalHandleCreate [RPCRT4.@]
53 RPC_STATUS WINAPI
MesEncodeIncrementalHandleCreate(
54 void *UserState
, MIDL_ES_ALLOC AllocFn
, MIDL_ES_WRITE WriteFn
,
57 MIDL_ES_MESSAGE
*pEsMsg
;
59 TRACE("(%p, %p, %p, %p)\n", UserState
, AllocFn
, WriteFn
, pHandle
);
61 pEsMsg
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg
));
63 return ERROR_OUTOFMEMORY
;
65 init_MIDL_ES_MESSAGE(pEsMsg
);
67 pEsMsg
->Operation
= MES_ENCODE
;
68 pEsMsg
->UserState
= UserState
;
69 pEsMsg
->HandleStyle
= MES_INCREMENTAL_HANDLE
;
70 pEsMsg
->Alloc
= AllocFn
;
71 pEsMsg
->Write
= WriteFn
;
73 *pHandle
= (handle_t
)pEsMsg
;
78 /***********************************************************************
79 * MesDecodeIncrementalHandleCreate [RPCRT4.@]
81 RPC_STATUS WINAPI
MesDecodeIncrementalHandleCreate(
82 void *UserState
, MIDL_ES_READ ReadFn
, handle_t
*pHandle
)
84 MIDL_ES_MESSAGE
*pEsMsg
;
86 TRACE("(%p, %p, %p)\n", UserState
, ReadFn
, pHandle
);
88 pEsMsg
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg
));
90 return ERROR_OUTOFMEMORY
;
92 init_MIDL_ES_MESSAGE(pEsMsg
);
94 pEsMsg
->Operation
= MES_DECODE
;
95 pEsMsg
->UserState
= UserState
;
96 pEsMsg
->HandleStyle
= MES_INCREMENTAL_HANDLE
;
97 pEsMsg
->Read
= ReadFn
;
99 *pHandle
= (handle_t
)pEsMsg
;
104 /***********************************************************************
105 * MesIncrementalHandleReset [RPCRT4.@]
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
)
111 MIDL_ES_MESSAGE
*pEsMsg
= Handle
;
113 TRACE("(%p, %p, %p, %p, %p, %d)\n", Handle
, UserState
, AllocFn
,
114 WriteFn
, ReadFn
, Operation
);
116 init_MIDL_ES_MESSAGE(pEsMsg
);
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
;
128 /***********************************************************************
129 * MesHandleFree [RPCRT4.@]
131 RPC_STATUS WINAPI
MesHandleFree(handle_t Handle
)
133 TRACE("(%p)\n", Handle
);
134 HeapFree(GetProcessHeap(), 0, Handle
);
138 /***********************************************************************
139 * MesEncodeFixedBufferHandleCreate [RPCRT4.@]
141 RPC_STATUS RPC_ENTRY
MesEncodeFixedBufferHandleCreate(
142 char *Buffer
, ULONG BufferSize
, ULONG
*pEncodedSize
, handle_t
*pHandle
)
144 MIDL_ES_MESSAGE
*pEsMsg
;
146 TRACE("(%p, %d, %p, %p)\n", Buffer
, BufferSize
, pEncodedSize
, pHandle
);
148 pEsMsg
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg
));
150 return ERROR_OUTOFMEMORY
;
152 init_MIDL_ES_MESSAGE(pEsMsg
);
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
;
160 *pHandle
= (handle_t
)pEsMsg
;
165 /***********************************************************************
166 * MesEncodeDynBufferHandleCreate [RPCRT4.@]
168 RPC_STATUS RPC_ENTRY
MesEncodeDynBufferHandleCreate(char **ppBuffer
,
169 ULONG
*pEncodedSize
, handle_t
*pHandle
)
171 FIXME("%p %p %p stub\n", ppBuffer
, pEncodedSize
, pHandle
);
175 /***********************************************************************
176 * MesDecodeBufferHandleCreate [RPCRT4.@]
178 RPC_STATUS RPC_ENTRY
MesDecodeBufferHandleCreate(
179 char *Buffer
, ULONG BufferSize
, handle_t
*pHandle
)
181 MIDL_ES_MESSAGE
*pEsMsg
;
183 TRACE("(%p, %d, %p)\n", Buffer
, BufferSize
, pHandle
);
185 pEsMsg
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pEsMsg
));
187 return ERROR_OUTOFMEMORY
;
189 init_MIDL_ES_MESSAGE(pEsMsg
);
191 pEsMsg
->Operation
= MES_DECODE
;
192 pEsMsg
->HandleStyle
= MES_FIXED_BUFFER_HANDLE
;
193 pEsMsg
->Buffer
= (unsigned char *)Buffer
;
194 pEsMsg
->BufferSize
= BufferSize
;
196 *pHandle
= (handle_t
)pEsMsg
;
201 static void es_data_alloc(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
203 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
205 unsigned int tmpsize
= size
;
206 TRACE("%d with incremental handle\n", size
);
207 pEsMsg
->Alloc(pEsMsg
->UserState
, (char **)&pEsMsg
->StubMsg
.Buffer
, &tmpsize
);
210 ERR("not enough bytes allocated - requested %d, got %d\n", size
, tmpsize
);
211 RpcRaiseException(ERROR_OUTOFMEMORY
);
214 else if (pEsMsg
->HandleStyle
== MES_FIXED_BUFFER_HANDLE
)
216 TRACE("%d with fixed buffer handle\n", size
);
217 pEsMsg
->StubMsg
.Buffer
= pEsMsg
->Buffer
;
219 pEsMsg
->StubMsg
.RpcMsg
->Buffer
= pEsMsg
->StubMsg
.BufferStart
= pEsMsg
->StubMsg
.Buffer
;
222 static void es_data_read(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
224 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
226 unsigned int tmpsize
= size
;
227 TRACE("%d from incremental handle\n", size
);
228 pEsMsg
->Read(pEsMsg
->UserState
, (char **)&pEsMsg
->StubMsg
.Buffer
, &tmpsize
);
231 ERR("not enough bytes read - requested %d, got %d\n", size
, tmpsize
);
232 RpcRaiseException(ERROR_OUTOFMEMORY
);
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
;
243 pEsMsg
->StubMsg
.BufferLength
= size
;
244 pEsMsg
->StubMsg
.RpcMsg
->Buffer
= pEsMsg
->StubMsg
.BufferStart
= pEsMsg
->StubMsg
.Buffer
;
245 pEsMsg
->StubMsg
.BufferEnd
= pEsMsg
->StubMsg
.Buffer
+ size
;
248 static void es_data_write(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
250 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
252 TRACE("%d to incremental handle\n", size
);
253 pEsMsg
->Write(pEsMsg
->UserState
, (char *)pEsMsg
->StubMsg
.BufferStart
, size
);
257 TRACE("%d to dynamic or fixed buffer handle\n", size
);
258 *pEsMsg
->pEncodedSize
+= size
;
262 static inline ULONG
mes_proc_header_buffer_size(void)
264 return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER
) + 12;
267 static void mes_proc_header_marshal(MIDL_ES_MESSAGE
*pEsMsg
)
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;
286 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE
*pEsMsg
)
288 const RPC_CLIENT_INTERFACE
*client_interface
= pEsMsg
->StubMsg
.StubDesc
->RpcInterfaceInformation
;
290 es_data_read(pEsMsg
, mes_proc_header_buffer_size());
292 if (*(WORD
*)pEsMsg
->StubMsg
.Buffer
!= 0x0101)
294 FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD
*)pEsMsg
->StubMsg
.Buffer
);
295 RpcRaiseException(RPC_X_WRONG_ES_VERSION
);
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
)))
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
);
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
);
323 /***********************************************************************
324 * NdrMesProcEncodeDecode [RPCRT4.@]
326 void WINAPIV
NdrMesProcEncodeDecode(handle_t Handle
, const MIDL_STUB_DESC
* pStubDesc
, PFORMAT_STRING pFormat
, ...)
328 /* pointer to start of stack where arguments start */
330 MIDL_ES_MESSAGE
*pEsMsg
= Handle
;
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
;
337 unsigned int number_of_params
;
338 ULONG_PTR arg_buffer
[256];
340 TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle
, pStubDesc
, pFormat
);
342 /* Later NDR language versions probably won't be backwards compatible */
343 if (pStubDesc
->Version
> 0x50002)
345 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc
->Version
);
346 RpcRaiseException(RPC_X_WRONG_STUB_VERSION
);
349 client_interface
= pStubDesc
->RpcInterfaceInformation
;
350 pEsMsg
->InterfaceId
= client_interface
->InterfaceId
;
352 if (pProcHeader
->Oi_flags
& RPC_FC_PROC_OIF_RPCFLAGS
)
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
);
361 stack_size
= pProcHeader
->stack_size
;
362 pEsMsg
->ProcNumber
= pProcHeader
->proc_num
;
363 pFormat
+= sizeof(NDR_PROC_HEADER
);
366 if (pProcHeader
->handle_type
== RPC_FC_BIND_EXPLICIT
)
368 switch (*pFormat
) /* handle_type */
370 case RPC_FC_BIND_PRIMITIVE
: /* explicit primitive */
371 pFormat
+= sizeof(NDR_EHD_PRIMITIVE
);
373 case RPC_FC_BIND_GENERIC
: /* explicit generic */
374 pFormat
+= sizeof(NDR_EHD_GENERIC
);
376 case RPC_FC_BIND_CONTEXT
: /* explicit context */
377 pFormat
+= sizeof(NDR_EHD_CONTEXT
);
380 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader
->handle_type
);
381 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
385 TRACE("stack size: 0x%x\n", stack_size
);
386 TRACE("proc num: %d\n", pEsMsg
->ProcNumber
);
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
;
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
);
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
);
402 /* needed for conformance of top-level objects */
403 __ms_va_start( args
, pFormat
);
404 pEsMsg
->StubMsg
.StackTop
= va_arg( args
, unsigned char * );
407 pFormat
= convert_old_args( &pEsMsg
->StubMsg
, pFormat
, stack_size
, FALSE
,
408 arg_buffer
, sizeof(arg_buffer
), &number_of_params
);
410 switch (pEsMsg
->Operation
)
413 pEsMsg
->StubMsg
.BufferLength
= mes_proc_header_buffer_size();
415 client_do_args( &pEsMsg
->StubMsg
, pFormat
, STUBLESS_CALCSIZE
, NULL
, number_of_params
, NULL
);
417 pEsMsg
->ByteCount
= pEsMsg
->StubMsg
.BufferLength
- mes_proc_header_buffer_size();
418 es_data_alloc(pEsMsg
, pEsMsg
->StubMsg
.BufferLength
);
420 mes_proc_header_marshal(pEsMsg
);
422 client_do_args( &pEsMsg
->StubMsg
, pFormat
, STUBLESS_MARSHAL
, NULL
, number_of_params
, NULL
);
424 es_data_write(pEsMsg
, pEsMsg
->ByteCount
);
427 mes_proc_header_unmarshal(pEsMsg
);
429 es_data_read(pEsMsg
, pEsMsg
->ByteCount
);
431 client_do_args( &pEsMsg
->StubMsg
, pFormat
, STUBLESS_UNMARSHAL
, NULL
, number_of_params
, NULL
);
434 RpcRaiseException(RPC_S_INTERNAL_ERROR
);
437 /* free the full pointer translation tables */
438 if (pProcHeader
->Oi_flags
& RPC_FC_PROC_OIF_FULLPTR
)
439 NdrFullPointerXlatFree(pEsMsg
->StubMsg
.FullPtrXlatTables
);
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
)
445 FIXME("(%p, %p, %p, %p, %p)\n", Handle
, pPicklingInfo
, pStubDesc
, pFormatString
, pObject
);
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
)
451 FIXME("(%p, %p, %p, %p, %p)\n", Handle
, pPicklingInfo
, pStubDesc
, pFormatString
, pObject
);
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
)
457 FIXME("(%p, %p, %p, %p, %p)\n", Handle
, pPicklingInfo
, pStubDesc
, pFormatString
, pObject
);