- more comments and comment-cleanup
[wine/multimedia.git] / dlls / rpcrt4 / ndr_marshall.c
blobfb6e595edf0620a4dfdc36df0eac744f5396a628
1 /*
2 * NDR data marshalling
4 * Copyright 2002 Greg Turner
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * TODO:
21 * - figure out whether we *really* got this right
22 * - check for errors and throw exceptions
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
34 #include "ndr_misc.h"
36 #include "wine/rpcfc.h"
37 #include "wine/obj_base.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43 #define BUFFER_PARANOIA 20
45 #if defined(__i386__)
46 #define LITTLE_ENDIAN_32_WRITE(pchar, word32) \
47 (*((UINT32 *)(pchar)) = (word32))
49 #define LITTLE_ENDIAN_32_READ(pchar) \
50 (*((UINT32 *)(pchar)))
51 #else
52 /* these would work for i386 too, but less efficient */
53 #define LITTLE_ENDIAN_32_WRITE(pchar, word32) \
54 (*(pchar) = LOBYTE(LOWORD(word32)), \
55 *((pchar)+1) = HIBYTE(LOWORD(word32)), \
56 *((pchar)+2) = LOBYTE(HIWORD(word32)), \
57 *((pchar)+3) = HIBYTE(HIWORD(word32)), \
58 (word32)) /* allow as r-value */
60 #define LITTLE_ENDIAN_32_READ(pchar) \
61 (MAKELONG( \
62 MAKEWORD(*(pchar), *((pchar)+1)) \
63 MAKEWORD(*((pchar)+2), *((pchar)+3)))
64 #endif
67 * NdrConformantString:
69 * What MS calls a ConformantString is, in DCE terminology,
70 * a Varying Conformant String.
71 * [
72 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
73 * offset: DWORD (actual elements begin at (offset) CHARTYPE's into (data))
74 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
75 * [
76 * data: CHARTYPE[maxlen]
77 * ]
78 * ], where CHARTYPE is the appropriate character type (specified externally)
82 /***********************************************************************
83 * NdrConformantStringMarshall [RPCRT4.@]
85 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pszMessage,
86 PFORMAT_STRING pFormat)
88 UINT32 len, i;
89 unsigned char *c;
91 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
93 assert(pFormat);
94 if (*pFormat == RPC_FC_C_CSTRING) {
95 len = strlen(pszMessage);
96 assert( (pStubMsg->BufferLength > (len + 13)) && (pStubMsg->Buffer != NULL) );
97 c = pStubMsg->Buffer;
98 memset(c, 0, 12);
99 LITTLE_ENDIAN_32_WRITE(c, len + 1); /* max length: strlen + 1 (for '\0') */
100 c += 8; /* offset: 0 */
101 LITTLE_ENDIAN_32_WRITE(c, len + 1); /* actual length: (same) */
102 c += 4;
103 for (i = 0; i <= len; i++)
104 *(c++) = *(pszMessage++); /* the string itself */
105 } else {
106 ERR("Unhandled string type: %#x\n", *pFormat);
107 /* FIXME: raise an exception. */
108 return NULL;
111 /* success */
112 pStubMsg->fBufferValid = 1;
113 return NULL; /* is this always right? */
116 /***********************************************************************
117 * NdrConformantStringBufferSize [RPCRT4.@]
119 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat)
121 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
123 assert(pFormat);
124 if (*pFormat == RPC_FC_C_CSTRING) {
125 /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 1 octet for '\0' */
126 pStubMsg->BufferLength = strlen(pMemory) + 13 + BUFFER_PARANOIA;
127 } else {
128 ERR("Unhandled string type: %#x\n", *pFormat);
129 /* FIXME: raise an exception */
133 /************************************************************************
134 * NdrConformantStringMemorySize [RPCRT4.@]
136 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
138 unsigned long rslt = 0;
140 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
142 assert(pStubMsg && pFormat);
144 if (*pFormat == RPC_FC_C_CSTRING) {
145 rslt = LITTLE_ENDIAN_32_READ(pStubMsg->Buffer); /* maxlen */
146 } else {
147 ERR("Unhandled string type: %#x\n", *pFormat);
148 /* FIXME: raise an exception */
151 TRACE(" --> %lu\n", rslt);
152 return rslt;
155 /************************************************************************
156 * NdrConformantStringUnmarshall [RPCRT4.@]
158 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory,
159 PFORMAT_STRING pFormat, unsigned char fMustAlloc )
161 unsigned long len, ofs;
163 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
164 pStubMsg, *ppMemory, pFormat, fMustAlloc);
166 assert(pFormat && ppMemory && pStubMsg);
168 len = NdrConformantStringMemorySize(pStubMsg, pFormat);
170 /* now the actual length (in bytes) that we need to store
171 the unmarshalled string is in len, including terminating '\0' */
173 if ( fMustAlloc || (!(*ppMemory)) || (pStubMsg->Memory != *ppMemory) ||
174 (pStubMsg->MemorySize < (len+BUFFER_PARANOIA)) ) {
175 /* crap, looks like we need to do something about the Memory. I don't
176 understand, it doesn't look like Microsoft is doing this the same
177 way... but then how do they do it? AFAICS the Memory is never deallocated by
178 the stub code so where does it go?... anyhow, I guess we'll just do it
179 our own way for now... */
180 pStubMsg->MemorySize = len + BUFFER_PARANOIA;
181 pStubMsg->Memory = *ppMemory;
182 /* FIXME: pfnAllocate? or does that not apply to these "Memory" parts? */
183 *ppMemory = pStubMsg->Memory = HeapReAlloc(GetProcessHeap(), 0, pStubMsg->Memory, pStubMsg->MemorySize);
186 if (!(pStubMsg->Memory)) {
187 ERR("Memory Allocation Failure\n");
188 /* FIXME: raise an exception */
189 return NULL;
192 /* OK, we've got our ram. now do the real unmarshalling */
193 if (*pFormat == RPC_FC_C_CSTRING) {
194 char *c = *ppMemory;
196 pStubMsg->Buffer += 4;
197 ofs = LITTLE_ENDIAN_32_READ(pStubMsg->Buffer);
198 pStubMsg->Buffer += 4;
199 len = LITTLE_ENDIAN_32_READ(pStubMsg->Buffer);
200 pStubMsg->Buffer += 4;
202 pStubMsg->Buffer += ofs;
204 while ((*c++ = *(pStubMsg->Buffer++)) != '\0')
206 } else {
207 ERR("Unhandled string type: %#x\n", *pFormat);
208 /* FIXME: raise an exception */
211 return NULL; /* FIXME: is this always right? */
214 /***********************************************************************
215 * NdrConvert [RPCRT4.@]
217 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
219 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
220 /* FIXME: since this stub doesn't do any converting, the proper behavior
221 is to raise an exception */
224 /***********************************************************************
225 * NdrConvert2 [RPCRT4.@]
227 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
229 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n", pStubMsg, pFormat, NumberParams);
230 /* FIXME: since this stub doesn't do any converting, the proper behavior
231 is to raise an exception */