From 0e85f48f9d30bbb951cc8d89bc8034077eda6b05 Mon Sep 17 00:00:00 2001 From: Ove Kaaven Date: Sat, 1 Feb 2003 00:44:51 +0000 Subject: [PATCH] Implemented marshalling of pointers, simple and complex structures, conformant and complex arrays, and user-marshalled types. Improved marshalling of conformant strings and interface pointers a bit. --- dlls/rpcrt4/ndr_marshall.c | 1817 ++++++++++++++++++++++++++++++++++-- dlls/rpcrt4/ndr_misc.h | 15 + dlls/rpcrt4/ndr_ole.c | 23 +- dlls/rpcrt4/rpcrt4.spec | 62 +- 4 files changed, 1825 insertions(+), 92 deletions(-) diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c index c242c9fe47..2a556d9a78 100644 --- a/dlls/rpcrt4/ndr_marshall.c +++ b/dlls/rpcrt4/ndr_marshall.c @@ -34,8 +34,8 @@ #include "ndr_misc.h" #include "rpcndr.h" +#include "wine/unicode.h" #include "wine/rpcfc.h" -#include "objbase.h" #include "wine/debug.h" @@ -88,6 +88,266 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); 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)ALIGN_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 NDR_TABLE_SIZE 128 +#define NDR_TABLE_MASK 127 + +NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 */ + 0, + /* 0x11 */ + NdrPointerMarshall, NdrPointerMarshall, + NdrPointerMarshall, NdrPointerMarshall, + /* 0x15 */ + NdrSimpleStructMarshall, NdrSimpleStructMarshall, + 0, 0, 0, + NdrComplexStructMarshall, + /* 0x1b */ + NdrConformantArrayMarshall, 0, 0, 0, 0, 0, + NdrComplexArrayMarshall, + /* 0x22 */ + NdrConformantStringMarshall, 0, 0, + NdrConformantStringMarshall, 0, 0, 0, 0, + /* 0x2a */ + 0, 0, 0, 0, 0, + /* 0x2f */ + NdrInterfacePointerMarshall, + /* 0xb0 */ + 0, 0, 0, 0, + NdrUserMarshalMarshall +}; +NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 */ + 0, + /* 0x11 */ + NdrPointerUnmarshall, NdrPointerUnmarshall, + NdrPointerUnmarshall, NdrPointerUnmarshall, + /* 0x15 */ + NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, + 0, 0, 0, + NdrComplexStructUnmarshall, + /* 0x1b */ + NdrConformantArrayUnmarshall, 0, 0, 0, 0, 0, + NdrComplexArrayUnmarshall, + /* 0x22 */ + NdrConformantStringUnmarshall, 0, 0, + NdrConformantStringUnmarshall, 0, 0, 0, 0, + /* 0x2a */ + 0, 0, 0, 0, 0, + /* 0x2f */ + NdrInterfacePointerUnmarshall, + /* 0xb0 */ + 0, 0, 0, 0, + NdrUserMarshalUnmarshall +}; +NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 */ + 0, + /* 0x11 */ + NdrPointerBufferSize, NdrPointerBufferSize, + NdrPointerBufferSize, NdrPointerBufferSize, + /* 0x15 */ + NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, + 0, 0, 0, + NdrComplexStructBufferSize, + /* 0x1b */ + NdrConformantArrayBufferSize, 0, 0, 0, 0, 0, + NdrComplexArrayBufferSize, + /* 0x22 */ + NdrConformantStringBufferSize, 0, 0, + NdrConformantStringBufferSize, 0, 0, 0, 0, + /* 0x2a */ + 0, 0, 0, 0, 0, + /* 0x2f */ + NdrInterfacePointerBufferSize, + /* 0xb0 */ + 0, 0, 0, 0, + NdrUserMarshalBufferSize +}; +NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 */ + 0, + /* 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, 0, 0, 0, 0, + /* 0x2a */ + 0, 0, 0, 0, 0, + /* 0x2f */ + NdrInterfacePointerMemorySize, + /* 0xb0 */ + 0, 0, 0, 0, + NdrUserMarshalMemorySize +}; +NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 */ + 0, + /* 0x11 */ + NdrPointerFree, NdrPointerFree, + NdrPointerFree, NdrPointerFree, + /* 0x15 */ + NdrSimpleStructFree, NdrSimpleStructFree, + 0, 0, 0, + NdrComplexStructFree, + /* 0x1b */ + NdrConformantArrayFree, 0, 0, 0, 0, 0, + NdrComplexArrayFree, + /* 0x22 */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x2a */ + 0, 0, 0, 0, 0, + /* 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); +} + +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); + return pFormat+4; +} + +PFORMAT_STRING ComputeConformance(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def) +{ + BYTE dtype = pFormat[0] & 0xf; + DWORD ofs = (DWORD)pFormat[2] | ((DWORD)pFormat[3] << 8); + LPVOID ptr = NULL; + DWORD data = 0; + + if (pFormat[0] == 0xff) { + /* null descriptor */ + pStubMsg->MaxCount = def; + goto finish_conf; + } + + switch (pFormat[0] & 0xf0) { + case RPC_FC_NORMAL_CONFORMANCE: + TRACE("normal conformance, ofs=%ld\n", ofs); + ptr = pMemory + ofs; + break; + case RPC_FC_POINTER_CONFORMANCE: + TRACE("pointer conformance, ofs=%ld\n", ofs); + ptr = pStubMsg->Memory + ofs; + break; + case RPC_FC_TOP_LEVEL_CONFORMANCE: + TRACE("toplevel conformance, ofs=%ld\n", ofs); + if (pStubMsg->StackTop) { + ptr = pStubMsg->StackTop + ofs; + } + else { + /* -Os mode, MaxCount 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); + pStubMsg->MaxCount = data; + goto finish_conf; + case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: + FIXME("toplevel multidimensional conformance, ofs=%ld\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: + /* ofs is index into StubDesc->apfnExprEval */ + FIXME("handle callback\n"); + goto finish_conf; + default: + break; + } + + switch (dtype) { + case RPC_FC_LONG: + case RPC_FC_ULONG: + data = *(DWORD*)ptr; + break; + case RPC_FC_SHORT: + data = *(SHORT*)ptr; + break; + case RPC_FC_USHORT: + data = *(USHORT*)ptr; + break; + case RPC_FC_SMALL: + data = *(CHAR*)ptr; + break; + case RPC_FC_USMALL: + data = *(UCHAR*)ptr; + break; + default: + FIXME("unknown conformance data type %x\n", dtype); + goto done_conf_grab; + } + TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data); + +done_conf_grab: + switch (pFormat[1]) { + case 0: /* no op */ + pStubMsg->MaxCount = data; + break; + case RPC_FC_DEREFERENCE: + /* already handled */ + break; + default: + FIXME("unknown conformance op %d\n", pFormat[1]); + goto finish_conf; + } + +finish_conf: + TRACE("resulting conformance is %ld\n", pStubMsg->MaxCount); + return pFormat+4; +} + + /* * NdrConformantString: * @@ -111,31 +371,45 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pszMessage, PFORMAT_STRING pFormat) { - UINT32 len, i; + unsigned long len, esize; unsigned char *c; TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); assert(pFormat); if (*pFormat == RPC_FC_C_CSTRING) { - len = strlen(pszMessage); - assert( (pStubMsg->BufferLength > (len + 13)) && (pStubMsg->Buffer != NULL) ); - c = pStubMsg->Buffer; - memset(c, 0, 12); - NDR_LOCAL_UINT32_WRITE(c, len + 1); /* max length: strlen + 1 (for '\0') */ - c += 8; /* offset: 0 */ - NDR_LOCAL_UINT32_WRITE(c, len + 1); /* actual length: (same) */ - c += 4; - for (i = 0; i <= len; i++) - *(c++) = *(pszMessage++); /* the string itself */ - } else { + TRACE("string=%s\n", debugstr_a(pszMessage)); + len = strlen(pszMessage)+1; + esize = 1; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); + len = strlenW((LPWSTR)pszMessage)+1; + esize = 2; + } + else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception. */ return NULL; } + + if (pFormat[1] != RPC_FC_PAD) { + FIXME("sized string format=%d\n", pFormat[1]); + } + + assert( (pStubMsg->BufferLength >= (len*esize + 13)) && (pStubMsg->Buffer != NULL) ); + + c = pStubMsg->Buffer; + memset(c, 0, 12); + NDR_LOCAL_UINT32_WRITE(c, len); /* max length: strlen + 1 (for '\0') */ + c += 8; /* offset: 0 */ + NDR_LOCAL_UINT32_WRITE(c, len); /* actual length: (same) */ + c += 4; + memcpy(c, pszMessage, len*esize); /* the string itself */ + c += len*esize; + pStubMsg->Buffer = c; /* success */ - pStubMsg->fBufferValid = 1; return NULL; /* is this always right? */ } @@ -150,11 +424,22 @@ void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, assert(pFormat); if (*pFormat == RPC_FC_C_CSTRING) { /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 1 octet for '\0' */ - pStubMsg->BufferLength = strlen(pMemory) + 13 + BUFFER_PARANOIA; - } else { + TRACE("string=%s\n", debugstr_a(pMemory)); + pStubMsg->BufferLength += strlen(pMemory) + 13 + BUFFER_PARANOIA; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 2 octets for L'\0' */ + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); + pStubMsg->BufferLength += strlenW((LPWSTR)pMemory)*2 + 14 + BUFFER_PARANOIA; + } + else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ } + + if (pFormat[1] != RPC_FC_PAD) { + FIXME("sized string format=%d\n", pFormat[1]); + } } /************************************************************************ @@ -171,11 +456,19 @@ unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat == RPC_FC_C_CSTRING) { rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */ - } else { + } + else if (*pFormat == RPC_FC_C_WSTRING) { + rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */ + } + else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ } + if (pFormat[1] != RPC_FC_PAD) { + FIXME("sized string format=%d\n", pFormat[1]); + } + TRACE(" --> %lu\n", rslt); return rslt; } @@ -186,60 +479,1470 @@ unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { - unsigned long len, ofs; + unsigned long len, esize, ofs; + unsigned char *pMem; TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); assert(pFormat && ppMemory && pStubMsg); - len = NdrConformantStringMemorySize(pStubMsg, pFormat); + pStubMsg->Buffer += 4; + ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; - /* now the actual length (in bytes) that we need to store - the unmarshalled string is in len, including terminating '\0' */ - - if ( fMustAlloc || (!(*ppMemory)) || (pStubMsg->Memory != *ppMemory) || - (pStubMsg->MemorySize < (len+BUFFER_PARANOIA)) ) { - /* crap, looks like we need to do something about the Memory. I don't - understand, it doesn't look like Microsoft is doing this the same - way... but then how do they do it? AFAICS the Memory is never deallocated by - the stub code so where does it go?... anyhow, I guess we'll just do it - our own way for now... */ - pStubMsg->MemorySize = len + BUFFER_PARANOIA; - pStubMsg->Memory = *ppMemory; - /* FIXME: pfnAllocate? or does that not apply to these "Memory" parts? */ - *ppMemory = pStubMsg->Memory = - HeapReAlloc(GetProcessHeap(), 0, pStubMsg->Memory, pStubMsg->MemorySize); - } - - if (!(pStubMsg->Memory)) { - ERR("Memory Allocation Failure\n"); - /* FIXME: raise an exception */ - return NULL; - } - - /* OK, we've got our ram. now do the real unmarshalling */ - if (*pFormat == RPC_FC_C_CSTRING) { - char *c = *ppMemory; - - pStubMsg->Buffer += 4; - ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - - c += ofs; /* presumably this will always be zero, otherwise the string is no good */ - - while ((*c++ = *(pStubMsg->Buffer++)) != '\0') - ; - } else { + if (*pFormat == RPC_FC_C_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; + else { ERR("Unhandled string type: %#x\n", *pFormat); /* FIXME: raise an exception */ + esize = 0; + } + + if (pFormat[1] != RPC_FC_PAD) { + FIXME("sized string format=%d\n", pFormat[1]); + } + + if (fMustAlloc) { + *ppMemory = NdrAllocate(pStubMsg, len*esize + BUFFER_PARANOIA); + } else { + if (pStubMsg->ReuseBuffer && !*ppMemory) + /* for servers, we may just point straight into the RPC buffer, I think + * (I guess that's what MS does since MIDL code doesn't try to free) */ + *ppMemory = pStubMsg->Buffer - ofs*esize; + /* for clients, memory should be provided by caller */ + } + + pMem = *ppMemory + ofs*esize; + + if (pMem != pStubMsg->Buffer) + memcpy(pMem, pStubMsg->Buffer, len*esize); + + pStubMsg->Buffer += len*esize; + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a(pMem)); + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pMem)); } return NULL; /* FIXME: is this always right? */ } +/*********************************************************************** + * PointerMarshall + */ +void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MARSHALL m; + + TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); + TRACE("type=%d, attr=%d\n", type, attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(SHORT*)pFormat; + if (attr & RPC_FC_P_DEREF) FIXME("deref?\n"); + + *(LPVOID*)Buffer = 0; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + } + + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no marshaller for data type=%02x\n", *desc); +} + +/*********************************************************************** + * PointerUnmarshall + */ +void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char **pPointer, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + + TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc); + TRACE("type=%d, attr=%d\n", type, attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(SHORT*)pFormat; + if (attr & RPC_FC_P_DEREF) FIXME("deref?\n"); + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + } + + *pPointer = NULL; + + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pPointer, desc, fMustAlloc); + else FIXME("no unmarshaller for data type=%02x\n", *desc); + TRACE("pointer=%p\n", *pPointer); +} + +/*********************************************************************** + * PointerBufferSize + */ +void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=%d, attr=%d\n", type, attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(SHORT*)pFormat; + if (attr & RPC_FC_P_DEREF) FIXME("deref?\n"); + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + } + + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no buffersizer for data type=%02x\n", *desc); +} + +/*********************************************************************** + * PointerMemorySize [RPCRT4.@] + */ +unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MEMORYSIZE m; + + FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat); + TRACE("type=%d, attr=%d\n", type, attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(SHORT*)pFormat; + if (attr & RPC_FC_P_DEREF) FIXME("deref?\n"); + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + } + + m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, desc); + else FIXME("no memorysizer for data type=%02x\n", *desc); + + return 0; +} + +/*********************************************************************** + * PointerFree [RPCRT4.@] + */ +void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_FREE m; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=%d, attr=%d\n", type, attr); + if (attr & RPC_FC_P_DONTFREE) return; + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(SHORT*)pFormat; + if (attr & RPC_FC_P_DEREF) FIXME("deref?\n"); + + if (!Pointer) return; + + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + + /* hmm... is this sensible? + * perhaps we should check if the memory comes from NdrAllocate, + * and deallocate only if so - checking if the pointer is between + * BufferStart and BufferEnd is probably no good since the buffer + * may be reallocated when the server wants to marshal the reply */ + switch (*desc) { + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_BOGUS_ARRAY: + break; + default: + FIXME("unhandled data type=%02x\n", *desc); + case RPC_FC_CARRAY: + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (pStubMsg->ReuseBuffer) goto notfree; + break; + } + + if (attr & RPC_FC_P_ONSTACK) { + TRACE("not freeing stack ptr %p\n", Pointer); + return; + } + TRACE("freeing %p\n", Pointer); + pStubMsg->pfnFree(Pointer); + return; +notfree: + TRACE("not freeing %p\n", Pointer); +} + +/*********************************************************************** + * EmbeddedPointerMarshall + */ +unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned long Offset = pStubMsg->Offset; + unsigned ofs, rep, count, stride, xofs; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + ofs = 0; + count = 1; + xofs = 0; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(WORD*)&pFormat[2]; + stride = *(WORD*)&pFormat[4]; + ofs = *(WORD*)&pFormat[6]; + count = *(WORD*)&pFormat[8]; + xofs = 0; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = pStubMsg->MaxCount; + stride = *(WORD*)&pFormat[2]; + ofs = *(WORD*)&pFormat[4]; + count = *(WORD*)&pFormat[6]; + xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; + pFormat += 8; + break; + } + /* ofs doesn't seem to matter in this context */ + while (rep) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + xofs; + unsigned u; + for (u=0; uBufferMark; + unsigned long Offset = pStubMsg->Offset; + unsigned ofs, rep, count, stride, xofs; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + ofs = 0; + count = 1; + xofs = 0; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(WORD*)&pFormat[2]; + stride = *(WORD*)&pFormat[4]; + ofs = *(WORD*)&pFormat[6]; + count = *(WORD*)&pFormat[8]; + xofs = 0; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = pStubMsg->MaxCount; + stride = *(WORD*)&pFormat[2]; + ofs = *(WORD*)&pFormat[4]; + count = *(WORD*)&pFormat[6]; + xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; + pFormat += 8; + break; + } + /* ofs doesn't seem to matter in this context */ + while (rep) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = *ppMemory + xofs; + unsigned u; + for (u=0; uOffset; + unsigned ofs, rep, count, stride, xofs; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + ofs = 0; + count = 1; + xofs = 0; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(WORD*)&pFormat[2]; + stride = *(WORD*)&pFormat[4]; + ofs = *(WORD*)&pFormat[6]; + count = *(WORD*)&pFormat[8]; + xofs = 0; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = pStubMsg->MaxCount; + stride = *(WORD*)&pFormat[2]; + ofs = *(WORD*)&pFormat[4]; + count = *(WORD*)&pFormat[6]; + xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; + pFormat += 8; + break; + } + /* ofs doesn't seem to matter in this context */ + while (rep) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + xofs; + unsigned u; + for (u=0; uOffset; + unsigned char *Mark = pStubMsg->BufferMark; + unsigned ofs, rep, count, stride, xofs; + + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + if (*pFormat != RPC_FC_PP) return 0; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + ofs = 0; + count = 1; + xofs = 0; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(WORD*)&pFormat[2]; + stride = *(WORD*)&pFormat[4]; + ofs = *(WORD*)&pFormat[6]; + count = *(WORD*)&pFormat[8]; + xofs = 0; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = pStubMsg->MaxCount; + stride = *(WORD*)&pFormat[2]; + ofs = *(WORD*)&pFormat[4]; + count = *(WORD*)&pFormat[6]; + xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; + pFormat += 8; + break; + } + /* ofs doesn't seem to matter in this context */ + while (rep) { + PFORMAT_STRING info = pFormat; + unsigned u; + for (u=0; uOffset; + unsigned ofs, rep, count, stride, xofs; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + ofs = 0; + count = 1; + xofs = 0; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(WORD*)&pFormat[2]; + stride = *(WORD*)&pFormat[4]; + ofs = *(WORD*)&pFormat[6]; + count = *(WORD*)&pFormat[8]; + xofs = 0; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = pStubMsg->MaxCount; + stride = *(WORD*)&pFormat[2]; + ofs = *(WORD*)&pFormat[4]; + count = *(WORD*)&pFormat[6]; + xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; + pFormat += 8; + break; + } + /* ofs doesn't seem to matter in this context */ + while (rep) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + xofs; + unsigned u; + for (u=0; uBufferMark = pStubMsg->Buffer; + PointerMarshall(pStubMsg, pStubMsg->Buffer, *(unsigned char**)pMemory, pFormat); + pStubMsg->Buffer += 4; + return NULL; +} + +/*********************************************************************** + * NdrPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (fMustAlloc) { + *ppMemory = NdrAllocate(pStubMsg, 4); + } else { + if (pStubMsg->ReuseBuffer && !*ppMemory) + /* for servers, we may just point straight into the RPC buffer, I think */ + *ppMemory = pStubMsg->Buffer; + /* else: for clients, memory should be provided by caller */ + } + + pStubMsg->BufferMark = pStubMsg->Buffer; + PointerUnmarshall(pStubMsg, pStubMsg->Buffer, *(unsigned char***)ppMemory, pFormat, fMustAlloc); + pStubMsg->Buffer += 4; + + return NULL; +} + +/*********************************************************************** + * NdrPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + pStubMsg->BufferLength += 4; + PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pFormat); +} + +/*********************************************************************** + * NdrPointerMemorySize [RPCRT4.@] + */ +unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); + return 0; +} + +/*********************************************************************** + * NdrPointerFree [RPCRT4.@] + */ +void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + PointerFree(pStubMsg, *(unsigned char**)pMemory, pFormat); + *(unsigned char**)pMemory = NULL; /* just in case */ +} + +/*********************************************************************** + * NdrSimpleStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + memcpy(pStubMsg->Buffer, pMemory, size); + pStubMsg->BufferMark = pStubMsg->Buffer; + pStubMsg->Buffer += size; + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (fMustAlloc) { + *ppMemory = NdrAllocate(pStubMsg, size); + memcpy(*ppMemory, pStubMsg->Buffer, size); + } else { + if (pStubMsg->ReuseBuffer && !*ppMemory) + /* for servers, we may just point straight into the RPC buffer, I think + * (I guess that's what MS does since MIDL code doesn't try to free) */ + *ppMemory = pStubMsg->Buffer; + else + /* for clients, memory should be provided by caller */ + memcpy(*ppMemory, pStubMsg->Buffer, size); + } + + pStubMsg->BufferMark = pStubMsg->Buffer; + pStubMsg->Buffer += size; + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + pStubMsg->BufferLength += size; + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); +} + +/*********************************************************************** + * NdrSimpleStructMemorySize [RPCRT4.@] + */ +unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMemorySize(pStubMsg, pFormat+4); + return 0; +} + +/*********************************************************************** + * NdrSimpleStructFree [RPCRT4.@] + */ +void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); +} + + +unsigned char * WINAPI ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_MARSHALL m; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_SHORT: + case RPC_FC_USHORT: + TRACE("short=%d\n", *(WORD*)pMemory); + memcpy(pStubMsg->Buffer, pMemory, 2); + pStubMsg->Buffer += 2; + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + TRACE("long=%ld\n", *(DWORD*)pMemory); + memcpy(pStubMsg->Buffer, pMemory, 4); + pStubMsg->Buffer += 4; + pMemory += 4; + break; + case RPC_FC_POINTER: + NdrPointerMarshall(pStubMsg, pMemory, pPointer); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 3); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 7); + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(SHORT*)pFormat; + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, desc); + else FIXME("no marshaller for embedded type %02x\n", *desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +unsigned char * WINAPI ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer, + unsigned char fMustAlloc) +{ + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_SHORT: + case RPC_FC_USHORT: + memcpy(pMemory, pStubMsg->Buffer, 2); + TRACE("short=%d\n", *(WORD*)pMemory); + pStubMsg->Buffer += 2; + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + memcpy(pMemory, pStubMsg->Buffer, 4); + TRACE("long=%ld\n", *(DWORD*)pMemory); + pStubMsg->Buffer += 4; + pMemory += 4; + break; + case RPC_FC_POINTER: + NdrPointerUnmarshall(pStubMsg, &pMemory, pPointer, fMustAlloc); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 3); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 7); + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(SHORT*)pFormat; + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, &pMemory, desc, fMustAlloc); + else FIXME("no unmarshaller for embedded type %02x\n", *desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +unsigned char * WINAPI ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_SHORT: + case RPC_FC_USHORT: + pStubMsg->BufferLength += 2; + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + pStubMsg->BufferLength += 4; + pMemory += 4; + break; + case RPC_FC_POINTER: + NdrPointerBufferSize(pStubMsg, pMemory, pPointer); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 3); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 7); + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(SHORT*)pFormat; + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, desc); + else FIXME("no buffersizer for embedded type %02x\n", *desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +unsigned char * WINAPI ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_FREE m; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_SHORT: + case RPC_FC_USHORT: + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + pMemory += 4; + break; + case RPC_FC_POINTER: + NdrPointerFree(pStubMsg, pMemory, pPointer); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 3); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 7); + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(SHORT*)pFormat; + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, desc); + else FIXME("no freer for embedded type %02x\n", *desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +unsigned long WINAPI ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING desc; + unsigned long size = 0; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_SHORT: + case RPC_FC_USHORT: + size += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + size += 4; + break; + case RPC_FC_POINTER: + size += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_LENGTH(size, 3); + break; + case RPC_FC_ALIGNM8: + ALIGN_LENGTH(size, 7); + break; + case RPC_FC_EMBEDDED_COMPLEX: + size += pFormat[1]; + pFormat += 2; + desc = pFormat + *(SHORT*)pFormat; + switch (*desc) { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_BOGUS_STRUCT: + size += *(WORD*)&pFormat[2]; + break; + case RPC_FC_USER_MARSHAL: + size += *(WORD*)&pFormat[4]; + break; + default: + FIXME("unhandled embedded type %02x\n", *desc); + } + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return size; +} + +/*********************************************************************** + * NdrComplexStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + pFormat += 4; + if (*(WORD*)pFormat) conf_array = pFormat + *(WORD*)pFormat; + pFormat += 2; + if (*(WORD*)pFormat) pointer_desc = pFormat + *(WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(LPWORD)(pFormat+2); + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *pMemory; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, size); + + pFormat += 4; + if (*(WORD*)pFormat) conf_array = pFormat + *(WORD*)pFormat; + pFormat += 2; + if (*(WORD*)pFormat) pointer_desc = pFormat + *(WORD*)pFormat; + pFormat += 2; + + pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc); + + if (conf_array) + NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + pFormat += 4; + if (*(WORD*)pFormat) conf_array = pFormat + *(WORD*)pFormat; + pFormat += 2; + if (*(WORD*)pFormat) pointer_desc = pFormat + *(WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; +} + +/*********************************************************************** + * NdrComplexStructMemorySize [RPCRT4.@] + */ +unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + + pFormat += 4; + if (*(WORD*)pFormat) conf_array = pFormat + *(WORD*)pFormat; + pFormat += 2; + if (*(WORD*)pFormat) pointer_desc = pFormat + *(WORD*)pFormat; + pFormat += 2; + + return 0; +} + +/*********************************************************************** + * NdrComplexStructFree [RPCRT4.@] + */ +void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + pFormat += 4; + if (*(WORD*)pFormat) conf_array = pFormat + *(WORD*)pFormat; + pFormat += 2; + if (*(WORD*)pFormat) pointer_desc = pFormat + *(WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayFree(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; +} + +/*********************************************************************** + * NdrConformantArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + size = pStubMsg->MaxCount; + + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size); + pStubMsg->Buffer += 4; + + memcpy(pStubMsg->Buffer, pMemory, size*esize); + pStubMsg->BufferMark = pStubMsg->Buffer; + pStubMsg->Buffer += size*esize; + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + DWORD size = 0, esize = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + size = pStubMsg->MaxCount; + + if (fMustAlloc) { + *ppMemory = NdrAllocate(pStubMsg, size*esize); + memcpy(*ppMemory, pStubMsg->Buffer, size*esize); + } else { + if (pStubMsg->ReuseBuffer && !*ppMemory) + /* for servers, we may just point straight into the RPC buffer, I think + * (I guess that's what MS does since MIDL code doesn't try to free) */ + *ppMemory = pStubMsg->Buffer; + else + /* for clients, memory should be provided by caller */ + memcpy(*ppMemory, pStubMsg->Buffer, size*esize); + } + + pStubMsg->BufferMark = pStubMsg->Buffer; + pStubMsg->Buffer += size*esize; + + EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(LPWORD)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + size = pStubMsg->MaxCount; + + pStubMsg->BufferLength += size*esize; + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantArrayMemorySize [RPCRT4.@] + */ +unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + DWORD size = 0; + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + size = pStubMsg->MaxCount; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return 0; +} + +/*********************************************************************** + * NdrConformantArrayFree [RPCRT4.@] + */ +void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrComplexArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, count, def; + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + def = *(WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + size = pStubMsg->MaxCount; + TRACE("conformance=%ld\n", size); + + if (*(DWORD*)pFormat != 0xffffffff) + FIXME("compute variance\n"); + pFormat += 4; + + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size); + pStubMsg->Buffer += 4; + + for (count=0; countMaxCount; + TRACE("conformance=%ld\n", size); + + pFormat += 4; + + esize = ComplexStructSize(pStubMsg, pFormat); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, size*esize); + + pMemory = *ppMemory; + for (count=0; countMaxCount; + TRACE("conformance=%ld\n", size); + + if (*(DWORD*)pFormat != 0xffffffff) + FIXME("compute variance\n"); + pFormat += 4; + + for (count=0; countMaxCount; + TRACE("conformance=%ld\n", size); + + pFormat += 4; + + return 0; +} + +/*********************************************************************** + * NdrComplexArrayFree [RPCRT4.@] + */ +void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, count, def; + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + def = *(WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + size = pStubMsg->MaxCount; + TRACE("conformance=%ld\n", size); + + if (*(DWORD*)pFormat != 0xffffffff) + FIXME("compute variance\n"); + pFormat += 4; + + for (count=0; countdwDestContext, + pStubMsg->RpcMsg->DataRepresentation); +} + +/*********************************************************************** + * NdrUserMarshalMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ +/* unsigned flags = pFormat[1]; */ + unsigned index = *(WORD*)&pFormat[2]; + unsigned long uflag = UserMarshalFlags(pStubMsg); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( + &uflag, pStubMsg->Buffer, pMemory); + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ +/* unsigned flags = pFormat[1];*/ + unsigned index = *(WORD*)&pFormat[2]; + DWORD memsize = *(WORD*)&pFormat[4]; + unsigned long uflag = UserMarshalFlags(pStubMsg); + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + TRACE("index=%d\n", index); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( + &uflag, pStubMsg->Buffer, *ppMemory); + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalBufferSize [RPCRT4.@] + */ +void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ +/* unsigned flags = pFormat[1];*/ + unsigned index = *(WORD*)&pFormat[2]; + DWORD bufsize = *(WORD*)&pFormat[6]; + unsigned long uflag = UserMarshalFlags(pStubMsg); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + if (bufsize) { + TRACE("size=%ld\n", bufsize); + pStubMsg->BufferLength += bufsize; + return; + } + + pStubMsg->BufferLength = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( + &uflag, pStubMsg->BufferLength, pMemory); +} + +/*********************************************************************** + * NdrUserMarshalMemorySize [RPCRT4.@] + */ +unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ +/* DWORD memsize = *(WORD*)&pFormat[4]; */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + return 0; +} + +/*********************************************************************** + * NdrUserMarshalFree [RPCRT4.@] + */ +void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ +/* unsigned flags = pFormat[1]; */ + unsigned index = *(WORD*)&pFormat[2]; + unsigned long uflag = UserMarshalFlags(pStubMsg); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( + &uflag, pMemory); +} + /*********************************************************************** * NdrConvert [RPCRT4.@] */ diff --git a/dlls/rpcrt4/ndr_misc.h b/dlls/rpcrt4/ndr_misc.h index 2fdd63133d..931a01c915 100644 --- a/dlls/rpcrt4/ndr_misc.h +++ b/dlls/rpcrt4/ndr_misc.h @@ -32,4 +32,19 @@ LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, HRESULT RPCRT4_GetPSFactory(REFIID riid, struct IPSFactoryBuffer **ppPS); +PFORMAT_STRING ComputeConformance(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def); + +typedef unsigned char* (WINAPI *NDR_MARSHALL) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char); +typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +typedef unsigned long (WINAPI *NDR_MEMORYSIZE)(PMIDL_STUB_MESSAGE, PFORMAT_STRING); +typedef void (WINAPI *NDR_FREE) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); + +extern NDR_MARSHALL NdrMarshaller[]; +extern NDR_UNMARSHALL NdrUnmarshaller[]; +extern NDR_BUFFERSIZE NdrBufferSizer[]; +extern NDR_MEMORYSIZE NdrMemorySizer[]; +extern NDR_FREE NdrFreer[]; + #endif /* __WINE_NDR_MISC_H */ diff --git a/dlls/rpcrt4/ndr_ole.c b/dlls/rpcrt4/ndr_ole.c index 611010c6ca..3e05275e82 100644 --- a/dlls/rpcrt4/ndr_ole.c +++ b/dlls/rpcrt4/ndr_ole.c @@ -36,7 +36,9 @@ #include "objbase.h" +#include "ndr_misc.h" #include "rpcndr.h" +#include "wine/rpcfc.h" #include "wine/debug.h" @@ -212,6 +214,21 @@ static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init) return (LPSTREAM)This; } +const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + const IID *riid; + if (!pFormat) return &IID_IUnknown; + TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); + if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); + if (pFormat[1] == RPC_FC_CONSTANT_IID) + return (const IID*)&pFormat[2]; + + ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); + riid = (const IID *)pStubMsg->MaxCount; + if (!riid) riid = &IID_IUnknown; + return riid; +} + /*********************************************************************** * NdrInterfacePointerMarshall [RPCRT4.@] */ @@ -219,12 +236,11 @@ unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - const IID *riid = (const IID *)pStubMsg->MaxCount; + const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); LPSTREAM stream; HRESULT hr; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (!riid) riid = &IID_IUnknown; pStubMsg->MaxCount = 0; if (!LoadCOM()) return NULL; stream = RpcStream_Create(pStubMsg, TRUE); @@ -262,12 +278,11 @@ void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - const IID *riid = (const IID *)pStubMsg->MaxCount; + const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); ULONG size = 0; HRESULT hr; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (!riid) riid = &IID_IUnknown; if (!LoadCOM()) return; hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, diff --git a/dlls/rpcrt4/rpcrt4.spec b/dlls/rpcrt4/rpcrt4.spec index 732dfbff12..086e8e166e 100644 --- a/dlls/rpcrt4/rpcrt4.spec +++ b/dlls/rpcrt4/rpcrt4.spec @@ -222,7 +222,7 @@ @ stdcall NdrDllRegisterProxy(long ptr ptr) NdrDllRegisterProxy @ stdcall NdrDllUnregisterProxy(long ptr ptr) NdrDllUnregisterProxy -@ stub NdrAllocate +@ stdcall NdrAllocate(ptr long) NdrAllocate @ stub NdrAsyncClientCall @ stub NdrAsyncServerCall @ stub NdrClearOutParameters @@ -330,21 +330,21 @@ @ stub NdrByteCountPointerUnmarshall @ stub NdrClientContextMarshall @ stub NdrClientContextUnmarshall -@ stub NdrComplexArrayBufferSize -@ stub NdrComplexArrayFree -@ stub NdrComplexArrayMarshall -@ stub NdrComplexArrayMemorySize -@ stub NdrComplexArrayUnmarshall -@ stub NdrComplexStructBufferSize -@ stub NdrComplexStructFree -@ stub NdrComplexStructMarshall -@ stub NdrComplexStructMemorySize -@ stub NdrComplexStructUnmarshall -@ stub NdrConformantArrayBufferSize -@ stub NdrConformantArrayFree -@ stub NdrConformantArrayMarshall -@ stub NdrConformantArrayMemorySize -@ stub NdrConformantArrayUnmarshall +@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr) NdrComplexArrayBufferSize +@ stdcall NdrComplexArrayFree(ptr ptr ptr) NdrComplexArrayFree +@ stdcall NdrComplexArrayMarshall(ptr ptr ptr) NdrComplexArrayMarshall +@ stdcall NdrComplexArrayMemorySize(ptr ptr) NdrComplexArrayMemorySize +@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long) NdrComplexArrayUnmarshall +@ stdcall NdrComplexStructBufferSize(ptr ptr ptr) NdrComplexStructBufferSize +@ stdcall NdrComplexStructFree(ptr ptr ptr) NdrComplexStructFree +@ stdcall NdrComplexStructMarshall(ptr ptr ptr) NdrComplexStructMarshall +@ stdcall NdrComplexStructMemorySize(ptr ptr) NdrComplexStructMemorySize +@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long) NdrComplexStructUnmarshall +@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr) NdrConformantArrayBufferSize +@ stdcall NdrConformantArrayFree(ptr ptr ptr) NdrConformantArrayFree +@ stdcall NdrConformantArrayMarshall(ptr ptr ptr) NdrConformantArrayMarshall +@ stdcall NdrConformantArrayMemorySize(ptr ptr) NdrConformantArrayMemorySize +@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long) NdrConformantArrayUnmarshall @ stdcall NdrConformantStringBufferSize(ptr ptr ptr) NdrConformantStringBufferSize @ stdcall NdrConformantStringMarshall(ptr ptr ptr) NdrConformantStringMarshall @ stdcall NdrConformantStringMemorySize(ptr ptr) NdrConformantStringMemorySize @@ -388,11 +388,11 @@ @ stub NdrNonEncapsulatedUnionMarshall @ stub NdrNonEncapsulatedUnionMemorySize @ stub NdrNonEncapsulatedUnionUnmarshall -@ stub NdrPointerBufferSize -@ stub NdrPointerFree -@ stub NdrPointerMarshall -@ stub NdrPointerMemorySize -@ stub NdrPointerUnmarshall +@ stdcall NdrPointerBufferSize(ptr ptr ptr) NdrPointerBufferSize +@ stdcall NdrPointerFree(ptr ptr ptr) NdrPointerFree +@ stdcall NdrPointerMarshall(ptr ptr ptr) NdrPointerMarshall +@ stdcall NdrPointerMemorySize(ptr ptr) NdrPointerMemorySize +@ stdcall NdrPointerUnmarshall(ptr ptr ptr long) NdrPointerUnmarshall @ stub NdrServerContextMarshall @ stub NdrServerContextUnmarshall @ stub NdrServerContextNewMarshall # wxp @@ -404,19 +404,19 @@ @ stub NdrServerInitializeUnmarshall @ stub NdrServerMarshall @ stub NdrServerUnmarshall -@ stub NdrSimpleStructBufferSize -@ stub NdrSimpleStructFree -@ stub NdrSimpleStructMarshall -@ stub NdrSimpleStructMemorySize -@ stub NdrSimpleStructUnmarshall +@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr) NdrSimpleStructBufferSize +@ stdcall NdrSimpleStructFree(ptr ptr ptr) NdrSimpleStructFree +@ stdcall NdrSimpleStructMarshall(ptr ptr ptr) NdrSimpleStructMarshall +@ stdcall NdrSimpleStructMemorySize(ptr ptr) NdrSimpleStructMemorySize +@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long) NdrSimpleStructUnmarshall @ stub NdrSimpleTypeMarshall @ stub NdrSimpleTypeUnmarshall -@ stub NdrUserMarshalBufferSize -@ stub NdrUserMarshalFree -@ stub NdrUserMarshalMarshall -@ stub NdrUserMarshalMemorySize +@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr) NdrUserMarshalBufferSize +@ stdcall NdrUserMarshalFree(ptr ptr ptr) NdrUserMarshalFree +@ stdcall NdrUserMarshalMarshall(ptr ptr ptr) NdrUserMarshalMarshall +@ stdcall NdrUserMarshalMemorySize(ptr ptr) NdrUserMarshalMemorySize @ stub NdrUserMarshalSimpleTypeConvert -@ stub NdrUserMarshalUnmarshall +@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long) NdrUserMarshalUnmarshall @ stub NdrVaryingArrayBufferSize @ stub NdrVaryingArrayFree @ stub NdrVaryingArrayMarshall