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