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