xref: /reactos/dll/win32/oleaut32/oleaut.c (revision 8540ab04)
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 
23 #include <stdarg.h>
24 #include <string.h>
25 #include <limits.h>
26 
27 #define COBJMACROS
28 
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winerror.h"
34 
35 #include "ole2.h"
36 #include "olectl.h"
37 #include "oleauto.h"
38 #include "initguid.h"
39 #include "typelib.h"
40 #include "oleaut32_oaidl.h"
41 
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
44 
45 WINE_DEFAULT_DEBUG_CHANNEL(ole);
46 WINE_DECLARE_DEBUG_CHANNEL(heap);
47 
48 /******************************************************************************
49  * BSTR  {OLEAUT32}
50  *
51  * NOTES
52  *  BSTR is a simple typedef for a wide-character string used as the principle
53  *  string type in ole automation. When encapsulated in a Variant type they are
54  *  automatically copied and destroyed as the variant is processed.
55  *
56  *  The low level BSTR API allows manipulation of these strings and is used by
57  *  higher level API calls to manage the strings transparently to the caller.
58  *
59  *  Internally the BSTR type is allocated with space for a DWORD byte count before
60  *  the string data begins. This is undocumented and non-system code should not
61  *  access the count directly. Use SysStringLen() or SysStringByteLen()
62  *  instead. Note that the byte count does not include the terminating NUL.
63  *
64  *  To create a new BSTR, use SysAllocString(), SysAllocStringLen() or
65  *  SysAllocStringByteLen(). To change the size of an existing BSTR, use SysReAllocString()
66  *  or SysReAllocStringLen(). Finally to destroy a string use SysFreeString().
67  *
68  *  BSTR's are cached by Ole Automation by default. To override this behaviour
69  *  either set the environment variable 'OANOCACHE', or call SetOaNoCache().
70  *
71  * SEE ALSO
72  *  'Inside OLE, second edition' by Kraig Brockshmidt.
73  */
74 
75 static BOOL bstr_cache_enabled;
76 
77 static CRITICAL_SECTION cs_bstr_cache;
78 static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg =
79 {
80     0, 0, &cs_bstr_cache,
81     { &cs_bstr_cache_dbg.ProcessLocksList, &cs_bstr_cache_dbg.ProcessLocksList },
82       0, 0, { (DWORD_PTR)(__FILE__ ": bstr_cache") }
83 };
84 static CRITICAL_SECTION cs_bstr_cache = { &cs_bstr_cache_dbg, -1, 0, 0, 0, 0 };
85 
86 typedef struct {
87 #ifdef _WIN64
88     DWORD pad;
89 #endif
90     DWORD size;
91     union {
92         char ptr[1];
93         WCHAR str[1];
94         DWORD dwptr[1];
95     } u;
96 } bstr_t;
97 
98 #define BUCKET_SIZE 16
99 #define BUCKET_BUFFER_SIZE 6
100 
101 typedef struct {
102     unsigned short head;
103     unsigned short cnt;
104     bstr_t *buf[BUCKET_BUFFER_SIZE];
105 } bstr_cache_entry_t;
106 
107 #define ARENA_INUSE_FILLER     0x55
108 #define ARENA_TAIL_FILLER      0xab
109 #define ARENA_FREE_FILLER      0xfeeefeee
110 
111 static bstr_cache_entry_t bstr_cache[0x10000/BUCKET_SIZE];
112 
113 static inline size_t bstr_alloc_size(size_t size)
114 {
115     return (FIELD_OFFSET(bstr_t, u.ptr[size]) + sizeof(WCHAR) + BUCKET_SIZE-1) & ~(BUCKET_SIZE-1);
116 }
117 
118 static inline bstr_t *bstr_from_str(BSTR str)
119 {
120     return CONTAINING_RECORD((void *)str, bstr_t, u.str);
121 }
122 
123 static inline bstr_cache_entry_t *get_cache_entry_from_idx(unsigned cache_idx)
124 {
125     return bstr_cache_enabled && cache_idx < sizeof(bstr_cache)/sizeof(*bstr_cache)
126         ? bstr_cache + cache_idx
127         : NULL;
128 }
129 
130 static inline bstr_cache_entry_t *get_cache_entry(size_t size)
131 {
132     unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)-1])/BUCKET_SIZE;
133     return get_cache_entry_from_idx(cache_idx);
134 }
135 
136 static inline bstr_cache_entry_t *get_cache_entry_from_alloc_size(SIZE_T alloc_size)
137 {
138     unsigned cache_idx;
139     if (alloc_size < BUCKET_SIZE) return NULL;
140     cache_idx = (alloc_size - BUCKET_SIZE) / BUCKET_SIZE;
141     return get_cache_entry_from_idx(cache_idx);
142 }
143 
144 static bstr_t *alloc_bstr(size_t size)
145 {
146     bstr_cache_entry_t *cache_entry = get_cache_entry(size);
147     bstr_t *ret;
148 
149     if(cache_entry) {
150         EnterCriticalSection(&cs_bstr_cache);
151 
152         if(!cache_entry->cnt) {
153             cache_entry = get_cache_entry(size+BUCKET_SIZE);
154             if(cache_entry && !cache_entry->cnt)
155                 cache_entry = NULL;
156         }
157 
158         if(cache_entry) {
159             ret = cache_entry->buf[cache_entry->head++];
160             cache_entry->head %= BUCKET_BUFFER_SIZE;
161             cache_entry->cnt--;
162         }
163 
164         LeaveCriticalSection(&cs_bstr_cache);
165 
166         if(cache_entry) {
167             if(WARN_ON(heap)) {
168                 size_t fill_size = (FIELD_OFFSET(bstr_t, u.ptr[size])+2*sizeof(WCHAR)-1) & ~(sizeof(WCHAR)-1);
169                 memset(ret, ARENA_INUSE_FILLER, fill_size);
170                 memset((char *)ret+fill_size, ARENA_TAIL_FILLER, bstr_alloc_size(size)-fill_size);
171             }
172             ret->size = size;
173             return ret;
174         }
175     }
176 
177     ret = CoTaskMemAlloc(bstr_alloc_size(size));
178     if(ret)
179         ret->size = size;
180     return ret;
181 }
182 
183 /******************************************************************************
184  *             SysStringLen  [OLEAUT32.7]
185  *
186  * Get the allocated length of a BSTR in wide characters.
187  *
188  * PARAMS
189  *  str [I] BSTR to find the length of
190  *
191  * RETURNS
192  *  The allocated length of str, or 0 if str is NULL.
193  *
194  * NOTES
195  *  See BSTR.
196  *  The returned length may be different from the length of the string as
197  *  calculated by lstrlenW(), since it returns the length that was used to
198  *  allocate the string by SysAllocStringLen().
199  */
200 UINT WINAPI SysStringLen(BSTR str)
201 {
202     return str ? bstr_from_str(str)->size/sizeof(WCHAR) : 0;
203 }
204 
205 /******************************************************************************
206  *             SysStringByteLen  [OLEAUT32.149]
207  *
208  * Get the allocated length of a BSTR in bytes.
209  *
210  * PARAMS
211  *  str [I] BSTR to find the length of
212  *
213  * RETURNS
214  *  The allocated length of str, or 0 if str is NULL.
215  *
216  * NOTES
217  *  See SysStringLen(), BSTR().
218  */
219 UINT WINAPI SysStringByteLen(BSTR str)
220 {
221     return str ? bstr_from_str(str)->size : 0;
222 }
223 
224 /******************************************************************************
225  *		SysAllocString	[OLEAUT32.2]
226  *
227  * Create a BSTR from an OLESTR.
228  *
229  * PARAMS
230  *  str [I] Source to create BSTR from
231  *
232  * RETURNS
233  *  Success: A BSTR allocated with SysAllocStringLen().
234  *  Failure: NULL, if oleStr is NULL.
235  *
236  * NOTES
237  *  See BSTR.
238  *  MSDN (October 2001) incorrectly states that NULL is returned if oleStr has
239  *  a length of 0. Native Win32 and this implementation both return a valid
240  *  empty BSTR in this case.
241  */
242 BSTR WINAPI SysAllocString(LPCOLESTR str)
243 {
244     if (!str) return 0;
245 
246     /* Delegate this to the SysAllocStringLen32 method. */
247     return SysAllocStringLen(str, lstrlenW(str));
248 }
249 
250 static inline IMalloc *get_malloc(void)
251 {
252     static IMalloc *malloc;
253 
254     if (!malloc)
255         CoGetMalloc(1, &malloc);
256 
257     return malloc;
258 }
259 
260 /******************************************************************************
261  *		SysFreeString	[OLEAUT32.6]
262  *
263  * Free a BSTR.
264  *
265  * PARAMS
266  *  str [I] BSTR to free.
267  *
268  * RETURNS
269  *  Nothing.
270  *
271  * NOTES
272  *  See BSTR.
273  *  str may be NULL, in which case this function does nothing.
274  */
275 void WINAPI SysFreeString(BSTR str)
276 {
277     bstr_cache_entry_t *cache_entry;
278     bstr_t *bstr;
279     IMalloc *malloc = get_malloc();
280     SIZE_T alloc_size;
281 
282     if(!str)
283         return;
284 
285     bstr = bstr_from_str(str);
286 
287     alloc_size = IMalloc_GetSize(malloc, bstr);
288     if (alloc_size == ~0UL)
289         return;
290 
291     cache_entry = get_cache_entry_from_alloc_size(alloc_size);
292     if(cache_entry) {
293         unsigned i;
294 
295         EnterCriticalSection(&cs_bstr_cache);
296 
297         /* According to tests, freeing a string that's already in cache doesn't corrupt anything.
298          * For that to work we need to search the cache. */
299         for(i=0; i < cache_entry->cnt; i++) {
300             if(cache_entry->buf[(cache_entry->head+i) % BUCKET_BUFFER_SIZE] == bstr) {
301                 WARN_(heap)("String already is in cache!\n");
302                 LeaveCriticalSection(&cs_bstr_cache);
303                 return;
304             }
305         }
306 
307         if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
308             cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr;
309             cache_entry->cnt++;
310 
311             if(WARN_ON(heap)) {
312                 unsigned n = (alloc_size-FIELD_OFFSET(bstr_t, u.ptr))/sizeof(DWORD);
313                 for(i=0; i<n; i++)
314                     bstr->u.dwptr[i] = ARENA_FREE_FILLER;
315             }
316 
317             LeaveCriticalSection(&cs_bstr_cache);
318             return;
319         }
320 
321         LeaveCriticalSection(&cs_bstr_cache);
322     }
323 
324     CoTaskMemFree(bstr);
325 }
326 
327 /******************************************************************************
328  *             SysAllocStringLen     [OLEAUT32.4]
329  *
330  * Create a BSTR from an OLESTR of a given wide character length.
331  *
332  * PARAMS
333  *  str [I] Source to create BSTR from
334  *  len [I] Length of oleStr in wide characters
335  *
336  * RETURNS
337  *  Success: A newly allocated BSTR from SysAllocStringByteLen()
338  *  Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
339  *
340  * NOTES
341  *  See BSTR(), SysAllocStringByteLen().
342  */
343 BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
344 {
345     bstr_t *bstr;
346     DWORD size;
347 
348     /* Detect integer overflow. */
349     if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
350 	return NULL;
351 
352     TRACE("%s\n", debugstr_wn(str, len));
353 
354     size = len*sizeof(WCHAR);
355     bstr = alloc_bstr(size);
356     if(!bstr)
357         return NULL;
358 
359     if(str) {
360         memcpy(bstr->u.str, str, size);
361         bstr->u.str[len] = 0;
362     }else {
363         memset(bstr->u.str, 0, size+sizeof(WCHAR));
364     }
365 
366     return bstr->u.str;
367 }
368 
369 /******************************************************************************
370  *             SysReAllocStringLen   [OLEAUT32.5]
371  *
372  * Change the length of a previously created BSTR.
373  *
374  * PARAMS
375  *  old [O] BSTR to change the length of
376  *  str [I] New source for pbstr
377  *  len [I] Length of oleStr in wide characters
378  *
379  * RETURNS
380  *  Success: 1. The size of pbstr is updated.
381  *  Failure: 0, if len >= 0x80000000 or memory allocation fails.
382  *
383  * NOTES
384  *  See BSTR(), SysAllocStringByteLen().
385  *  *old may be changed by this function.
386  */
387 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
388 {
389     /* Detect integer overflow. */
390     if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
391 	return FALSE;
392 
393     if (*old!=NULL) {
394       DWORD newbytelen = len*sizeof(WCHAR);
395       bstr_t *old_bstr = bstr_from_str(*old);
396       bstr_t *bstr = CoTaskMemRealloc(old_bstr, bstr_alloc_size(newbytelen));
397 
398       if (!bstr) return FALSE;
399 
400       *old = bstr->u.str;
401       bstr->size = newbytelen;
402       /* The old string data is still there when str is NULL */
403       if (str && old_bstr->u.str != str) memmove(bstr->u.str, str, newbytelen);
404       bstr->u.str[len] = 0;
405     } else {
406       *old = SysAllocStringLen(str, len);
407     }
408 
409     return TRUE;
410 }
411 
412 /******************************************************************************
413  *             SysAllocStringByteLen     [OLEAUT32.150]
414  *
415  * Create a BSTR from an OLESTR of a given byte length.
416  *
417  * PARAMS
418  *  str [I] Source to create BSTR from
419  *  len [I] Length of oleStr in bytes
420  *
421  * RETURNS
422  *  Success: A newly allocated BSTR
423  *  Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
424  *
425  * NOTES
426  *  -If len is 0 or oleStr is NULL the resulting string is empty ("").
427  *  -This function always NUL terminates the resulting BSTR.
428  *  -oleStr may be either an LPCSTR or LPCOLESTR, since it is copied
429  *  without checking for a terminating NUL.
430  *  See BSTR.
431  */
432 BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len)
433 {
434     bstr_t *bstr;
435 
436     /* Detect integer overflow. */
437     if (len >= (UINT_MAX-sizeof(WCHAR)-sizeof(DWORD)))
438 	return NULL;
439 
440     bstr = alloc_bstr(len);
441     if(!bstr)
442         return NULL;
443 
444     if(str) {
445         memcpy(bstr->u.ptr, str, len);
446         bstr->u.ptr[len] = 0;
447     }else {
448         memset(bstr->u.ptr, 0, len+1);
449     }
450     bstr->u.str[(len+sizeof(WCHAR)-1)/sizeof(WCHAR)] = 0;
451 
452     return bstr->u.str;
453 }
454 
455 /******************************************************************************
456  *		SysReAllocString	[OLEAUT32.3]
457  *
458  * Change the length of a previously created BSTR.
459  *
460  * PARAMS
461  *  old [I/O] BSTR to change the length of
462  *  str [I]   New source for pbstr
463  *
464  * RETURNS
465  *  Success: 1
466  *  Failure: 0.
467  *
468  * NOTES
469  *  See BSTR(), SysAllocStringStringLen().
470  */
471 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR str)
472 {
473     /*
474      * Sanity check
475      */
476     if (old==NULL)
477       return 0;
478 
479     /*
480      * Make sure we free the old string.
481      */
482     SysFreeString(*old);
483 
484     /*
485      * Allocate the new string
486      */
487     *old = SysAllocString(str);
488 
489      return 1;
490 }
491 
492 /******************************************************************************
493  *		SetOaNoCache (OLEAUT32.327)
494  *
495  * Instruct Ole Automation not to cache BSTR allocations.
496  *
497  * PARAMS
498  *  None.
499  *
500  * RETURNS
501  *  Nothing.
502  *
503  * NOTES
504  *  SetOaNoCache does not release cached strings, so it leaks by design.
505  */
506 void WINAPI SetOaNoCache(void)
507 {
508     TRACE("\n");
509     bstr_cache_enabled = FALSE;
510 }
511 
512 static const WCHAR	_delimiter[] = {'!',0}; /* default delimiter apparently */
513 static const WCHAR	*pdelimiter = &_delimiter[0];
514 
515 /***********************************************************************
516  *		RegisterActiveObject (OLEAUT32.33)
517  *
518  * Registers an object in the global item table.
519  *
520  * PARAMS
521  *  punk        [I] Object to register.
522  *  rcid        [I] CLSID of the object.
523  *  dwFlags     [I] Flags.
524  *  pdwRegister [O] Address to store cookie of object registration in.
525  *
526  * RETURNS
527  *  Success: S_OK.
528  *  Failure: HRESULT code.
529  */
530 HRESULT WINAPI DECLSPEC_HOTPATCH RegisterActiveObject(
531 	LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
532 ) {
533 	WCHAR 			guidbuf[80];
534 	HRESULT			ret;
535 	LPRUNNINGOBJECTTABLE	runobtable;
536 	LPMONIKER		moniker;
537         DWORD                   rot_flags = ROTFLAGS_REGISTRATIONKEEPSALIVE; /* default registration is strong */
538 
539 	StringFromGUID2(rcid,guidbuf,39);
540 	ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
541 	if (FAILED(ret))
542 		return ret;
543 	ret = GetRunningObjectTable(0,&runobtable);
544 	if (FAILED(ret)) {
545 		IMoniker_Release(moniker);
546 		return ret;
547 	}
548         if(dwFlags == ACTIVEOBJECT_WEAK)
549           rot_flags = 0;
550 	ret = IRunningObjectTable_Register(runobtable,rot_flags,punk,moniker,pdwRegister);
551 	IRunningObjectTable_Release(runobtable);
552 	IMoniker_Release(moniker);
553 	return ret;
554 }
555 
556 /***********************************************************************
557  *		RevokeActiveObject (OLEAUT32.34)
558  *
559  * Revokes an object from the global item table.
560  *
561  * PARAMS
562  *  xregister [I] Registration cookie.
563  *  reserved  [I] Reserved. Set to NULL.
564  *
565  * RETURNS
566  *  Success: S_OK.
567  *  Failure: HRESULT code.
568  */
569 HRESULT WINAPI DECLSPEC_HOTPATCH RevokeActiveObject(DWORD xregister,LPVOID reserved)
570 {
571 	LPRUNNINGOBJECTTABLE	runobtable;
572 	HRESULT			ret;
573 
574 	ret = GetRunningObjectTable(0,&runobtable);
575 	if (FAILED(ret)) return ret;
576 	ret = IRunningObjectTable_Revoke(runobtable,xregister);
577 	if (SUCCEEDED(ret)) ret = S_OK;
578 	IRunningObjectTable_Release(runobtable);
579 	return ret;
580 }
581 
582 /***********************************************************************
583  *		GetActiveObject (OLEAUT32.35)
584  *
585  * Gets an object from the global item table.
586  *
587  * PARAMS
588  *  rcid        [I] CLSID of the object.
589  *  preserved   [I] Reserved. Set to NULL.
590  *  ppunk       [O] Address to store object into.
591  *
592  * RETURNS
593  *  Success: S_OK.
594  *  Failure: HRESULT code.
595  */
596 HRESULT WINAPI DECLSPEC_HOTPATCH GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
597 {
598 	WCHAR 			guidbuf[80];
599 	HRESULT			ret;
600 	LPRUNNINGOBJECTTABLE	runobtable;
601 	LPMONIKER		moniker;
602 
603 	StringFromGUID2(rcid,guidbuf,39);
604 	ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker);
605 	if (FAILED(ret))
606 		return ret;
607 	ret = GetRunningObjectTable(0,&runobtable);
608 	if (FAILED(ret)) {
609 		IMoniker_Release(moniker);
610 		return ret;
611 	}
612 	ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk);
613 	IRunningObjectTable_Release(runobtable);
614 	IMoniker_Release(moniker);
615 	return ret;
616 }
617 
618 
619 /***********************************************************************
620  *           OaBuildVersion           [OLEAUT32.170]
621  *
622  * Get the Ole Automation build version.
623  *
624  * PARAMS
625  *  None
626  *
627  * RETURNS
628  *  The build version.
629  *
630  * NOTES
631  *  Known oleaut32.dll versions:
632  *| OLE Ver.  Comments                   Date     Build Ver.
633  *| --------  -------------------------  ----     ---------
634  *| OLE 2.1   NT                         1993-95  10 3023
635  *| OLE 2.1                                       10 3027
636  *| Win32s    Ver 1.1e                            20 4049
637  *| OLE 2.20  W95/NT                     1993-96  20 4112
638  *| OLE 2.20  W95/NT                     1993-96  20 4118
639  *| OLE 2.20  W95/NT                     1993-96  20 4122
640  *| OLE 2.30  W95/NT                     1993-98  30 4265
641  *| OLE 2.40  NT??                       1993-98  40 4267
642  *| OLE 2.40  W98 SE orig. file          1993-98  40 4275
643  *| OLE 2.40  W2K orig. file             1993-XX  40 4514
644  *
645  * Currently the versions returned are 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
646  * and 2.40 for all later versions. The build number is maximum, i.e. 0xffff.
647  */
648 ULONG WINAPI OaBuildVersion(void)
649 {
650     switch(GetVersion() & 0x8000ffff)  /* mask off build number */
651     {
652     case 0x80000a03:  /* WIN31 */
653 		return MAKELONG(0xffff, 20);
654     case 0x00003303:  /* NT351 */
655 		return MAKELONG(0xffff, 30);
656     case 0x80000004:  /* WIN95; I'd like to use the "standard" w95 minor
657 		         version here (30), but as we still use w95
658 		         as default winver (which is good IMHO), I better
659 		         play safe and use the latest value for w95 for now.
660 		         Change this as soon as default winver gets changed
661 		         to something more recent */
662     case 0x80000a04:  /* WIN98 */
663     case 0x00000004:  /* NT40 */
664     case 0x00000005:  /* W2K */
665 		return MAKELONG(0xffff, 40);
666     case 0x00000105:  /* WinXP */
667     case 0x00000006:  /* Vista */
668     case 0x00000106:  /* Win7 */
669 		return MAKELONG(0xffff, 50);
670     default:
671 		FIXME("Version value not known yet. Please investigate it !\n");
672 		return MAKELONG(0xffff, 40);  /* for now return the same value as for w2k */
673     }
674 }
675 
676 /******************************************************************************
677  *		OleTranslateColor	[OLEAUT32.421]
678  *
679  * Convert an OLE_COLOR to a COLORREF.
680  *
681  * PARAMS
682  *  clr       [I] Color to convert
683  *  hpal      [I] Handle to a palette for the conversion
684  *  pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok
685  *
686  * RETURNS
687  *  Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL.
688  *  Failure: E_INVALIDARG, if any argument is invalid.
689  *
690  * FIXME
691  *  Document the conversion rules.
692  */
693 HRESULT WINAPI OleTranslateColor(
694   OLE_COLOR clr,
695   HPALETTE  hpal,
696   COLORREF* pColorRef)
697 {
698   COLORREF colorref;
699   BYTE b = HIBYTE(HIWORD(clr));
700 
701   TRACE("(%08x, %p, %p)\n", clr, hpal, pColorRef);
702 
703   /*
704    * In case pColorRef is NULL, provide our own to simplify the code.
705    */
706   if (pColorRef == NULL)
707     pColorRef = &colorref;
708 
709   switch (b)
710   {
711     case 0x00:
712     {
713       if (hpal != 0)
714         *pColorRef =  PALETTERGB(GetRValue(clr),
715                                  GetGValue(clr),
716                                  GetBValue(clr));
717       else
718         *pColorRef = clr;
719 
720       break;
721     }
722 
723     case 0x01:
724     {
725       if (hpal != 0)
726       {
727         PALETTEENTRY pe;
728         /*
729          * Validate the palette index.
730          */
731         if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
732           return E_INVALIDARG;
733       }
734 
735       *pColorRef = clr;
736 
737       break;
738     }
739 
740     case 0x02:
741       *pColorRef = clr;
742       break;
743 
744     case 0x80:
745     {
746       int index = LOBYTE(LOWORD(clr));
747 
748       /*
749        * Validate GetSysColor index.
750        */
751       if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR))
752         return E_INVALIDARG;
753 
754       *pColorRef =  GetSysColor(index);
755 
756       break;
757     }
758 
759     default:
760       return E_INVALIDARG;
761   }
762 
763   return S_OK;
764 }
765 
766 extern HRESULT WINAPI OLEAUTPS_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN;
767 extern BOOL WINAPI OLEAUTPS_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
768 extern HRESULT WINAPI OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN;
769 extern HRESULT WINAPI OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN;
770 
771 extern void _get_STDFONT_CF(LPVOID *);
772 extern void _get_STDPIC_CF(LPVOID *);
773 
774 static HRESULT WINAPI PSDispatchFacBuf_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv)
775 {
776     if (IsEqualIID(riid, &IID_IUnknown) ||
777         IsEqualIID(riid, &IID_IPSFactoryBuffer))
778     {
779         IPSFactoryBuffer_AddRef(iface);
780         *ppv = iface;
781         return S_OK;
782     }
783     return E_NOINTERFACE;
784 }
785 
786 static ULONG WINAPI PSDispatchFacBuf_AddRef(IPSFactoryBuffer *iface)
787 {
788     return 2;
789 }
790 
791 static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface)
792 {
793     return 1;
794 }
795 
796 static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface, IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv)
797 {
798     IPSFactoryBuffer *pPSFB;
799     HRESULT hr;
800 
801     if (IsEqualIID(riid, &IID_IDispatch))
802         hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB);
803     else
804         hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB);
805 
806     if (FAILED(hr)) return hr;
807 
808     hr = IPSFactoryBuffer_CreateProxy(pPSFB, pUnkOuter, riid, ppProxy, ppv);
809 
810     IPSFactoryBuffer_Release(pPSFB);
811     return hr;
812 }
813 
814 static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface, REFIID riid, IUnknown *pUnkOuter, IRpcStubBuffer **ppStub)
815 {
816     IPSFactoryBuffer *pPSFB;
817     HRESULT hr;
818 
819     if (IsEqualIID(riid, &IID_IDispatch))
820         hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB);
821     else
822         hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB);
823 
824     if (FAILED(hr)) return hr;
825 
826     hr = IPSFactoryBuffer_CreateStub(pPSFB, riid, pUnkOuter, ppStub);
827 
828     IPSFactoryBuffer_Release(pPSFB);
829     return hr;
830 }
831 
832 static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl =
833 {
834     PSDispatchFacBuf_QueryInterface,
835     PSDispatchFacBuf_AddRef,
836     PSDispatchFacBuf_Release,
837     PSDispatchFacBuf_CreateProxy,
838     PSDispatchFacBuf_CreateStub
839 };
840 
841 /* This is the whole PSFactoryBuffer object, just the vtableptr */
842 static const IPSFactoryBufferVtbl *pPSDispatchFacBuf = &PSDispatchFacBuf_Vtbl;
843 
844 /***********************************************************************
845  *		DllGetClassObject (OLEAUT32.@)
846  */
847 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
848 {
849     *ppv = NULL;
850     if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
851 	if (IsEqualGUID(iid,&IID_IClassFactory)) {
852 	    _get_STDFONT_CF(ppv);
853 	    IClassFactory_AddRef((IClassFactory*)*ppv);
854 	    return S_OK;
855 	}
856     }
857     if (IsEqualGUID(rclsid,&CLSID_StdPicture)) {
858 	if (IsEqualGUID(iid,&IID_IClassFactory)) {
859 	    _get_STDPIC_CF(ppv);
860 	    IClassFactory_AddRef((IClassFactory*)*ppv);
861 	    return S_OK;
862 	}
863     }
864     if (IsEqualCLSID(rclsid, &CLSID_PSDispatch) && IsEqualIID(iid, &IID_IPSFactoryBuffer)) {
865         *ppv = &pPSDispatchFacBuf;
866         IPSFactoryBuffer_AddRef((IPSFactoryBuffer *)*ppv);
867         return S_OK;
868     }
869     if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
870 	if (S_OK==TMARSHAL_DllGetClassObject(rclsid,iid,ppv))
871 	    return S_OK;
872 	/*FALLTHROUGH*/
873     }
874     if (IsEqualCLSID(rclsid, &CLSID_PSTypeComp) ||
875         IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) ||
876         IsEqualCLSID(rclsid, &CLSID_PSTypeLib) ||
877         IsEqualCLSID(rclsid, &CLSID_PSDispatch) ||
878         IsEqualCLSID(rclsid, &CLSID_PSEnumVariant))
879         return OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, iid, ppv);
880 
881     return OLEAUTPS_DllGetClassObject(rclsid, iid, ppv);
882 }
883 
884 /***********************************************************************
885  *		DllCanUnloadNow (OLEAUT32.@)
886  *
887  * Determine if this dll can be unloaded from the callers address space.
888  *
889  * PARAMS
890  *  None.
891  *
892  * RETURNS
893  *  Always returns S_FALSE. This dll cannot be unloaded.
894  */
895 HRESULT WINAPI DllCanUnloadNow(void)
896 {
897     return S_FALSE;
898 }
899 
900 /*****************************************************************************
901  *              DllMain         [OLEAUT32.@]
902  */
903 BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
904 {
905     static const WCHAR oanocacheW[] = {'o','a','n','o','c','a','c','h','e',0};
906 
907     if(fdwReason == DLL_PROCESS_ATTACH)
908         bstr_cache_enabled = !GetEnvironmentVariableW(oanocacheW, NULL, 0);
909 
910     return OLEAUTPS_DllMain( hInstDll, fdwReason, lpvReserved );
911 }
912 
913 /***********************************************************************
914  *		DllRegisterServer (OLEAUT32.@)
915  */
916 HRESULT WINAPI DllRegisterServer(void)
917 {
918     return OLEAUTPS_DllRegisterServer();
919 }
920 
921 /***********************************************************************
922  *		DllUnregisterServer (OLEAUT32.@)
923  */
924 HRESULT WINAPI DllUnregisterServer(void)
925 {
926     return OLEAUTPS_DllUnregisterServer();
927 }
928 
929 /***********************************************************************
930  *              OleIconToCursor (OLEAUT32.415)
931  */
932 HCURSOR WINAPI OleIconToCursor( HINSTANCE hinstExe, HICON hIcon)
933 {
934     FIXME("(%p,%p), partially implemented.\n",hinstExe,hIcon);
935     /* FIXME: make an extended conversation from HICON to HCURSOR */
936     return CopyCursor(hIcon);
937 }
938 
939 /***********************************************************************
940  *              GetAltMonthNames (OLEAUT32.@)
941  */
942 HRESULT WINAPI GetAltMonthNames(LCID lcid, LPOLESTR **str)
943 {
944     static const WCHAR ar_month1W[] = {0x645,0x62d,0x631,0x645,0};
945     static const WCHAR ar_month2W[] = {0x635,0x641,0x631,0};
946     static const WCHAR ar_month3W[] = {0x631,0x628,0x64a,0x639,' ',0x627,0x644,0x627,0x648,0x644,0};
947     static const WCHAR ar_month4W[] = {0x631,0x628,0x64a,0x639,' ',0x627,0x644,0x62b,0x627,0x646,0x64a,0};
948     static const WCHAR ar_month5W[] = {0x62c,0x645,0x627,0x62f,0x649,' ',0x627,0x644,0x627,0x648,0x644,0x649,0};
949     static const WCHAR ar_month6W[] = {0x62c,0x645,0x627,0x62f,0x649,' ',0x627,0x644,0x62b,0x627,0x646,0x64a,0x629,0};
950     static const WCHAR ar_month7W[] = {0x631,0x62c,0x628,0};
951     static const WCHAR ar_month8W[] = {0x634,0x639,0x628,0x627,0x646,0};
952     static const WCHAR ar_month9W[] = {0x631,0x645,0x636,0x627,0x646,0};
953     static const WCHAR ar_month10W[] = {0x634,0x648,0x627,0x643,0};
954     static const WCHAR ar_month11W[] = {0x630,0x648,' ',0x627,0x644,0x642,0x639,0x62f,0x629,0};
955     static const WCHAR ar_month12W[] = {0x630,0x648,' ',0x627,0x644,0x62d,0x62c,0x629,0};
956 
957     static const WCHAR *arabic_hijri[] =
958     {
959         ar_month1W,
960         ar_month2W,
961         ar_month3W,
962         ar_month4W,
963         ar_month5W,
964         ar_month6W,
965         ar_month7W,
966         ar_month8W,
967         ar_month9W,
968         ar_month10W,
969         ar_month11W,
970         ar_month12W,
971         NULL
972     };
973 
974     static const WCHAR pl_month1W[] = {'s','t','y','c','z','n','i','a',0};
975     static const WCHAR pl_month2W[] = {'l','u','t','e','g','o',0};
976     static const WCHAR pl_month3W[] = {'m','a','r','c','a',0};
977     static const WCHAR pl_month4W[] = {'k','w','i','e','t','n','i','a',0};
978     static const WCHAR pl_month5W[] = {'m','a','j','a',0};
979     static const WCHAR pl_month6W[] = {'c','z','e','r','w','c','a',0};
980     static const WCHAR pl_month7W[] = {'l','i','p','c','a',0};
981     static const WCHAR pl_month8W[] = {'s','i','e','r','p','n','i','a',0};
982     static const WCHAR pl_month9W[] = {'w','r','z','e',0x15b,'n','i','a',0};
983     static const WCHAR pl_month10W[] = {'p','a',0x17a,'d','z','i','e','r','n','i','k','a',0};
984     static const WCHAR pl_month11W[] = {'l','i','s','t','o','p','a','d','a',0};
985     static const WCHAR pl_month12W[] = {'g','r','u','d','n','i','a',0};
986 
987     static const WCHAR *polish_genitive_names[] =
988     {
989         pl_month1W,
990         pl_month2W,
991         pl_month3W,
992         pl_month4W,
993         pl_month5W,
994         pl_month6W,
995         pl_month7W,
996         pl_month8W,
997         pl_month9W,
998         pl_month10W,
999         pl_month11W,
1000         pl_month12W,
1001         NULL
1002     };
1003 
1004     static const WCHAR ru_month1W[] = {0x44f,0x43d,0x432,0x430,0x440,0x44f,0};
1005     static const WCHAR ru_month2W[] = {0x444,0x435,0x432,0x440,0x430,0x43b,0x44f,0};
1006     static const WCHAR ru_month3W[] = {0x43c,0x430,0x440,0x442,0x430,0};
1007     static const WCHAR ru_month4W[] = {0x430,0x43f,0x440,0x435,0x43b,0x44f,0};
1008     static const WCHAR ru_month5W[] = {0x43c,0x430,0x44f,0};
1009     static const WCHAR ru_month6W[] = {0x438,0x44e,0x43d,0x44f,0};
1010     static const WCHAR ru_month7W[] = {0x438,0x44e,0x43b,0x44f,0};
1011     static const WCHAR ru_month8W[] = {0x430,0x432,0x433,0x443,0x441,0x442,0x430,0};
1012     static const WCHAR ru_month9W[] = {0x441,0x435,0x43d,0x442,0x44f,0x431,0x440,0x44f,0};
1013     static const WCHAR ru_month10W[] = {0x43e,0x43a,0x442,0x44f,0x431,0x440,0x44f,0};
1014     static const WCHAR ru_month11W[] = {0x43d,0x43e,0x44f,0x431,0x440,0x44f,0};
1015     static const WCHAR ru_month12W[] = {0x434,0x435,0x43a,0x430,0x431,0x440,0x44f,0};
1016 
1017     static const WCHAR *russian_genitive_names[] =
1018     {
1019         ru_month1W,
1020         ru_month2W,
1021         ru_month3W,
1022         ru_month4W,
1023         ru_month5W,
1024         ru_month6W,
1025         ru_month7W,
1026         ru_month8W,
1027         ru_month9W,
1028         ru_month10W,
1029         ru_month11W,
1030         ru_month12W,
1031         NULL
1032     };
1033 
1034     TRACE("%#x, %p\n", lcid, str);
1035 
1036     if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_ARABIC)
1037         *str = (LPOLESTR *)arabic_hijri;
1038     else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_POLISH)
1039         *str = (LPOLESTR *)polish_genitive_names;
1040     else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_RUSSIAN)
1041         *str = (LPOLESTR *)russian_genitive_names;
1042     else
1043         *str = NULL;
1044 
1045     return S_OK;
1046 }
1047