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