This one is good for a laugh. It sucessfully marshalls "hello", but truncates "world," and fails to reply back to the client that it's done. Still, that's actual data going across the wire, so it kind of makes me happy. Perhaps I should say that it makes me "ha". LICENSE: X11 CHANGELOG: * dlls/rpcrt4: ndr_marshall.c, ndr_midl.c: Greg Turner <gmturner007@ameritech.net> - pull the buffer from the rpc message into the midl stub message during RpcServerInitializeNew - Attempt to implement NdrConformantStringUnmarshall - more assertions - comments and cleanups -- gmt "The purpose of government is to rein in the rights of the people" --President Bill Clinton, MTV interview, 1993
diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/ndr_marshall.c ./dlls/rpcrt4/ndr_marshall.c --- ../wine.test/dlls/rpcrt4/ndr_marshall.c 2002-10-26 21:53:13.000000000 -0500 +++ ./dlls/rpcrt4/ndr_marshall.c 2002-10-27 18:40:38.000000000 -0600 @@ -74,6 +74,7 @@ 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) ); @@ -88,7 +89,7 @@ *(c++) = *(pszMessage++); /* copy the string itself into the remaining space */ } else { ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME what to do here? */ + /* FIXME: raise an exception. */ return NULL; } @@ -104,12 +105,13 @@ { TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + 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 { ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME what to do here? */ + /* FIXME: raise an exception */ } } @@ -128,9 +130,77 @@ unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { - FIXME("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u): stub.\n", + UINT32 len; + + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); - return NULL; + + assert(pFormat && ppMemory && pStubMsg); + + /* get the length and check that we handle the format string... + FIXME: this is probably what NdrConformantStringMemorySize is for... so move code there? */ + + if (*pFormat == RPC_FC_C_CSTRING) { + /* What we should have here is a varying conformant string (of single-octet-chars): + * [ + * maxlen: DWORD + * offset: DWORD + * length: DWORD + * [ + * data: char[], null terminated. + * ] + * ] + * I think what we want to do is advance the buffer pointer in the pStubMsg + * up to the point of the char after the last marshalled char. + * FIXME: it is probably supposed to really advance either length or maxlength + * chars... but which? For now I have ignored the issue and just positioned + * after the terminating '\0'; this is (probably) wrong and will (probably) + * cause problems until its fixed. + */ + + pStubMsg->Buffer += 8; /* FIXME: do we care about maxlen? */ + len = LITTLE_ENDIAN_32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + } else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception. */ + return NULL; + } + + /* 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; + 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; + + while (*c != '\0') + *c++ = *(pStubMsg->Buffer++); + pStubMsg->Buffer++; /* advance past the '\0' */ + + } else + assert(FALSE); + + return NULL; /*is this always right? */ } /*********************************************************************** diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/ndr_midl.c ./dlls/rpcrt4/ndr_midl.c --- ../wine.test/dlls/rpcrt4/ndr_midl.c 2002-10-26 21:53:13.000000000 -0500 +++ ./dlls/rpcrt4/ndr_midl.c 2002-10-27 18:47:03.000000000 -0600 @@ -213,6 +213,8 @@ pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; pStubMsg->RpcMsg = pRpcMsg; + pStubMsg->Buffer = pRpcMsg->Buffer; + pStubMsg->BufferLength = pRpcMsg->BufferLength; /* FIXME: determine the proper return value */ return NULL; diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/rpc_message.c ./dlls/rpcrt4/rpc_message.c --- ../wine.test/dlls/rpcrt4/rpc_message.c 2002-10-26 21:53:13.000000000 -0500 +++ ./dlls/rpcrt4/rpc_message.c 2002-10-27 18:23:06.000000000 -0600 @@ -49,6 +49,7 @@ void* buf; TRACE("(%p)\n", pMsg); + /* FIXME: pfnAllocate? */ buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); if (buf) pMsg->Buffer = buf; /* FIXME: which errors to return? */ @@ -61,6 +62,7 @@ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) { TRACE("(%p)\n", pMsg); + /* FIXME: pfnFree? */ HeapFree(GetProcessHeap(), 0, pMsg->Buffer); pMsg->Buffer = NULL; return S_OK;