📄 ndr_marshall.c
字号:
/*
* NDR data marshalling
*
* Copyright 2002 Greg Turner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* TODO:
* - figure out whether we *really* got this right
* - check for errors and throw exceptions
*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
#include "ndr_misc.h"
#include "rpcndr.h"
#include "wine/unicode.h"
#include "wine/rpcfc.h"
#include "wine/debug.h"
#include "rpc_binding.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define BUFFER_PARANOIA 20
#if defined(__i386__)
# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
(*((UINT32 *)(pchar)) = (uint32))
# define LITTLE_ENDIAN_UINT32_READ(pchar) \
(*((UINT32 *)(pchar)))
#else
/* these would work for i386 too, but less efficient */
# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
(*(pchar) = LOBYTE(LOWORD(uint32)), \
*((pchar)+1) = HIBYTE(LOWORD(uint32)), \
*((pchar)+2) = LOBYTE(HIWORD(uint32)), \
*((pchar)+3) = HIBYTE(HIWORD(uint32)), \
(uint32)) /* allow as r-value */
# define LITTLE_ENDIAN_UINT32_READ(pchar) \
(MAKELONG( \
MAKEWORD(*(pchar), *((pchar)+1)), \
MAKEWORD(*((pchar)+2), *((pchar)+3))))
#endif
#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
(*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
*((pchar)+2) = HIBYTE(LOWORD(uint32)), \
*((pchar)+1) = LOBYTE(HIWORD(uint32)), \
*(pchar) = HIBYTE(HIWORD(uint32)), \
(uint32)) /* allow as r-value */
#define BIG_ENDIAN_UINT32_READ(pchar) \
(MAKELONG( \
MAKEWORD(*((pchar)+3), *((pchar)+2)), \
MAKEWORD(*((pchar)+1), *(pchar))))
#ifdef NDR_LOCAL_IS_BIG_ENDIAN
# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
# define NDR_LOCAL_UINT32_READ(pchar) \
BIG_ENDIAN_UINT32_READ(pchar)
#else
# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
# define NDR_LOCAL_UINT32_READ(pchar) \
LITTLE_ENDIAN_UINT32_READ(pchar)
#endif
/* _Align must be the desired alignment minus 1,
* e.g. ALIGN_LENGTH(len, 3) to align on a dword boundary. */
#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
#define STD_OVERFLOW_CHECK(_Msg) do { \
TRACE("buffer=%d/%ld\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
} while (0)
#define NDR_TABLE_SIZE 128
#define NDR_TABLE_MASK 127
static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
static unsigned long WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
0,
NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
/* 0x10 */
NdrBaseTypeMarshall,
/* 0x11 */
NdrPointerMarshall, NdrPointerMarshall,
NdrPointerMarshall, NdrPointerMarshall,
/* 0x15 */
NdrSimpleStructMarshall, NdrSimpleStructMarshall,
NdrConformantStructMarshall, NdrConformantStructMarshall,
NdrConformantVaryingStructMarshall,
NdrComplexStructMarshall,
/* 0x1b */
NdrConformantArrayMarshall,
NdrConformantVaryingArrayMarshall,
NdrFixedArrayMarshall, NdrFixedArrayMarshall,
NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
NdrComplexArrayMarshall,
/* 0x22 */
NdrConformantStringMarshall, 0, 0,
NdrConformantStringMarshall,
NdrNonConformantStringMarshall, 0, 0, 0,
/* 0x2a */
NdrEncapsulatedUnionMarshall,
NdrNonEncapsulatedUnionMarshall,
0,
NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
/* 0x2f */
NdrInterfacePointerMarshall,
/* 0xb0 */
0, 0, 0, 0,
NdrUserMarshalMarshall
};
NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
0,
NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
/* 0x10 */
NdrBaseTypeUnmarshall,
/* 0x11 */
NdrPointerUnmarshall, NdrPointerUnmarshall,
NdrPointerUnmarshall, NdrPointerUnmarshall,
/* 0x15 */
NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
NdrConformantVaryingStructUnmarshall,
NdrComplexStructUnmarshall,
/* 0x1b */
NdrConformantArrayUnmarshall,
NdrConformantVaryingArrayUnmarshall,
NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
NdrComplexArrayUnmarshall,
/* 0x22 */
NdrConformantStringUnmarshall, 0, 0,
NdrConformantStringUnmarshall,
NdrNonConformantStringUnmarshall, 0, 0, 0,
/* 0x2a */
NdrEncapsulatedUnionUnmarshall,
NdrNonEncapsulatedUnionUnmarshall,
0,
NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
/* 0x2f */
NdrInterfacePointerUnmarshall,
/* 0xb0 */
0, 0, 0, 0,
NdrUserMarshalUnmarshall
};
NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
0,
NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
/* 0x10 */
NdrBaseTypeBufferSize,
/* 0x11 */
NdrPointerBufferSize, NdrPointerBufferSize,
NdrPointerBufferSize, NdrPointerBufferSize,
/* 0x15 */
NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
NdrConformantStructBufferSize, NdrConformantStructBufferSize,
NdrConformantVaryingStructBufferSize,
NdrComplexStructBufferSize,
/* 0x1b */
NdrConformantArrayBufferSize,
NdrConformantVaryingArrayBufferSize,
NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
NdrComplexArrayBufferSize,
/* 0x22 */
NdrConformantStringBufferSize, 0, 0,
NdrConformantStringBufferSize,
NdrNonConformantStringBufferSize, 0, 0, 0,
/* 0x2a */
NdrEncapsulatedUnionBufferSize,
NdrNonEncapsulatedUnionBufferSize,
0,
NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
/* 0x2f */
NdrInterfacePointerBufferSize,
/* 0xb0 */
0, 0, 0, 0,
NdrUserMarshalBufferSize
};
NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
0,
NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
/* 0x10 */
NdrBaseTypeMemorySize,
/* 0x11 */
NdrPointerMemorySize, NdrPointerMemorySize,
NdrPointerMemorySize, NdrPointerMemorySize,
/* 0x15 */
NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
0, 0, 0,
NdrComplexStructMemorySize,
/* 0x1b */
NdrConformantArrayMemorySize, 0, 0, 0, 0, 0,
NdrComplexArrayMemorySize,
/* 0x22 */
NdrConformantStringMemorySize, 0, 0,
NdrConformantStringMemorySize,
NdrNonConformantStringMemorySize, 0, 0, 0,
/* 0x2a */
0, 0, 0, 0, 0,
/* 0x2f */
NdrInterfacePointerMemorySize,
/* 0xb0 */
0, 0, 0, 0,
NdrUserMarshalMemorySize
};
NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
0,
NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
/* 0x10 */
NdrBaseTypeFree,
/* 0x11 */
NdrPointerFree, NdrPointerFree,
NdrPointerFree, NdrPointerFree,
/* 0x15 */
NdrSimpleStructFree, NdrSimpleStructFree,
NdrConformantStructFree, NdrConformantStructFree,
NdrConformantVaryingStructFree,
NdrComplexStructFree,
/* 0x1b */
NdrConformantArrayFree,
NdrConformantVaryingArrayFree,
NdrFixedArrayFree, NdrFixedArrayFree,
NdrVaryingArrayFree, NdrVaryingArrayFree,
NdrComplexArrayFree,
/* 0x22 */
0, 0, 0,
0, 0, 0, 0, 0,
/* 0x2a */
NdrEncapsulatedUnionFree,
NdrNonEncapsulatedUnionFree,
0,
NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
/* 0x2f */
NdrInterfacePointerFree,
/* 0xb0 */
0, 0, 0, 0,
NdrUserMarshalFree
};
void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
{
/* hmm, this is probably supposed to do more? */
return pStubMsg->pfnAllocate(len);
}
static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
{
pStubMsg->pfnFree(Pointer);
}
static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
{
return (*(const ULONG *)pFormat != -1);
}
PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
{
pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
pStubMsg->Buffer += 4;
TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
if (pStubMsg->fHasNewCorrDesc)
return pFormat+6;
else
return pFormat+4;
}
static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
{
if (!IsConformanceOrVariancePresent(pFormat))
{
pStubMsg->Offset = 0;
pStubMsg->ActualCount = pStubMsg->MaxCount;
goto done;
}
pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
pStubMsg->Buffer += 4;
TRACE("offset is %ld\n", pStubMsg->Offset);
pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
pStubMsg->Buffer += 4;
TRACE("variance is %ld\n", pStubMsg->ActualCount);
done:
if (pStubMsg->fHasNewCorrDesc)
return pFormat+6;
else
return pFormat+4;
}
PFORMAT_STRING ComputeConformanceOrVariance(
MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
PFORMAT_STRING pFormat, ULONG_PTR def, ULONG *pCount)
{
BYTE dtype = pFormat[0] & 0xf;
short ofs = *(short *)&pFormat[2];
LPVOID ptr = NULL;
DWORD data = 0;
if (!IsConformanceOrVariancePresent(pFormat)) {
/* null descriptor */
*pCount = def;
goto finish_conf;
}
switch (pFormat[0] & 0xf0) {
case RPC_FC_NORMAL_CONFORMANCE:
TRACE("normal conformance, ofs=%d\n", ofs);
ptr = pMemory + ofs;
break;
case RPC_FC_POINTER_CONFORMANCE:
TRACE("pointer conformance, ofs=%d\n", ofs);
ptr = pStubMsg->Memory + ofs;
break;
case RPC_FC_TOP_LEVEL_CONFORMANCE:
TRACE("toplevel conformance, ofs=%d\n", ofs);
if (pStubMsg->StackTop) {
ptr = pStubMsg->StackTop + ofs;
}
else {
/* -Os mode, *pCount is already set */
goto finish_conf;
}
break;
case RPC_FC_CONSTANT_CONFORMANCE:
data = ofs | ((DWORD)pFormat[1] << 16);
TRACE("constant conformance, val=%ld\n", data);
*pCount = data;
goto finish_conf;
case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
if (pStubMsg->StackTop) {
ptr = pStubMsg->StackTop + ofs;
}
else {
/* ? */
goto done_conf_grab;
}
break;
default:
FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
}
switch (pFormat[1]) {
case RPC_FC_DEREFERENCE:
ptr = *(LPVOID*)ptr;
break;
case RPC_FC_CALLBACK:
{
unsigned char *old_stack_top = pStubMsg->StackTop;
pStubMsg->StackTop = ptr;
/* ofs is index into StubDesc->apfnExprEval */
TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
pStubMsg->StackTop = old_stack_top;
goto finish_conf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -