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