Fixed a race condition on RPC worker thread creation, and a typo.
[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     if (*old!=NULL) {
210       DWORD newbytelen = len*sizeof(WCHAR);
211       DWORD *ptr = HeapReAlloc(GetProcessHeap(),0,((DWORD*)*old)-1,newbytelen+sizeof(WCHAR)+sizeof(DWORD));
212       *old = (BSTR)(ptr+1);
213       *ptr = newbytelen;
214       if (in) {
215         memcpy(*old, in, newbytelen);
216         (*old)[len] = 0;
217       } else {
218         /* Subtle hidden feature: The old string data is still there
219          * when 'in' is NULL! 
220          * Some Microsoft program needs it.
221          */
222       }
223     } else {
224       /*
225        * Allocate the new string
226        */
227       *old = SysAllocStringLen(in, len);
228     }
229
230     return 1;
231 }
232
233 /******************************************************************************
234  *             SysAllocStringByteLen     [OLEAUT32.150]
235  *
236  */
237 BSTR WINAPI SysAllocStringByteLen(LPCSTR in, UINT len)
238 {
239     DWORD* newBuffer;
240     char* stringBuffer;
241
242     /*
243      * Allocate a new buffer to hold the string.
244      * dont't forget to keep an empty spot at the beginning of the
245      * buffer for the character count and an extra character at the
246      * end for the NULL.
247      */
248     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
249                                  0,
250                                  len + sizeof(WCHAR) + sizeof(DWORD));
251
252     /*
253      * If the memory allocation failed, return a null pointer.
254      */
255     if (newBuffer==0)
256       return 0;
257
258     /*
259      * Copy the length of the string in the placeholder.
260      */
261     *newBuffer = len;
262
263     /*
264      * Skip the byte count.
265      */
266     newBuffer++;
267
268     /*
269      * Copy the information in the buffer.
270      * Since it is valid to pass a NULL pointer here, we'll initialize the
271      * buffer to nul if it is the case.
272      */
273     if (in != 0)
274       memcpy(newBuffer, in, len);
275
276     /*
277      * Make sure that there is a nul character at the end of the
278      * string.
279      */
280     stringBuffer = (char *)newBuffer;
281     stringBuffer[len] = 0;
282     stringBuffer[len+1] = 0;
283
284     return (LPWSTR)stringBuffer;
285 }
286
287 /******************************************************************************
288  *              SysReAllocString        [OLEAUT32.3]
289  */
290 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR in)
291 {
292     /*
293      * Sanity check
294      */
295     if (old==NULL)
296       return 0;
297
298     /*
299      * Make sure we free the old string.
300      */
301     if (*old!=NULL)
302       SysFreeString(*old);
303
304     /*
305      * Allocate the new string
306      */
307     *old = SysAllocString(in);
308
309      return 1;
310 }
311
312 static WCHAR    _delimiter[2] = {'!',0}; /* default delimiter apparently */
313 static WCHAR    *pdelimiter = &_delimiter[0];
314
315 /***********************************************************************
316  *              RegisterActiveObject (OLEAUT32.33)
317  */
318 HRESULT WINAPI RegisterActiveObject(
319         LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
320 ) {
321         WCHAR                   guidbuf[80];
322         HRESULT                 ret;
323         LPRUNNINGOBJECTTABLE    runobtable;
324         LPMONIKER               moniker;
325
326         StringFromGUID2(rcid,guidbuf,39);
327         ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
328         if (FAILED(ret))
329                 return ret;
330         ret = GetRunningObjectTable(0,&runobtable);
331         if (FAILED(ret)) {
332                 IMoniker_Release(moniker);
333                 return ret;
334         }
335         ret = IRunningObjectTable_Register(runobtable,dwFlags,punk,moniker,pdwRegister);
336         IRunningObjectTable_Release(runobtable);
337         IMoniker_Release(moniker);
338         return ret;
339 }
340
341 /***********************************************************************
342  *              RevokeActiveObject (OLEAUT32.34)
343  */
344 HRESULT WINAPI RevokeActiveObject(DWORD xregister,LPVOID reserved)
345 {
346         LPRUNNINGOBJECTTABLE    runobtable;
347         HRESULT                 ret;
348
349         ret = GetRunningObjectTable(0,&runobtable);
350         if (FAILED(ret)) return ret;
351         ret = IRunningObjectTable_Revoke(runobtable,xregister);
352         if (SUCCEEDED(ret)) ret = S_OK;
353         IRunningObjectTable_Release(runobtable);
354         return ret;
355 }
356
357 /***********************************************************************
358  *              GetActiveObject (OLEAUT32.35)
359  */
360 HRESULT WINAPI GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
361 {
362         WCHAR                   guidbuf[80];
363         HRESULT                 ret;
364         LPRUNNINGOBJECTTABLE    runobtable;
365         LPMONIKER               moniker;
366
367         StringFromGUID2(rcid,guidbuf,39);
368         ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
369         if (FAILED(ret))
370                 return ret;
371         ret = GetRunningObjectTable(0,&runobtable);
372         if (FAILED(ret)) {
373                 IMoniker_Release(moniker);
374                 return ret;
375         }
376         ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk);
377         IRunningObjectTable_Release(runobtable);
378         IMoniker_Release(moniker);
379         return ret;
380 }
381
382
383 /***********************************************************************
384  *           OaBuildVersion           [OLEAUT32.170]
385  *
386  * known OLEAUT32.DLL versions:
387  * OLE 2.1  NT                          1993-95 10     3023
388  * OLE 2.1                                      10     3027
389  * Win32s 1.1e                                  20     4049
390  * OLE 2.20 W95/NT                      1993-96 20     4112
391  * OLE 2.20 W95/NT                      1993-96 20     4118
392  * OLE 2.20 W95/NT                      1993-96 20     4122
393  * OLE 2.30 W95/NT                      1993-98 30     4265
394  * OLE 2.40 NT??                        1993-98 40     4267
395  * OLE 2.40 W98 SE orig. file           1993-98 40     4275
396  * OLE 2.40 W2K orig. file              1993-XX 40     4514
397  *
398  * I just decided to use version 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
399  * and 2.40 for all newer OSs. The build number is maximum, i.e. 0xffff.
400  */
401 UINT WINAPI OaBuildVersion()
402 {
403     switch(GetVersion() & 0x8000ffff)  /* mask off build number */
404     {
405     case 0x80000a03:  /* WIN31 */
406                 return MAKELONG(0xffff, 20);
407     case 0x00003303:  /* NT351 */
408                 return MAKELONG(0xffff, 30);
409     case 0x80000004:  /* WIN95; I'd like to use the "standard" w95 minor
410                          version here (30), but as we still use w95
411                          as default winver (which is good IMHO), I better
412                          play safe and use the latest value for w95 for now.
413                          Change this as soon as default winver gets changed
414                          to something more recent */
415     case 0x80000a04:  /* WIN98 */
416     case 0x00000004:  /* NT40 */
417     case 0x00000005:  /* W2K */
418                 return MAKELONG(0xffff, 40);
419     default:
420                 ERR("Version value not known yet. Please investigate it !\n");
421                 return 0x0;
422     }
423 }
424
425 /******************************************************************************
426  *              OleTranslateColor       [OLEAUT32.421]
427  *
428  * Converts an OLE_COLOR to a COLORREF.
429  * See the documentation for conversion rules.
430  * pColorRef can be NULL. In that case the user only wants to test the
431  * conversion.
432  */
433 HRESULT WINAPI OleTranslateColor(
434   OLE_COLOR clr,
435   HPALETTE  hpal,
436   COLORREF* pColorRef)
437 {
438   COLORREF colorref;
439   BYTE b = HIBYTE(HIWORD(clr));
440
441   TRACE("(%08lx, %p, %p):stub\n", clr, hpal, pColorRef);
442
443   /*
444    * In case pColorRef is NULL, provide our own to simplify the code.
445    */
446   if (pColorRef == NULL)
447     pColorRef = &colorref;
448
449   switch (b)
450   {
451     case 0x00:
452     {
453       if (hpal != 0)
454         *pColorRef =  PALETTERGB(GetRValue(clr),
455                                  GetGValue(clr),
456                                  GetBValue(clr));
457       else
458         *pColorRef = clr;
459
460       break;
461     }
462
463     case 0x01:
464     {
465       if (hpal != 0)
466       {
467         PALETTEENTRY pe;
468         /*
469          * Validate the palette index.
470          */
471         if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
472           return E_INVALIDARG;
473       }
474
475       *pColorRef = clr;
476
477       break;
478     }
479
480     case 0x02:
481       *pColorRef = clr;
482       break;
483
484     case 0x80:
485     {
486       int index = LOBYTE(LOWORD(clr));
487
488       /*
489        * Validate GetSysColor index.
490        */
491       if ((index < COLOR_SCROLLBAR) || (index > COLOR_GRADIENTINACTIVECAPTION))
492         return E_INVALIDARG;
493
494       *pColorRef =  GetSysColor(index);
495
496       break;
497     }
498
499     default:
500       return E_INVALIDARG;
501   }
502
503   return S_OK;
504 }
505
506 /***********************************************************************
507  *              DllRegisterServer (OLEAUT32.320)
508  */
509 HRESULT WINAPI OLEAUT32_DllRegisterServer() {
510     FIXME("stub!\n");
511     return S_OK;
512 }
513
514 /***********************************************************************
515  *              DllUnregisterServer (OLEAUT32.321)
516  */
517 HRESULT WINAPI OLEAUT32_DllUnregisterServer() {
518     FIXME("stub!\n");
519     return S_OK;
520 }
521
522 extern void _get_STDFONT_CF(LPVOID);
523 extern void _get_STDPIC_CF(LPVOID);
524
525 /***********************************************************************
526  *              DllGetClassObject (OLEAUT32.1)
527  */
528 HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
529 {
530     *ppv = NULL;
531     if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
532         if (IsEqualGUID(iid,&IID_IClassFactory)) {
533             _get_STDFONT_CF(ppv);
534             IClassFactory_AddRef((IClassFactory*)*ppv);
535             return S_OK;
536         }
537     }
538     if (IsEqualGUID(rclsid,&CLSID_StdPicture)) {
539         if (IsEqualGUID(iid,&IID_IClassFactory)) {
540             _get_STDPIC_CF(ppv);
541             IClassFactory_AddRef((IClassFactory*)*ppv);
542             return S_OK;
543         }
544     }
545     if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
546         if (S_OK==TypeLibFac_DllGetClassObject(rclsid,iid,ppv))
547             return S_OK;
548         /*FALLTHROUGH*/
549     }
550     FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
551     return CLASS_E_CLASSNOTAVAILABLE;
552 }
553
554 /***********************************************************************
555  *              DllCanUnloadNow (OLEAUT32.410)
556  */
557 HRESULT WINAPI OLEAUT32_DllCanUnloadNow() {
558     FIXME("(), stub!\n");
559     return S_FALSE;
560 }