Always open the device in the default 22050x8x2 format, and let it
[wine] / dlls / rpcrt4 / ndr_marshall.c
1 /*
2  * NDR data marshalling
3  *
4  * Copyright 2002 Greg Turner
5  *
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.
10  *
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.
15  *
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
19  *
20  * TODO:
21  *  - figure out whether we *really* got this right
22  *  - check for errors and throw exceptions
23  */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
33
34 #include "ndr_misc.h"
35 #include "rpcndr.h"
36
37 #include "wine/rpcfc.h"
38 #include "objbase.h"
39
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43
44 #define BUFFER_PARANOIA 20
45
46 #if defined(__i386__)
47   #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
48     (*((UINT32 *)(pchar)) = (uint32))
49
50   #define LITTLE_ENDIAN_UINT32_READ(pchar) \
51     (*((UINT32 *)(pchar)))
52 #else
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 */
60
61   #define LITTLE_ENDIAN_UINT32_READ(pchar) \
62     (MAKELONG( \
63       MAKEWORD(*(pchar), *((pchar)+1)), \
64       MAKEWORD(*((pchar)+2), *((pchar)+3))))
65 #endif
66
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 */
73
74 #define BIG_ENDIAN_UINT32_READ(pchar) \
75   (MAKELONG( \
76     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
77     MAKEWORD(*((pchar)+1), *(pchar))))
78
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)
84 #else
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)
89 #endif
90
91 /*
92  * NdrConformantString:
93  * 
94  * What MS calls a ConformantString is, in DCE terminology,
95  * a Varying-Conformant String.
96  * [
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')
101  *   [ 
102  *     data: CHARTYPE[maxlen]
103  *   ] 
104  * ], where CHARTYPE is the appropriate character type (specified externally)
105  *
106  */
107
108 /***********************************************************************
109  *            NdrConformantStringMarshall [RPCRT4.@]
110  */
111 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
112   unsigned char *pszMessage, PFORMAT_STRING pFormat)
113
114   UINT32 len, i;
115   unsigned char *c;
116
117   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
118   
119   assert(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;
124     memset(c, 0, 12);
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) */
128     c += 4;
129     for (i = 0; i <= len; i++)
130       *(c++) = *(pszMessage++);         /* the string itself */
131   } else {
132     ERR("Unhandled string type: %#x\n", *pFormat); 
133     /* FIXME: raise an exception. */
134     return NULL;
135   }
136   
137   /* success */
138   pStubMsg->fBufferValid = 1;
139   return NULL; /* is this always right? */
140 }
141
142 /***********************************************************************
143  *           NdrConformantStringBufferSize [RPCRT4.@]
144  */
145 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
146   unsigned char* pMemory, PFORMAT_STRING pFormat)
147 {
148   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
149
150   assert(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;
154   } else {
155     ERR("Unhandled string type: %#x\n", *pFormat); 
156     /* FIXME: raise an exception */
157   }
158 }
159
160 /************************************************************************
161  *            NdrConformantStringMemorySize [RPCRT4.@]
162  */
163 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
164   PFORMAT_STRING pFormat )
165 {
166   unsigned long rslt = 0;
167
168   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
169    
170   assert(pStubMsg && pFormat);
171
172   if (*pFormat == RPC_FC_C_CSTRING) {
173     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
174   } else {
175     ERR("Unhandled string type: %#x\n", *pFormat);
176     /* FIXME: raise an exception */
177   }
178
179   TRACE("  --> %lu\n", rslt);
180   return rslt;
181 }
182
183 /************************************************************************
184  *           NdrConformantStringUnmarshall [RPCRT4.@]
185  */
186 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
187   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
188 {
189   unsigned long len, ofs;
190
191   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
192     pStubMsg, *ppMemory, pFormat, fMustAlloc);
193
194   assert(pFormat && ppMemory && pStubMsg);
195
196   len = NdrConformantStringMemorySize(pStubMsg, pFormat);
197
198   /* now the actual length (in bytes) that we need to store
199      the unmarshalled string is in len, including terminating '\0' */
200
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);   
213   } 
214
215   if (!(pStubMsg->Memory)) {
216     ERR("Memory Allocation Failure\n");
217     /* FIXME: raise an exception */
218     return NULL;
219   }
220
221   /* OK, we've got our ram.  now do the real unmarshalling */
222   if (*pFormat == RPC_FC_C_CSTRING) {
223     char *c = *ppMemory;
224
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;
230
231     c += ofs; /* presumably this will always be zero, otherwise the string is no good */
232
233     while ((*c++ = *(pStubMsg->Buffer++)) != '\0') 
234       ;
235   } else {
236     ERR("Unhandled string type: %#x\n", *pFormat);
237     /* FIXME: raise an exception */
238   }
239
240   return NULL; /* FIXME: is this always right? */
241 }
242
243 /***********************************************************************
244  *           NdrConvert [RPCRT4.@]
245  */
246 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
247 {
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 */
251 }
252
253 /***********************************************************************
254  *           NdrConvert2 [RPCRT4.@]
255  */
256 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
257 {
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 */
262 }