Huw Davies : rpcrt4: Support for non-encapsulated unions.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri May 5 12:10:19 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: b1d5158980a89dd92d23b2ee4f6fd5d6f705296d
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=b1d5158980a89dd92d23b2ee4f6fd5d6f705296d
Author: Huw Davies <huw at codeweavers.com>
Date: Fri Apr 28 14:28:24 2006 +0100
rpcrt4: Support for non-encapsulated unions.
---
dlls/rpcrt4/ndr_marshall.c | 264 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 259 insertions(+), 5 deletions(-)
diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c
index 6830530..66a4caa 100644
--- a/dlls/rpcrt4/ndr_marshall.c
+++ b/dlls/rpcrt4/ndr_marshall.c
@@ -1422,6 +1422,20 @@ void WINAPI NdrSimpleStructFree(PMIDL_ST
}
+static long NonEncapsulatedUnionSize(PMIDL_STUB_MESSAGE pStubMsg,
+ PFORMAT_STRING pFormat)
+{
+ pFormat += 2;
+ if (pStubMsg->fHasNewCorrDesc)
+ pFormat += 6;
+ else
+ pFormat += 4;
+
+ pFormat += *(const SHORT*)pFormat;
+ TRACE("size %d\n", *(const SHORT*)pFormat);
+ return *(const SHORT*)pFormat;
+}
+
unsigned long WINAPI EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat)
{
@@ -1433,6 +1447,8 @@ unsigned long WINAPI EmbeddedComplexSize
return *(const WORD*)&pFormat[2];
case RPC_FC_USER_MARSHAL:
return *(const WORD*)&pFormat[4];
+ case RPC_FC_NON_ENCAPSULATED_UNION:
+ return NonEncapsulatedUnionSize(pStubMsg, pFormat);
default:
FIXME("unhandled embedded type %02x\n", *pFormat);
}
@@ -2799,6 +2815,83 @@ void WINAPI NdrEncapsulatedUnionFree(PMI
FIXME("stub\n");
}
+static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
+ unsigned long discriminant,
+ PFORMAT_STRING pFormat)
+{
+ unsigned short num_arms, arm, type;
+
+ num_arms = *(const SHORT*)pFormat & 0x0fff;
+ pFormat += 2;
+ for(arm = 0; arm < num_arms; arm++)
+ {
+ if(discriminant == *(const ULONG*)pFormat)
+ {
+ pFormat += 4;
+ break;
+ }
+ pFormat += 6;
+ }
+
+ type = *(const unsigned short*)pFormat;
+ TRACE("type %04x\n", type);
+ if(arm == num_arms) /* default arm extras */
+ {
+ if(type == 0xffff)
+ {
+ FIXME("should raise an exception here\n");
+ return NULL;
+ }
+ if(type == 0)
+ {
+ /* Don't marshall any type. FIXME is this correct? */
+ return NULL;
+ }
+ }
+ return pFormat;
+}
+
+static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg,
+ unsigned char *pMemory,
+ PFORMAT_STRING pFormat)
+{
+ ULONG value;
+
+ pFormat = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat,
+ 0, &value);
+ TRACE("got switch value %lx\n", value);
+ pFormat += *(const SHORT*)pFormat;
+ pFormat += 2;
+
+ return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat);
+}
+
+static unsigned char *get_conformance_address(PMIDL_STUB_MESSAGE pStubMsg,
+ unsigned char *pMemory,
+ PFORMAT_STRING pFormat)
+{
+ short ofs = *(short *)&pFormat[2];
+ LPVOID ptr = NULL;
+
+ switch (pFormat[0] & 0xf0)
+ {
+ case RPC_FC_NORMAL_CONFORMANCE:
+ ptr = pMemory;
+ break;
+ default:
+ FIXME("Conformance type %x\n", pFormat[0]);
+ return NULL;
+ }
+
+ if(pFormat[1])
+ {
+ FIXME("Conformance op %x\n", pFormat[1]);
+ return NULL;
+ }
+
+ return (unsigned char *)ptr + ofs;
+}
+
/***********************************************************************
* NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
*/
@@ -2806,19 +2899,143 @@ unsigned char * WINAPI NdrNonEncapsulat
unsigned char *pMemory,
PFORMAT_STRING pFormat)
{
- FIXME("stub\n");
+ unsigned char *discriminant;
+ unsigned short type;
+
+ TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
+ pFormat++;
+
+ /* Marshall discriminant */
+ discriminant = get_conformance_address(pStubMsg, pMemory, pFormat + 1);
+ NdrBaseTypeMarshall(pStubMsg, discriminant, pFormat);
+ pFormat++;
+
+ pFormat = get_non_encapsulated_union_arm(pStubMsg, pMemory, pFormat);
+ if(!pFormat)
+ return NULL;
+
+ type = *(const unsigned short*)pFormat;
+ if(type & 0x8000)
+ {
+ pFormat++;
+ return NdrBaseTypeMarshall(pStubMsg, pMemory, pFormat);
+ }
+ else
+ {
+ PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
+ NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
+ if (m)
+ {
+ switch(*desc)
+ {
+ case RPC_FC_RP:
+ case RPC_FC_UP:
+ case RPC_FC_OP:
+ case RPC_FC_FP:
+ pMemory = *(void**)pMemory;
+ break;
+ }
+ m(pStubMsg, pMemory, desc);
+ }
+ else FIXME("no marshaller for embedded type %02x\n", *desc);
+ }
return NULL;
}
-/***********************************************************************
- * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
+static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
+ PFORMAT_STRING *ppFormat)
+{
+ long discriminant = 0;
+
+ switch(**ppFormat)
+ {
+ case RPC_FC_BYTE:
+ case RPC_FC_CHAR:
+ case RPC_FC_SMALL:
+ case RPC_FC_USMALL:
+ discriminant = *(UCHAR *)pStubMsg->Buffer;
+ pStubMsg->Buffer += sizeof(UCHAR);
+ break;
+ case RPC_FC_WCHAR:
+ case RPC_FC_SHORT:
+ case RPC_FC_USHORT:
+ ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT) - 1);
+ discriminant = *(USHORT *)pStubMsg->Buffer;
+ pStubMsg->Buffer += sizeof(USHORT);
+ break;
+ case RPC_FC_LONG:
+ case RPC_FC_ULONG:
+ ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG) - 1);
+ discriminant = *(ULONG *)pStubMsg->Buffer;
+ pStubMsg->Buffer += sizeof(ULONG);
+ break;
+ default:
+ FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
+ }
+ (*ppFormat)++;
+
+ if (pStubMsg->fHasNewCorrDesc)
+ *ppFormat += 6;
+ else
+ *ppFormat += 4;
+ return discriminant;
+}
+
+/**********************************************************************
+ * NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@]
*/
unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
unsigned char **ppMemory,
PFORMAT_STRING pFormat,
unsigned char fMustAlloc)
{
- FIXME("stub\n");
+ long discriminant;
+ unsigned short type, size;
+
+ TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
+ pFormat++;
+
+ /* Unmarshall discriminant */
+ discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
+ TRACE("unmarshalled discriminant %lx\n", discriminant);
+
+ pFormat += *(const SHORT*)pFormat;
+
+ size = *(const unsigned short*)pFormat;
+ pFormat += 2;
+
+ pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
+ if(!pFormat)
+ return NULL;
+
+ if(!*ppMemory || fMustAlloc)
+ *ppMemory = NdrAllocate(pStubMsg, size);
+
+ type = *(const unsigned short*)pFormat;
+ if(type & 0x8000)
+ {
+ pFormat++;
+ return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
+ }
+ else
+ {
+ PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
+ NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
+ if (m)
+ {
+ switch(*desc)
+ {
+ case RPC_FC_RP:
+ case RPC_FC_UP:
+ case RPC_FC_OP:
+ case RPC_FC_FP:
+ **(void***)ppMemory = NULL;
+ break;
+ }
+ return m(pStubMsg, (unsigned char **)*ppMemory, desc, fMustAlloc);
+ }
+ else FIXME("no marshaller for embedded type %02x\n", *desc);
+ }
return NULL;
}
@@ -2829,7 +3046,44 @@ void WINAPI NdrNonEncapsulatedUnionBuffe
unsigned char *pMemory,
PFORMAT_STRING pFormat)
{
- FIXME("stub\n");
+ unsigned short type;
+ TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
+
+ pFormat++;
+ /* Add discriminant size */
+ NdrBaseTypeBufferSize(pStubMsg, pMemory, pFormat);
+ pFormat++;
+
+ pFormat = get_non_encapsulated_union_arm(pStubMsg, pMemory, pFormat);
+ if(!pFormat)
+ return;
+
+ type = *(const unsigned short*)pFormat;
+ if(type & 0x8000)
+ {
+ pFormat++;
+ NdrBaseTypeBufferSize(pStubMsg, pMemory, pFormat);
+ }
+ else
+ {
+ PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
+ NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
+ if (m)
+ {
+ switch(*desc)
+ {
+ case RPC_FC_RP:
+ case RPC_FC_UP:
+ case RPC_FC_OP:
+ case RPC_FC_FP:
+ pMemory = *(void**)pMemory;
+ break;
+ }
+ m(pStubMsg, pMemory, desc);
+ }
+ else FIXME("no buffersizer for embedded type %02x\n", *desc);
+ }
+ return;
}
/***********************************************************************
More information about the wine-cvs
mailing list