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 static void es_data_alloc(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
137 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
139 unsigned int tmpsize
= size
;
140 TRACE("%d with incremental handle\n", size
);
141 pEsMsg
->Alloc(pEsMsg
->UserState
, (char **)&pEsMsg
->StubMsg
.Buffer
, &tmpsize
);
144 ERR("not enough bytes allocated - requested %d, got %d\n", size
, tmpsize
);
145 RpcRaiseException(ERROR_OUTOFMEMORY
);
148 pEsMsg
->StubMsg
.RpcMsg
->Buffer
= pEsMsg
->StubMsg
.BufferStart
= pEsMsg
->StubMsg
.Buffer
;
151 static void es_data_read(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
153 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
155 unsigned int tmpsize
= size
;
156 TRACE("%d from incremental handle\n", size
);
157 pEsMsg
->Read(pEsMsg
->UserState
, (char **)&pEsMsg
->StubMsg
.Buffer
, &tmpsize
);
160 ERR("not enough bytes read - requested %d, got %d\n", size
, tmpsize
);
161 RpcRaiseException(ERROR_OUTOFMEMORY
);
164 pEsMsg
->StubMsg
.BufferLength
= size
;
165 pEsMsg
->StubMsg
.RpcMsg
->Buffer
= pEsMsg
->StubMsg
.BufferStart
= pEsMsg
->StubMsg
.Buffer
;
166 pEsMsg
->StubMsg
.BufferEnd
= pEsMsg
->StubMsg
.Buffer
+ size
;
169 static void es_data_write(MIDL_ES_MESSAGE
*pEsMsg
, ULONG size
)
171 if (pEsMsg
->HandleStyle
== MES_INCREMENTAL_HANDLE
)
173 TRACE("%d to incremental handle\n", size
);
174 pEsMsg
->Write(pEsMsg
->UserState
, (char *)pEsMsg
->StubMsg
.BufferStart
, size
);
178 static inline ULONG
mes_proc_header_buffer_size(void)
180 return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER
) + 12;
183 static void mes_proc_header_marshal(MIDL_ES_MESSAGE
*pEsMsg
)
185 const RPC_CLIENT_INTERFACE
*client_interface
= pEsMsg
->StubMsg
.StubDesc
->RpcInterfaceInformation
;
186 *(WORD
*)pEsMsg
->StubMsg
.Buffer
= 0x0101;
187 pEsMsg
->StubMsg
.Buffer
+= 2;
188 *(WORD
*)pEsMsg
->StubMsg
.Buffer
= 0xcccc;
189 pEsMsg
->StubMsg
.Buffer
+= 2;
190 memcpy(pEsMsg
->StubMsg
.Buffer
, &client_interface
->TransferSyntax
, sizeof(RPC_SYNTAX_IDENTIFIER
));
191 pEsMsg
->StubMsg
.Buffer
+= sizeof(RPC_SYNTAX_IDENTIFIER
);
192 memcpy(pEsMsg
->StubMsg
.Buffer
, &pEsMsg
->InterfaceId
, sizeof(RPC_SYNTAX_IDENTIFIER
));
193 pEsMsg
->StubMsg
.Buffer
+= sizeof(RPC_SYNTAX_IDENTIFIER
);
194 *(DWORD
*)pEsMsg
->StubMsg
.Buffer
= pEsMsg
->ProcNumber
;
195 pEsMsg
->StubMsg
.Buffer
+= 4;
196 *(DWORD
*)pEsMsg
->StubMsg
.Buffer
= 0x00000001;
197 pEsMsg
->StubMsg
.Buffer
+= 4;
198 *(DWORD
*)pEsMsg
->StubMsg
.Buffer
= pEsMsg
->ByteCount
;
199 pEsMsg
->StubMsg
.Buffer
+= 4;
202 static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE
*pEsMsg
)
204 const RPC_CLIENT_INTERFACE
*client_interface
= pEsMsg
->StubMsg
.StubDesc
->RpcInterfaceInformation
;
206 es_data_read(pEsMsg
, mes_proc_header_buffer_size());
208 if (*(WORD
*)pEsMsg
->StubMsg
.Buffer
!= 0x0101)
210 FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD
*)pEsMsg
->StubMsg
.Buffer
);
211 RpcRaiseException(RPC_X_WRONG_ES_VERSION
);
213 pEsMsg
->StubMsg
.Buffer
+= 2;
214 if (*(WORD
*)pEsMsg
->StubMsg
.Buffer
!= 0xcccc)
215 FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD
*)pEsMsg
->StubMsg
.Buffer
);
216 pEsMsg
->StubMsg
.Buffer
+= 2;
217 if (memcmp(pEsMsg
->StubMsg
.Buffer
, &client_interface
->TransferSyntax
, sizeof(RPC_SYNTAX_IDENTIFIER
)))
219 const RPC_SYNTAX_IDENTIFIER
*AlienTransferSyntax
= (const RPC_SYNTAX_IDENTIFIER
*)pEsMsg
->StubMsg
.Buffer
;
220 ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax
->SyntaxGUID
),
221 AlienTransferSyntax
->SyntaxVersion
.MajorVersion
,
222 AlienTransferSyntax
->SyntaxVersion
.MinorVersion
);
223 RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN
);
225 pEsMsg
->StubMsg
.Buffer
+= sizeof(RPC_SYNTAX_IDENTIFIER
);
226 memcpy(&pEsMsg
->InterfaceId
, pEsMsg
->StubMsg
.Buffer
, sizeof(RPC_SYNTAX_IDENTIFIER
));
227 pEsMsg
->StubMsg
.Buffer
+= sizeof(RPC_SYNTAX_IDENTIFIER
);
228 pEsMsg
->ProcNumber
= *(DWORD
*)pEsMsg
->StubMsg
.Buffer
;
229 pEsMsg
->StubMsg
.Buffer
+= 4;
230 if (*(DWORD
*)pEsMsg
->StubMsg
.Buffer
!= 0x00000001)
231 FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD
*)pEsMsg
->StubMsg
.Buffer
);
232 pEsMsg
->StubMsg
.Buffer
+= 4;
233 pEsMsg
->ByteCount
= *(DWORD
*)pEsMsg
->StubMsg
.Buffer
;
234 pEsMsg
->StubMsg
.Buffer
+= 4;
235 if (pEsMsg
->ByteCount
+ mes_proc_header_buffer_size() < pEsMsg
->ByteCount
)
236 RpcRaiseException(RPC_S_INVALID_BOUND
);
239 /***********************************************************************
240 * NdrMesProcEncodeDecode [RPCRT4.@]
242 void WINAPIV
NdrMesProcEncodeDecode(handle_t Handle
, const MIDL_STUB_DESC
* pStubDesc
, PFORMAT_STRING pFormat
, ...)
244 /* pointer to start of stack where arguments start */
246 MIDL_ES_MESSAGE
*pEsMsg
= (MIDL_ES_MESSAGE
*)Handle
;
248 unsigned short stack_size
;
249 /* header for procedure string */
250 const NDR_PROC_HEADER
*pProcHeader
= (const NDR_PROC_HEADER
*)&pFormat
[0];
251 /* the value to return to the client from the remote procedure */
253 const RPC_CLIENT_INTERFACE
*client_interface
;
255 TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle
, pStubDesc
, pFormat
);
257 /* Later NDR language versions probably won't be backwards compatible */
258 if (pStubDesc
->Version
> 0x50002)
260 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc
->Version
);
261 RpcRaiseException(RPC_X_WRONG_STUB_VERSION
);
264 client_interface
= pStubDesc
->RpcInterfaceInformation
;
265 pEsMsg
->InterfaceId
= client_interface
->InterfaceId
;
267 if (pProcHeader
->Oi_flags
& RPC_FC_PROC_OIF_RPCFLAGS
)
269 const NDR_PROC_HEADER_RPC
*pProcHeader
= (const NDR_PROC_HEADER_RPC
*)&pFormat
[0];
270 stack_size
= pProcHeader
->stack_size
;
271 pEsMsg
->ProcNumber
= pProcHeader
->proc_num
;
272 pFormat
+= sizeof(NDR_PROC_HEADER_RPC
);
276 stack_size
= pProcHeader
->stack_size
;
277 pEsMsg
->ProcNumber
= pProcHeader
->proc_num
;
278 pFormat
+= sizeof(NDR_PROC_HEADER
);
281 if (pProcHeader
->handle_type
== RPC_FC_BIND_EXPLICIT
)
283 switch (*pFormat
) /* handle_type */
285 case RPC_FC_BIND_PRIMITIVE
: /* explicit primitive */
286 pFormat
+= sizeof(NDR_EHD_PRIMITIVE
);
288 case RPC_FC_BIND_GENERIC
: /* explicit generic */
289 pFormat
+= sizeof(NDR_EHD_GENERIC
);
291 case RPC_FC_BIND_CONTEXT
: /* explicit context */
292 pFormat
+= sizeof(NDR_EHD_CONTEXT
);
295 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader
->handle_type
);
296 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
300 TRACE("stack size: 0x%x\n", stack_size
);
301 TRACE("proc num: %d\n", pEsMsg
->ProcNumber
);
303 memset(&rpcMsg
, 0, sizeof(rpcMsg
));
304 pEsMsg
->StubMsg
.RpcMsg
= &rpcMsg
;
305 pEsMsg
->StubMsg
.StubDesc
= pStubDesc
;
306 pEsMsg
->StubMsg
.pfnAllocate
= pStubDesc
->pfnAllocate
;
307 pEsMsg
->StubMsg
.pfnFree
= pStubDesc
->pfnFree
;
309 /* create the full pointer translation tables, if requested */
310 if (pProcHeader
->Oi_flags
& RPC_FC_PROC_OIF_FULLPTR
)
311 pEsMsg
->StubMsg
.FullPtrXlatTables
= NdrFullPointerXlatInit(0,XLAT_CLIENT
);
313 TRACE("Oi_flags = 0x%02x\n", pProcHeader
->Oi_flags
);
314 TRACE("stubdesc version = 0x%x\n", pStubDesc
->Version
);
315 TRACE("MIDL stub version = 0x%x\n", pStubDesc
->MIDLVersion
);
317 /* needed for conformance of top-level objects */
319 pEsMsg
->StubMsg
.StackTop
= *(unsigned char **)(&pFormat
+1);
321 # warning Stack not retrieved for your CPU architecture
324 switch (pEsMsg
->Operation
)
327 pEsMsg
->StubMsg
.BufferLength
= mes_proc_header_buffer_size();
329 client_do_args_old_format(&pEsMsg
->StubMsg
, pFormat
, PROXY_CALCSIZE
,
330 pEsMsg
->StubMsg
.StackTop
, stack_size
, (unsigned char *)&RetVal
,
331 FALSE
/* object_proc */);
333 pEsMsg
->ByteCount
= pEsMsg
->StubMsg
.BufferLength
- mes_proc_header_buffer_size();
334 es_data_alloc(pEsMsg
, pEsMsg
->StubMsg
.BufferLength
);
336 mes_proc_header_marshal(pEsMsg
);
338 client_do_args_old_format(&pEsMsg
->StubMsg
, pFormat
, PROXY_MARSHAL
,
339 pEsMsg
->StubMsg
.StackTop
, stack_size
, (unsigned char *)&RetVal
,
340 FALSE
/* object_proc */);
342 es_data_write(pEsMsg
, pEsMsg
->ByteCount
);
345 mes_proc_header_unmarshal(pEsMsg
);
347 es_data_read(pEsMsg
, pEsMsg
->ByteCount
);
349 client_do_args_old_format(&pEsMsg
->StubMsg
, pFormat
, PROXY_UNMARSHAL
,
350 pEsMsg
->StubMsg
.StackTop
, stack_size
, (unsigned char *)&RetVal
,
351 FALSE
/* object_proc */);
354 RpcRaiseException(RPC_S_INTERNAL_ERROR
);
357 /* free the full pointer translation tables */
358 if (pProcHeader
->Oi_flags
& RPC_FC_PROC_OIF_FULLPTR
)
359 NdrFullPointerXlatFree(pEsMsg
->StubMsg
.FullPtrXlatTables
);