ok() does not support '%S'. Store the Ansi version, convert to Unicode
[wine] / dlls / oleaut32 / oleaut.c
1 /*
2  *      OLEAUT32
3  *
4  * Copyright 1999, 2000 Marcus Meissner
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 <string.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28
29 #include "ole2.h"
30 #include "olectl.h"
31 #include "oleauto.h"
32 #include "wine/obj_olefont.h"
33
34 #include "tmarshal.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39
40 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
41 extern const GUID CLSID_PSOAInterface;
42
43 /******************************************************************************
44  *             SysStringLen  [OLEAUT32.7]
45  *
46  * The Windows documentation states that the length returned by this function
47  * is not necessarely the same as the length returned by the _lstrlenW method.
48  * It is the same number that was passed in as the "len" parameter if the
49  * string was allocated with a SysAllocStringLen method call.
50  */
51 int WINAPI SysStringLen(BSTR str)
52 {
53     DWORD* bufferPointer;
54
55      if (!str) return 0;
56     /*
57      * The length of the string (in bytes) is contained in a DWORD placed
58      * just before the BSTR pointer
59      */
60     bufferPointer = (DWORD*)str;
61
62     bufferPointer--;
63
64     return (int)(*bufferPointer/sizeof(WCHAR));
65 }
66
67 /******************************************************************************
68  *             SysStringByteLen  [OLEAUT32.149]
69  *
70  * The Windows documentation states that the length returned by this function
71  * is not necessarely the same as the length returned by the _lstrlenW method.
72  * It is the same number that was passed in as the "len" parameter if the
73  * string was allocated with a SysAllocStringLen method call.
74  */
75 int WINAPI SysStringByteLen(BSTR str)
76 {
77     DWORD* bufferPointer;
78
79      if (!str) return 0;
80     /*
81      * The length of the string (in bytes) is contained in a DWORD placed
82      * just before the BSTR pointer
83      */
84     bufferPointer = (DWORD*)str;
85
86     bufferPointer--;
87
88     return (int)(*bufferPointer);
89 }
90
91 /******************************************************************************
92  *              SysAllocString  [OLEAUT32.2]
93  *
94  * MSDN (October 2001) states that this returns a NULL value if the argument
95  * is a zero-length string.  This does not appear to be true; certainly it
96  * returns a value under Win98 (Oleaut32.dll Ver 2.40.4515.0)
97  */
98 BSTR WINAPI SysAllocString(LPCOLESTR in)
99 {
100     if (!in) return 0;
101
102     /* Delegate this to the SysAllocStringLen32 method. */
103     return SysAllocStringLen(in, lstrlenW(in));
104 }
105
106 /******************************************************************************
107  *              SysFreeString   [OLEAUT32.6]
108  */
109 void WINAPI SysFreeString(BSTR in)
110 {
111     DWORD* bufferPointer;
112
113     /* NULL is a valid parameter */
114     if(!in) return;
115
116     /*
117      * We have to be careful when we free a BSTR pointer, it points to
118      * the beginning of the string but it skips the byte count contained
119      * before the string.
120      */
121     bufferPointer = (DWORD*)in;
122
123     bufferPointer--;
124
125     /*
126      * Free the memory from its "real" origin.
127      */
128     HeapFree(GetProcessHeap(), 0, bufferPointer);
129 }
130
131 /******************************************************************************
132  *             SysAllocStringLen     [OLEAUT32.4]
133  *
134  * In "Inside OLE, second edition" by Kraig Brockshmidt. In the Automation
135  * section, he describes the DWORD value placed *before* the BSTR data type.
136  * he describes it as a "DWORD count of characters". By experimenting with
137  * a windows application, this count seems to be a DWORD count of bytes in
138  * the string. Meaning that the count is double the number of wide
139  * characters in the string.
140  */
141 BSTR WINAPI SysAllocStringLen(const OLECHAR *in, unsigned int len)
142 {
143     DWORD  bufferSize;
144     DWORD* newBuffer;
145     WCHAR* stringBuffer;
146
147     /*
148      * Find the length of the buffer passed-in in bytes.
149      */
150     bufferSize = len * sizeof (WCHAR);
151
152     /*
153      * Allocate a new buffer to hold the string.
154      * dont't forget to keep an empty spot at the beginning of the
155      * buffer for the character count and an extra character at the
156      * end for the NULL.
157      */
158     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
159                                  0,
160                                  bufferSize + sizeof(WCHAR) + sizeof(DWORD));
161
162     /*
163      * If the memory allocation failed, return a null pointer.
164      */
165     if (newBuffer==0)
166       return 0;
167
168     /*
169      * Copy the length of the string in the placeholder.
170      */
171     *newBuffer = bufferSize;
172
173     /*
174      * Skip the byte count.
175      */
176     newBuffer++;
177
178     /*
179      * Copy the information in the buffer.
180      * Since it is valid to pass a NULL pointer here, we'll initialize the
181      * buffer to nul if it is the case.
182      */
183     if (in != 0)
184       memcpy(newBuffer, in, bufferSize);
185     else
186       memset(newBuffer, 0, bufferSize);
187
188     /*
189      * Make sure that there is a nul character at the end of the
190      * string.
191      */
192     stringBuffer = (WCHAR*)newBuffer;
193     stringBuffer[len] = L'\0';
194
195     return (LPWSTR)stringBuffer;
196 }
197
198 /******************************************************************************
199  *             SysReAllocStringLen   [OLEAUT32.5]
200  */
201 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* in, unsigned int len)
202 {
203     /*
204      * Sanity check
205      */
206     if (old==NULL)
207       return 0;
208
209     /*
210      * Make sure we free the old string.
211      */
212     if (*old!=NULL)
213       SysFreeString(*old);
214
215     /*
216      * Allocate the new string
217      */
218     *old = SysAllocStringLen(in, len);
219
220     return 1;
221 }
222
223 /******************************************************************************
224  *             SysAllocStringByteLen     [OLEAUT32.150]
225  *
226  */
227 BSTR WINAPI SysAllocStringByteLen(LPCSTR in, UINT len)
228 {
229     DWORD* newBuffer;
230     char* stringBuffer;
231
232     /*
233      * Allocate a new buffer to hold the string.
234      * dont't forget to keep an empty spot at the beginning of the
235      * buffer for the character count and an extra character at the
236      * end for the NULL.
237      */
238     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
239                                  0,
240                                  len + sizeof(WCHAR) + sizeof(DWORD));
241
242     /*
243      * If the memory allocation failed, return a null pointer.
244      */
245     if (newBuffer==0)
246       return 0;
247
248     /*
249      * Copy the length of the string in the placeholder.
250      */
251     *newBuffer = len;
252
253     /*
254      * Skip the byte count.
255      */
256     newBuffer++;
257
258     /*
259      * Copy the information in the buffer.
260      * Since it is valid to pass a NULL pointer here, we'll initialize the
261      * buffer to nul if it is the case.
262      */
263     if (in != 0)
264       memcpy(newBuffer, in, len);
265
266     /*
267      * Make sure that there is a nul character at the end of the
268      * string.
269      */
270     stringBuffer = (char *)newBuffer;
271     stringBuffer[len] = 0;
272     stringBuffer[len+1] = 0;
273
274     return (LPWSTR)stringBuffer;
275 }
276
277 /******************************************************************************
278  *              SysReAllocString        [OLEAUT32.3]
279  */
280 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR in)
281 {
282     /*
283      * Sanity check
284      */
285     if (old==NULL)
286       return 0;
287
288     /*
289      * Make sure we free the old string.
290      */
291     if (*old!=NULL)
292       SysFreeString(*old);
293
294     /*
295      * Allocate the new string
296      */
297     *old = SysAllocString(in);
298
299      return 1;
300 }
301
302 static WCHAR    _delimiter[2] = {'!',0}; /* default delimiter apparently */
303 static WCHAR    *pdelimiter = &_delimiter[0];
304
305 /***********************************************************************
306  *              RegisterActiveObject (OLEAUT32.33)
307  */
308 HRESULT WINAPI RegisterActiveObject(
309         LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
310 ) {
311         WCHAR                   guidbuf[80];
312         HRESULT                 ret;
313         LPRUNNINGOBJECTTABLE    runobtable;
314         LPMONIKER               moniker;
315
316         StringFromGUID2(rcid,guidbuf,39);
317         ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
318         if (FAILED(ret))
319                 return ret;
320         ret = GetRunningObjectTable(0,&runobtable);
321         if (FAILED(ret)) {
322                 IMoniker_Release(moniker);
323                 return ret;
324         }
325         ret = IRunningObjectTable_Register(runobtable,dwFlags,punk,moniker,pdwRegister);
326         IRunningObjectTable_Release(runobtable);
327         IMoniker_Release(moniker);
328         return ret;
329 }
330
331 /***********************************************************************
332  *              RevokeActiveObject (OLEAUT32.34)
333  */
334 HRESULT WINAPI RevokeActiveObject(DWORD xregister,LPVOID reserved)
335 {
336         LPRUNNINGOBJECTTABLE    runobtable;
337         HRESULT                 ret;
338
339         ret = GetRunningObjectTable(0,&runobtable);
340         if (FAILED(ret)) return ret;
341         ret = IRunningObjectTable_Revoke(runobtable,xregister);
342         if (SUCCEEDED(ret)) ret = S_OK;
343         IRunningObjectTable_Release(runobtable);
344         return ret;
345 }
346
347 /***********************************************************************
348  *              GetActiveObject (OLEAUT32.35)
349  */
350 HRESULT WINAPI GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
351 {
352         WCHAR                   guidbuf[80];
353         HRESULT                 ret;
354         LPRUNNINGOBJECTTABLE    runobtable;
355         LPMONIKER               moniker;
356
357         StringFromGUID2(rcid,guidbuf,39);
358         ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
359         if (FAILED(ret))
360                 return ret;
361         ret = GetRunningObjectTable(0,&runobtable);
362         if (FAILED(ret)) {
363                 IMoniker_Release(moniker);
364                 return ret;
365         }
366         ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk);
367         IRunningObjectTable_Release(runobtable);
368         IMoniker_Release(moniker);
369         return ret;
370 }
371
372
373 /***********************************************************************
374  *           OaBuildVersion           [OLEAUT32.170]
375  *
376  * known OLEAUT32.DLL versions:
377  * OLE 2.1  NT                          1993-95 10     3023
378  * OLE 2.1                                      10     3027
379  * Win32s 1.1e                                  20     4049
380  * OLE 2.20 W95/NT                      1993-96 20     4112
381  * OLE 2.20 W95/NT                      1993-96 20     4118
382  * OLE 2.20 W95/NT                      1993-96 20     4122
383  * OLE 2.30 W95/NT                      1993-98 30     4265
384  * OLE 2.40 NT??                        1993-98 40     4267
385  * OLE 2.40 W98 SE orig. file           1993-98 40     4275
386  * OLE 2.40 W2K orig. file              1993-XX 40     4514
387  *
388  * I just decided to use version 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
389  * and 2.40 for all newer OSs. The build number is maximum, i.e. 0xffff.
390  */
391 UINT WINAPI OaBuildVersion()
392 {
393     switch(GetVersion() & 0x8000ffff)  /* mask off build number */
394     {
395     case 0x80000a03:  /* WIN31 */
396                 return MAKELONG(0xffff, 20);
397     case 0x00003303:  /* NT351 */
398                 return MAKELONG(0xffff, 30);
399     case 0x80000004:  /* WIN95; I'd like to use the "standard" w95 minor
400                          version here (30), but as we still use w95
401                          as default winver (which is good IMHO), I better
402                          play safe and use the latest value for w95 for now.
403                          Change this as soon as default winver gets changed
404                          to something more recent */
405     case 0x80000a04:  /* WIN98 */
406     case 0x00000004:  /* NT40 */
407     case 0x00000005:  /* W2K */
408                 return MAKELONG(0xffff, 40);
409     default:
410                 ERR("Version value not known yet. Please investigate it !\n");
411                 return 0x0;
412     }
413 }
414
415 /******************************************************************************
416  *              OleTranslateColor       [OLEAUT32.421]
417  *
418  * Converts an OLE_COLOR to a COLORREF.
419  * See the documentation for conversion rules.
420  * pColorRef can be NULL. In that case the user only wants to test the
421  * conversion.
422  */
423 HRESULT WINAPI OleTranslateColor(
424   OLE_COLOR clr,
425   HPALETTE  hpal,
426   COLORREF* pColorRef)
427 {
428   COLORREF colorref;
429   BYTE b = HIBYTE(HIWORD(clr));
430
431   TRACE("(%08lx, %p, %p):stub\n", clr, hpal, pColorRef);
432
433   /*
434    * In case pColorRef is NULL, provide our own to simplify the code.
435    */
436   if (pColorRef == NULL)
437     pColorRef = &colorref;
438
439   switch (b)
440   {
441     case 0x00:
442     {
443       if (hpal != 0)
444         *pColorRef =  PALETTERGB(GetRValue(clr),
445                                  GetGValue(clr),
446                                  GetBValue(clr));
447       else
448         *pColorRef = clr;
449
450       break;
451     }
452
453     case 0x01:
454     {
455       if (hpal != 0)
456       {
457         PALETTEENTRY pe;
458         /*
459          * Validate the palette index.
460          */
461         if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
462           return E_INVALIDARG;
463       }
464
465       *pColorRef = clr;
466
467       break;
468     }
469
470     case 0x02:
471       *pColorRef = clr;
472       break;
473
474     case 0x80:
475     {
476       int index = LOBYTE(LOWORD(clr));
477
478       /*
479        * Validate GetSysColor index.
480        */
481       if ((index < COLOR_SCROLLBAR) || (index > COLOR_GRADIENTINACTIVECAPTION))
482         return E_INVALIDARG;
483
484       *pColorRef =  GetSysColor(index);
485
486       break;
487     }
488
489     default:
490       return E_INVALIDARG;
491   }
492
493   return S_OK;
494 }
495
496 /***********************************************************************
497  *              DllRegisterServer (OLEAUT32.320)
498  */
499 HRESULT WINAPI OLEAUT32_DllRegisterServer() {
500     FIXME("stub!\n");
501     return S_OK;
502 }
503
504 /***********************************************************************
505  *              DllUnregisterServer (OLEAUT32.321)
506  */
507 HRESULT WINAPI OLEAUT32_DllUnregisterServer() {
508     FIXME("stub!\n");
509     return S_OK;
510 }
511
512 extern void _get_STDFONT_CF(LPVOID);
513 extern void _get_STDPIC_CF(LPVOID);
514
515 /***********************************************************************
516  *              DllGetClassObject (OLEAUT32.1)
517  */
518 HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
519 {
520     *ppv = NULL;
521     if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
522         if (IsEqualGUID(iid,&IID_IClassFactory)) {
523             _get_STDFONT_CF(ppv);
524             IClassFactory_AddRef((IClassFactory*)*ppv);
525             return S_OK;
526         }
527     }
528     if (IsEqualGUID(rclsid,&CLSID_StdPicture)) {
529         if (IsEqualGUID(iid,&IID_IClassFactory)) {
530             _get_STDPIC_CF(ppv);
531             IClassFactory_AddRef((IClassFactory*)*ppv);
532             return S_OK;
533         }
534     }
535     if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
536         if (S_OK==TypeLibFac_DllGetClassObject(rclsid,iid,ppv))
537             return S_OK;
538         /*FALLTHROUGH*/
539     }
540     FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
541     return CLASS_E_CLASSNOTAVAILABLE;
542 }
543
544 /***********************************************************************
545  *              DllCanUnloadNow (OLEAUT32.410)
546  */
547 HRESULT WINAPI OLEAUT32_DllCanUnloadNow() {
548     FIXME("(), stub!\n");
549     return S_FALSE;
550 }