Fixed the Win16/Win32 structure size/alignment differences of
[wine] / dlls / oleaut32 / ole2disp.c
1 /*
2  *      OLE2DISP library
3  *
4  *      Copyright 1995  Martin von Loewis
5  */
6 #include <string.h>
7 #include "windef.h"
8 #include "wingdi.h"
9 #include "winuser.h"
10 #include "winerror.h"
11 #include "olectl.h"
12 #include "oleauto.h"
13 #include "heap.h"
14 #include "ldt.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(ole);
18
19 /* This implementation of the BSTR API is 16-bit only. It
20    represents BSTR as a 16:16 far pointer, and the strings
21    as ISO-8859 */
22
23 /******************************************************************************
24  *              BSTR_AllocBytes [Internal]
25  */
26 static BSTR16 BSTR_AllocBytes(int n)
27 {
28     void *ptr = SEGPTR_ALLOC(n);
29     return (BSTR16)SEGPTR_GET(ptr);
30 }
31
32 /******************************************************************************
33  * BSTR_Free [INTERNAL]
34  */
35 static void BSTR_Free(BSTR16 in)
36 {
37     SEGPTR_FREE( PTR_SEG_TO_LIN(in) );
38 }
39
40 /******************************************************************************
41  * BSTR_GetAddr [INTERNAL]
42  */
43 static void* BSTR_GetAddr(BSTR16 in)
44 {
45     return in ? PTR_SEG_TO_LIN(in) : 0;
46 }
47
48 /******************************************************************************
49  *              SysAllocString16        [OLE2DISP.2]
50  */
51 BSTR16 WINAPI SysAllocString16(LPCOLESTR16 in)
52 {
53         BSTR16 out;
54     
55         if (!in) return 0;
56     
57         out = BSTR_AllocBytes(strlen(in)+1);
58         if(!out)return 0;
59         strcpy(BSTR_GetAddr(out),in);
60         return out;
61 }
62
63 /******************************************************************************
64  *              SysAllocString  [OLEAUT32.2]
65  */
66 BSTR WINAPI SysAllocString(LPCOLESTR in)
67 {
68     if (!in) return 0;
69     
70     /* Delegate this to the SysAllocStringLen32 method. */
71     return SysAllocStringLen(in, lstrlenW(in));
72 }
73
74 /******************************************************************************
75  *              SysReAllocString16      [OLE2DISP.3]
76  */
77 INT16 WINAPI SysReAllocString16(LPBSTR16 old,LPCOLESTR16 in)
78 {
79         BSTR16 new=SysAllocString16(in);
80         BSTR_Free(*old);
81         *old=new;
82         return 1;
83 }
84
85 /******************************************************************************
86  *              SysReAllocString        [OLEAUT32.3]
87  */
88 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR in)
89 {
90     /*
91      * Sanity check
92      */
93     if (old==NULL) 
94       return 0;
95
96     /*
97      * Make sure we free the old string.
98      */
99     if (*old!=NULL)      
100       SysFreeString(*old);
101
102     /*
103      * Allocate the new string
104      */
105     *old = SysAllocString(in);
106
107      return 1;
108 }
109
110 /******************************************************************************
111  *              SysAllocStringLen16     [OLE2DISP.4]
112  */
113 BSTR16 WINAPI SysAllocStringLen16(const char *in, int len)
114 {
115         BSTR16 out=BSTR_AllocBytes(len+1);
116
117         if (!out)
118                 return 0;
119
120     /*
121      * Copy the information in the buffer.
122      * Since it is valid to pass a NULL pointer here, we'll initialize the
123      * buffer to nul if it is the case.
124      */
125     if (in != 0)
126         strcpy(BSTR_GetAddr(out),in);
127     else
128       memset(BSTR_GetAddr(out), 0, len+1);
129
130         return out;
131 }
132
133 /******************************************************************************
134  *             SysAllocStringLen     [OLEAUT32.4]
135  *
136  * In "Inside OLE, second edition" by Kraig Brockshmidt. In the Automation
137  * section, he describes the DWORD value placed before the BSTR data type.
138  * he describes it as a "DWORD count of characters". By experimenting with
139  * a windows application, this count seems to be a DWORD count of bytes in
140  * the string. Meaning that the count is double the number of wide 
141  * characters in the string.
142  */
143 BSTR WINAPI SysAllocStringLen(const OLECHAR *in, unsigned int len)
144 {
145     DWORD  bufferSize;
146     DWORD* newBuffer;
147     WCHAR* stringBuffer;
148
149     /*
150      * Find the lenth of the buffer passed-in in bytes.
151      */
152     bufferSize = len * sizeof (WCHAR);
153
154     /*
155      * Allocate a new buffer to hold the string.
156      * dont't forget to keep an empty spot at the begining of the
157      * buffer for the character count and an extra character at the
158      * end for the NULL.
159      */
160     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
161                                  0,
162                                  bufferSize + sizeof(WCHAR) + sizeof(DWORD));
163
164     /*
165      * If the memory allocation failed, return a null pointer.
166      */
167     if (newBuffer==0)
168       return 0;
169
170     /*
171      * Copy the length of the string in the placeholder.
172      */
173     *newBuffer = bufferSize;
174
175     /*
176      * Skip the byte count.
177      */
178     newBuffer++;
179
180     /*
181      * Copy the information in the buffer.
182      * Since it is valid to pass a NULL pointer here, we'll initialize the
183      * buffer to nul if it is the case.
184      */
185     if (in != 0)
186       memcpy(newBuffer, in, bufferSize);
187     else
188       memset(newBuffer, 0, bufferSize);
189
190     /*
191      * Make sure that there is a nul character at the end of the
192      * string.
193      */
194     stringBuffer = (WCHAR*)newBuffer;
195     stringBuffer[len] = L'\0';
196
197     return (LPWSTR)stringBuffer;
198 }
199
200 /******************************************************************************
201  *              SysReAllocStringLen16   [OLE2DISP.5]
202  */
203 int WINAPI SysReAllocStringLen16(BSTR16 *old,const char *in,int len)
204 {
205         BSTR16 new=SysAllocStringLen16(in,len);
206         BSTR_Free(*old);
207         *old=new;
208         return 1;
209 }
210
211  
212 /******************************************************************************
213  *             SysReAllocStringLen   [OLEAUT32.5]
214  */
215 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* in, unsigned int len)
216 {
217     /*
218      * Sanity check
219      */
220     if (old==NULL) 
221       return 0;
222
223     /*
224      * Make sure we free the old string.
225      */
226     if (*old!=NULL)      
227       SysFreeString(*old);
228
229     /*
230      * Allocate the new string
231      */
232     *old = SysAllocStringLen(in, len);
233
234     return 1;
235 }
236
237 /******************************************************************************
238  *              SysFreeString16 [OLE2DISP.6]
239  */
240 void WINAPI SysFreeString16(BSTR16 in)
241 {
242         BSTR_Free(in);
243 }
244
245 /******************************************************************************
246  *              SysFreeString   [OLEAUT32.6]
247  */
248 void WINAPI SysFreeString(BSTR in)
249 {
250     DWORD* bufferPointer;
251     
252     /* NULL is a valid parameter */
253     if(!in) return;
254
255     /*
256      * We have to be careful when we free a BSTR pointer, it points to
257      * the beginning of the string but it skips the byte count contained
258      * before the string.
259      */
260     bufferPointer = (DWORD*)in;
261
262     bufferPointer--;
263
264     /*
265      * Free the memory from it's "real" origin.
266      */
267     HeapFree(GetProcessHeap(), 0, bufferPointer);
268 }
269
270 /******************************************************************************
271  *              SysStringLen16  [OLE2DISP.7]
272  */
273 int WINAPI SysStringLen16(BSTR16 str)
274 {
275         return strlen(BSTR_GetAddr(str));
276 }
277
278 /******************************************************************************
279  *             SysStringLen  [OLEAUT32.7]
280  *
281  * The Windows documentation states that the length returned by this function
282  * is not necessarely the same as the length returned by the _lstrlenW method.
283  * It is the same number that was passed in as the "len" parameter if the
284  * string was allocated with a SysAllocStringLen method call.
285  */
286 int WINAPI SysStringLen(BSTR str)
287 {
288     DWORD* bufferPointer;
289
290      if (!str) return 0;
291     /*
292      * The length of the string (in bytes) is contained in a DWORD placed 
293      * just before the BSTR pointer
294      */
295     bufferPointer = (DWORD*)str;
296
297     bufferPointer--;
298
299     return (int)(*bufferPointer/sizeof(WCHAR));
300 }
301
302 /******************************************************************************
303  *             SysStringByteLen  [OLEAUT32.149]
304  *
305  * The Windows documentation states that the length returned by this function
306  * is not necessarely the same as the length returned by the _lstrlenW method.
307  * It is the same number that was passed in as the "len" parameter if the
308  * string was allocated with a SysAllocStringLen method call.
309  */
310 int WINAPI SysStringByteLen(BSTR str)
311 {
312     DWORD* bufferPointer;
313
314      if (!str) return 0;
315     /*
316      * The length of the string (in bytes) is contained in a DWORD placed 
317      * just before the BSTR pointer
318      */
319     bufferPointer = (DWORD*)str;
320
321     bufferPointer--;
322
323     return (int)(*bufferPointer);
324 }
325
326 /******************************************************************************
327  * CreateDispTypeInfo [OLE2DISP.31]
328  */
329 HRESULT WINAPI CreateDispTypeInfo16(
330         INTERFACEDATA *pidata,
331         LCID lcid,
332         ITypeInfo **pptinfo
333 ) {
334         FIXME("(%p,%ld,%p),stub\n",pidata,lcid,pptinfo);
335         return 0;
336 }
337
338 /******************************************************************************
339  * RegisterActiveObject [OLE2DISP.35]
340  */
341 HRESULT WINAPI RegisterActiveObject16(
342         IUnknown *punk, REFCLSID rclsid, DWORD dwFlags, unsigned long *pdwRegister
343 ) {
344         FIXME("(%p,%s,0x%08lx,%p):stub\n",punk,debugstr_guid(rclsid),dwFlags,pdwRegister);
345         return 0;
346 }
347
348 /******************************************************************************
349  *              OleTranslateColor       [OLEAUT32.421]
350  *
351  * Converts an OLE_COLOR to a COLORREF.
352  * See the documentation for conversion rules.
353  * pColorRef can be NULL. In that case the user only wants to test the 
354  * conversion.
355  */
356 HRESULT WINAPI OleTranslateColor(
357   OLE_COLOR clr,
358   HPALETTE  hpal,
359   COLORREF* pColorRef)
360 {
361   COLORREF colorref;
362   BYTE b = HIBYTE(HIWORD(clr));
363
364   TRACE("(%08lx, %d, %p):stub\n", clr, hpal, pColorRef);
365
366   /*
367    * In case pColorRef is NULL, provide our own to simplify the code.
368    */
369   if (pColorRef == NULL)
370     pColorRef = &colorref;
371
372   switch (b)
373   {
374     case 0x00:
375     {
376       if (hpal != 0)
377         *pColorRef =  PALETTERGB(GetRValue(clr),
378                                  GetGValue(clr),
379                                  GetBValue(clr));
380       else
381         *pColorRef = clr;
382
383       break;
384     }
385
386     case 0x01:
387     {
388       if (hpal != 0)
389       {
390         PALETTEENTRY pe;
391         /*
392          * Validate the palette index.
393          */
394         if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
395           return E_INVALIDARG;
396       }
397
398       *pColorRef = clr;
399
400       break;
401     }
402
403     case 0x02:
404       *pColorRef = clr;
405       break;
406
407     case 0x80:
408     {
409       int index = LOBYTE(LOWORD(clr));
410
411       /*
412        * Validate GetSysColor index.
413        */
414       if ((index < COLOR_SCROLLBAR) || (index > COLOR_GRADIENTINACTIVECAPTION))
415         return E_INVALIDARG;
416
417       *pColorRef =  GetSysColor(index);
418
419       break;
420     }
421
422     default:
423       return E_INVALIDARG;
424   }
425
426   return S_OK;
427 }
428
429 /******************************************************************************
430  *             SysAllocStringByteLen     [OLEAUT32.150]
431  *
432  */
433 BSTR WINAPI SysAllocStringByteLen(char *in, int len)
434 {
435     DWORD* newBuffer;
436     char* stringBuffer;
437
438     /*
439      * Allocate a new buffer to hold the string.
440      * dont't forget to keep an empty spot at the begining of the
441      * buffer for the character count and an extra character at the
442      * end for the NULL.
443      */
444     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
445                                  0,
446                                  len + sizeof(WCHAR) + sizeof(DWORD));
447
448     /*
449      * If the memory allocation failed, return a null pointer.
450      */
451     if (newBuffer==0)
452       return 0;
453
454     /*
455      * Copy the length of the string in the placeholder.
456      */
457     *newBuffer = len;
458
459     /*
460      * Skip the byte count.
461      */
462     newBuffer++;
463
464     /*
465      * Copy the information in the buffer.
466      * Since it is valid to pass a NULL pointer here, we'll initialize the
467      * buffer to nul if it is the case.
468      */
469     if (in != 0)
470       memcpy(newBuffer, in, len);
471
472     /*
473      * Make sure that there is a nul character at the end of the
474      * string.
475      */
476     stringBuffer = (char *)newBuffer;
477     stringBuffer[len] = 0;
478     stringBuffer[len+1] = 0;
479
480     return (LPWSTR)stringBuffer;
481 }
482
483