Added a first-cut version of MapVirtualKeyExW() that has the same
[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 "ldt.h"
17 #include "debugtools.h"
18
19 DEFAULT_DEBUG_CHANNEL(ole);
20
21 /* This implementation of the BSTR API is 16-bit only. It
22    represents BSTR as a 16:16 far pointer, and the strings
23    as ISO-8859 */
24
25 /******************************************************************************
26  *              BSTR_AllocBytes [Internal]
27  */
28 static BSTR16 BSTR_AllocBytes(int n)
29 {
30     void *ptr = SEGPTR_ALLOC(n);
31     return (BSTR16)SEGPTR_GET(ptr);
32 }
33
34 /******************************************************************************
35  * BSTR_Free [INTERNAL]
36  */
37 static void BSTR_Free(BSTR16 in)
38 {
39     SEGPTR_FREE( PTR_SEG_TO_LIN(in) );
40 }
41
42 /******************************************************************************
43  * BSTR_GetAddr [INTERNAL]
44  */
45 static void* BSTR_GetAddr(BSTR16 in)
46 {
47     return in ? PTR_SEG_TO_LIN(in) : 0;
48 }
49
50 /******************************************************************************
51  *              SysAllocString16        [OLE2DISP.2]
52  */
53 BSTR16 WINAPI SysAllocString16(LPCOLESTR16 in)
54 {
55         BSTR16 out;
56     
57         if (!in) return 0;
58     
59         out = BSTR_AllocBytes(strlen(in)+1);
60         if(!out)return 0;
61         strcpy(BSTR_GetAddr(out),in);
62         return out;
63 }
64
65 /******************************************************************************
66  *              SysAllocString  [OLEAUT32.2]
67  */
68 BSTR WINAPI SysAllocString(LPCOLESTR in)
69 {
70     if (!in) return 0;
71     
72     /* Delegate this to the SysAllocStringLen32 method. */
73     return SysAllocStringLen(in, lstrlenW(in));
74 }
75
76 /******************************************************************************
77  *              SysReAllocString16      [OLE2DISP.3]
78  */
79 INT16 WINAPI SysReAllocString16(LPBSTR16 old,LPCOLESTR16 in)
80 {
81         BSTR16 new=SysAllocString16(in);
82         BSTR_Free(*old);
83         *old=new;
84         return 1;
85 }
86
87 /******************************************************************************
88  *              SysReAllocString        [OLEAUT32.3]
89  */
90 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR in)
91 {
92     /*
93      * Sanity check
94      */
95     if (old==NULL) 
96       return 0;
97
98     /*
99      * Make sure we free the old string.
100      */
101     if (*old!=NULL)      
102       SysFreeString(*old);
103
104     /*
105      * Allocate the new string
106      */
107     *old = SysAllocString(in);
108
109      return 1;
110 }
111
112 /******************************************************************************
113  *              SysAllocStringLen16     [OLE2DISP.4]
114  */
115 BSTR16 WINAPI SysAllocStringLen16(const char *in, int len)
116 {
117         BSTR16 out=BSTR_AllocBytes(len+1);
118
119         if (!out)
120                 return 0;
121
122     /*
123      * Copy the information in the buffer.
124      * Since it is valid to pass a NULL pointer here, we'll initialize the
125      * buffer to nul if it is the case.
126      */
127     if (in != 0)
128         strcpy(BSTR_GetAddr(out),in);
129     else
130       memset(BSTR_GetAddr(out), 0, len+1);
131
132         return out;
133 }
134
135 /******************************************************************************
136  *             SysAllocStringLen     [OLEAUT32.4]
137  *
138  * In "Inside OLE, second edition" by Kraig Brockshmidt. In the Automation
139  * section, he describes the DWORD value placed before the BSTR data type.
140  * he describes it as a "DWORD count of characters". By experimenting with
141  * a windows application, this count seems to be a DWORD count of bytes in
142  * the string. Meaning that the count is double the number of wide 
143  * characters in the string.
144  */
145 BSTR WINAPI SysAllocStringLen(const OLECHAR *in, unsigned int len)
146 {
147     DWORD  bufferSize;
148     DWORD* newBuffer;
149     WCHAR* stringBuffer;
150
151     /*
152      * Find the lenth of the buffer passed-in in bytes.
153      */
154     bufferSize = len * sizeof (WCHAR);
155
156     /*
157      * Allocate a new buffer to hold the string.
158      * dont't forget to keep an empty spot at the begining of the
159      * buffer for the character count and an extra character at the
160      * end for the NULL.
161      */
162     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
163                                  0,
164                                  bufferSize + sizeof(WCHAR) + sizeof(DWORD));
165
166     /*
167      * If the memory allocation failed, return a null pointer.
168      */
169     if (newBuffer==0)
170       return 0;
171
172     /*
173      * Copy the length of the string in the placeholder.
174      */
175     *newBuffer = bufferSize;
176
177     /*
178      * Skip the byte count.
179      */
180     newBuffer++;
181
182     /*
183      * Copy the information in the buffer.
184      * Since it is valid to pass a NULL pointer here, we'll initialize the
185      * buffer to nul if it is the case.
186      */
187     if (in != 0)
188       memcpy(newBuffer, in, bufferSize);
189     else
190       memset(newBuffer, 0, bufferSize);
191
192     /*
193      * Make sure that there is a nul character at the end of the
194      * string.
195      */
196     stringBuffer = (WCHAR*)newBuffer;
197     stringBuffer[len] = L'\0';
198
199     return (LPWSTR)stringBuffer;
200 }
201
202 /******************************************************************************
203  *              SysReAllocStringLen16   [OLE2DISP.5]
204  */
205 int WINAPI SysReAllocStringLen16(BSTR16 *old,const char *in,int len)
206 {
207         BSTR16 new=SysAllocStringLen16(in,len);
208         BSTR_Free(*old);
209         *old=new;
210         return 1;
211 }
212
213  
214 /******************************************************************************
215  *             SysReAllocStringLen   [OLEAUT32.5]
216  */
217 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* in, unsigned int len)
218 {
219     /*
220      * Sanity check
221      */
222     if (old==NULL) 
223       return 0;
224
225     /*
226      * Make sure we free the old string.
227      */
228     if (*old!=NULL)      
229       SysFreeString(*old);
230
231     /*
232      * Allocate the new string
233      */
234     *old = SysAllocStringLen(in, len);
235
236     return 1;
237 }
238
239 /******************************************************************************
240  *              SysFreeString16 [OLE2DISP.6]
241  */
242 void WINAPI SysFreeString16(BSTR16 in)
243 {
244         BSTR_Free(in);
245 }
246
247 /******************************************************************************
248  *              SysFreeString   [OLEAUT32.6]
249  */
250 void WINAPI SysFreeString(BSTR in)
251 {
252     DWORD* bufferPointer;
253     
254     /* NULL is a valid parameter */
255     if(!in) return;
256
257     /*
258      * We have to be careful when we free a BSTR pointer, it points to
259      * the beginning of the string but it skips the byte count contained
260      * before the string.
261      */
262     bufferPointer = (DWORD*)in;
263
264     bufferPointer--;
265
266     /*
267      * Free the memory from it's "real" origin.
268      */
269     HeapFree(GetProcessHeap(), 0, bufferPointer);
270 }
271
272 /******************************************************************************
273  *              SysStringLen16  [OLE2DISP.7]
274  */
275 int WINAPI SysStringLen16(BSTR16 str)
276 {
277         return strlen(BSTR_GetAddr(str));
278 }
279
280 /******************************************************************************
281  *             SysStringLen  [OLEAUT32.7]
282  *
283  * The Windows documentation states that the length returned by this function
284  * is not necessarely the same as the length returned by the _lstrlenW method.
285  * It is the same number that was passed in as the "len" parameter if the
286  * string was allocated with a SysAllocStringLen method call.
287  */
288 int WINAPI SysStringLen(BSTR str)
289 {
290     DWORD* bufferPointer;
291
292      if (!str) return 0;
293     /*
294      * The length of the string (in bytes) is contained in a DWORD placed 
295      * just before the BSTR pointer
296      */
297     bufferPointer = (DWORD*)str;
298
299     bufferPointer--;
300
301     return (int)(*bufferPointer/sizeof(WCHAR));
302 }
303
304 /******************************************************************************
305  *             SysStringByteLen  [OLEAUT32.149]
306  *
307  * The Windows documentation states that the length returned by this function
308  * is not necessarely the same as the length returned by the _lstrlenW method.
309  * It is the same number that was passed in as the "len" parameter if the
310  * string was allocated with a SysAllocStringLen method call.
311  */
312 int WINAPI SysStringByteLen(BSTR str)
313 {
314     DWORD* bufferPointer;
315
316      if (!str) return 0;
317     /*
318      * The length of the string (in bytes) is contained in a DWORD placed 
319      * just before the BSTR pointer
320      */
321     bufferPointer = (DWORD*)str;
322
323     bufferPointer--;
324
325     return (int)(*bufferPointer);
326 }
327
328 /******************************************************************************
329  * CreateDispTypeInfo16 [OLE2DISP.31]
330  */
331 HRESULT WINAPI CreateDispTypeInfo16(
332         INTERFACEDATA *pidata,
333         LCID lcid,
334         ITypeInfo **pptinfo)
335 {
336         FIXME("(%p,%ld,%p),stub\n",pidata,lcid,pptinfo);
337         return 0;
338 }
339
340 /******************************************************************************
341  * CreateDispTypeInfo [OLE2DISP.31]
342  */
343 HRESULT WINAPI CreateDispTypeInfo(
344         INTERFACEDATA *pidata,
345         LCID lcid,
346         ITypeInfo **pptinfo)
347 {
348         FIXME("(%p,%ld,%p),stub\n",pidata,lcid,pptinfo);
349         return 0;
350 }
351
352 /******************************************************************************
353  * CreateStdDispatch16 [OLE2DISP.32]
354  */
355 HRESULT WINAPI CreateStdDispatch16(
356         IUnknown* punkOuter,
357         void* pvThis,
358         ITypeInfo* ptinfo,
359         IUnknown** ppunkStdDisp)
360 {
361         FIXME("(%p,%p,%p,%p),stub\n",punkOuter, pvThis, ptinfo,
362                ppunkStdDisp);
363         return 0;
364 }
365
366 /******************************************************************************
367  * CreateStdDispatch [OLE2DISP.32]
368  */
369 HRESULT WINAPI CreateStdDispatch(
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 begining 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