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
21 * - figure out whether we *really* got this right
22 * - check for errors and throw exceptions
37 #include "wine/rpcfc.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44 #define BUFFER_PARANOIA 20
47 #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
48 (*((UINT32 *)(pchar)) = (uint32))
50 #define LITTLE_ENDIAN_UINT32_READ(pchar) \
51 (*((UINT32 *)(pchar)))
53 /* these would work for i386 too, but less efficient */
54 #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
55 (*(pchar) = LOBYTE(LOWORD(uint32)), \
56 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
57 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
58 *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
59 (uint32)) /* allow as r-value */
61 #define LITTLE_ENDIAN_UINT32_READ(pchar) \
63 MAKEWORD(*(pchar), *((pchar)+1)), \
64 MAKEWORD(*((pchar)+2), *((pchar)+3))))
67 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
68 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
69 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
70 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
71 *(pchar) = HIBYTE(HIWORD(uint32)), \
72 (uint32)) /* allow as r-value */
74 #define BIG_ENDIAN_UINT32_READ(pchar) \
76 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
77 MAKEWORD(*((pchar)+1), *(pchar))))
79 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
80 #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
81 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
82 #define NDR_LOCAL_UINT32_READ(pchar) \
83 BIG_ENDIAN_UINT32_READ(pchar)
85 #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
86 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
87 #define NDR_LOCAL_UINT32_READ(pchar) \
88 LITTLE_ENDIAN_UINT32_READ(pchar)
92 * NdrConformantString:
94 * What MS calls a ConformantString is, in DCE terminology,
95 * a Varying-Conformant String.
97 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
98 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
99 * into unmarshalled string)
100 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
102 * data: CHARTYPE[maxlen]
104 * ], where CHARTYPE is the appropriate character type (specified externally)
108 /***********************************************************************
109 * NdrConformantStringMarshall [RPCRT4.@]
111 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
112 unsigned char *pszMessage, PFORMAT_STRING pFormat)
117 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
120 if (*pFormat == RPC_FC_C_CSTRING) {
121 len = strlen(pszMessage);
122 assert( (pStubMsg->BufferLength > (len + 13)) && (pStubMsg->Buffer != NULL) );
123 c = pStubMsg->Buffer;
125 NDR_LOCAL_UINT32_WRITE(c, len + 1); /* max length: strlen + 1 (for '\0') */
126 c += 8; /* offset: 0 */
127 NDR_LOCAL_UINT32_WRITE(c, len + 1); /* actual length: (same) */
129 for (i = 0; i <= len; i++)
130 *(c++) = *(pszMessage++); /* the string itself */
132 ERR("Unhandled string type: %#x\n", *pFormat);
133 /* FIXME: raise an exception. */
138 pStubMsg->fBufferValid = 1;
139 return NULL; /* is this always right? */
142 /***********************************************************************
143 * NdrConformantStringBufferSize [RPCRT4.@]
145 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
146 unsigned char* pMemory, PFORMAT_STRING pFormat)
148 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
151 if (*pFormat == RPC_FC_C_CSTRING) {
152 /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 1 octet for '\0' */
153 pStubMsg->BufferLength = strlen(pMemory) + 13 + BUFFER_PARANOIA;
155 ERR("Unhandled string type: %#x\n", *pFormat);
156 /* FIXME: raise an exception */
160 /************************************************************************
161 * NdrConformantStringMemorySize [RPCRT4.@]
163 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
164 PFORMAT_STRING pFormat )
166 unsigned long rslt = 0;
168 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
170 assert(pStubMsg && pFormat);
172 if (*pFormat == RPC_FC_C_CSTRING) {
173 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
175 ERR("Unhandled string type: %#x\n", *pFormat);
176 /* FIXME: raise an exception */
179 TRACE(" --> %lu\n", rslt);
183 /************************************************************************
184 * NdrConformantStringUnmarshall [RPCRT4.@]
186 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
187 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
189 unsigned long len, ofs;
191 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
192 pStubMsg, *ppMemory, pFormat, fMustAlloc);
194 assert(pFormat && ppMemory && pStubMsg);
196 len = NdrConformantStringMemorySize(pStubMsg, pFormat);
198 /* now the actual length (in bytes) that we need to store
199 the unmarshalled string is in len, including terminating '\0' */
201 if ( fMustAlloc || (!(*ppMemory)) || (pStubMsg->Memory != *ppMemory) ||
202 (pStubMsg->MemorySize < (len+BUFFER_PARANOIA)) ) {
203 /* crap, looks like we need to do something about the Memory. I don't
204 understand, it doesn't look like Microsoft is doing this the same
205 way... but then how do they do it? AFAICS the Memory is never deallocated by
206 the stub code so where does it go?... anyhow, I guess we'll just do it
207 our own way for now... */
208 pStubMsg->MemorySize = len + BUFFER_PARANOIA;
209 pStubMsg->Memory = *ppMemory;
210 /* FIXME: pfnAllocate? or does that not apply to these "Memory" parts? */
211 *ppMemory = pStubMsg->Memory =
212 HeapReAlloc(GetProcessHeap(), 0, pStubMsg->Memory, pStubMsg->MemorySize);
215 if (!(pStubMsg->Memory)) {
216 ERR("Memory Allocation Failure\n");
217 /* FIXME: raise an exception */
221 /* OK, we've got our ram. now do the real unmarshalling */
222 if (*pFormat == RPC_FC_C_CSTRING) {
225 pStubMsg->Buffer += 4;
226 ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
227 pStubMsg->Buffer += 4;
228 len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
229 pStubMsg->Buffer += 4;
231 c += ofs; /* presumably this will always be zero, otherwise the string is no good */
233 while ((*c++ = *(pStubMsg->Buffer++)) != '\0')
236 ERR("Unhandled string type: %#x\n", *pFormat);
237 /* FIXME: raise an exception */
240 return NULL; /* FIXME: is this always right? */
243 /***********************************************************************
244 * NdrConvert [RPCRT4.@]
246 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
248 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
249 /* FIXME: since this stub doesn't do any converting, the proper behavior
250 is to raise an exception */
253 /***********************************************************************
254 * NdrConvert2 [RPCRT4.@]
256 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
258 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
259 pStubMsg, pFormat, NumberParams);
260 /* FIXME: since this stub doesn't do any converting, the proper behavior
261 is to raise an exception */