mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / oleaut32 / oleaut.c
blob08e6bc6e3f2fb2825e941d74b488401f869167bc
1 /*
2 * OLEAUT32
4 * Copyright 1999, 2000 Marcus Meissner
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <limits.h>
26 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winerror.h"
34 #include "ole2.h"
35 #include "olectl.h"
36 #include "oleauto.h"
37 #include "initguid.h"
38 #include "typelib.h"
39 #include "oleaut32_oaidl.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44 WINE_DECLARE_DEBUG_CHANNEL(heap);
46 /******************************************************************************
47 * BSTR {OLEAUT32}
49 * NOTES
50 * BSTR is a simple typedef for a wide-character string used as the principle
51 * string type in ole automation. When encapsulated in a Variant type they are
52 * automatically copied and destroyed as the variant is processed.
54 * The low level BSTR API allows manipulation of these strings and is used by
55 * higher level API calls to manage the strings transparently to the caller.
57 * Internally the BSTR type is allocated with space for a DWORD byte count before
58 * the string data begins. This is undocumented and non-system code should not
59 * access the count directly. Use SysStringLen() or SysStringByteLen()
60 * instead. Note that the byte count does not include the terminating NUL.
62 * To create a new BSTR, use SysAllocString(), SysAllocStringLen() or
63 * SysAllocStringByteLen(). To change the size of an existing BSTR, use SysReAllocString()
64 * or SysReAllocStringLen(). Finally to destroy a string use SysFreeString().
66 * BSTR's are cached by Ole Automation by default. To override this behaviour
67 * either set the environment variable 'OANOCACHE', or call SetOaNoCache().
69 * SEE ALSO
70 * 'Inside OLE, second edition' by Kraig Brockshmidt.
73 static BOOL bstr_cache_enabled;
75 static CRITICAL_SECTION cs_bstr_cache;
76 static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg =
78 0, 0, &cs_bstr_cache,
79 { &cs_bstr_cache_dbg.ProcessLocksList, &cs_bstr_cache_dbg.ProcessLocksList },
80 0, 0, { (DWORD_PTR)(__FILE__ ": bstr_cache") }
82 static CRITICAL_SECTION cs_bstr_cache = { &cs_bstr_cache_dbg, -1, 0, 0, 0, 0 };
84 typedef struct {
85 #ifdef _WIN64
86 DWORD pad;
87 #endif
88 DWORD size;
89 union {
90 char ptr[1];
91 WCHAR str[1];
92 DWORD dwptr[1];
93 } u;
94 } bstr_t;
96 #define BUCKET_SIZE 16
97 #define BUCKET_BUFFER_SIZE 6
99 typedef struct {
100 unsigned short head;
101 unsigned short cnt;
102 bstr_t *buf[BUCKET_BUFFER_SIZE];
103 } bstr_cache_entry_t;
105 #define ARENA_INUSE_FILLER 0x55
106 #define ARENA_TAIL_FILLER 0xab
107 #define ARENA_FREE_FILLER 0xfeeefeee
109 static bstr_cache_entry_t bstr_cache[0x10000/BUCKET_SIZE];
111 static inline size_t bstr_alloc_size(size_t size)
113 return (FIELD_OFFSET(bstr_t, u.ptr[size]) + sizeof(WCHAR) + BUCKET_SIZE-1) & ~(BUCKET_SIZE-1);
116 static inline bstr_t *bstr_from_str(BSTR str)
118 return CONTAINING_RECORD(str, bstr_t, u.str);
121 static inline bstr_cache_entry_t *get_cache_entry_from_idx(unsigned cache_idx)
123 return bstr_cache_enabled && cache_idx < ARRAY_SIZE(bstr_cache) ? bstr_cache + cache_idx : NULL;
126 static inline bstr_cache_entry_t *get_cache_entry(size_t size)
128 unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)-1])/BUCKET_SIZE;
129 return get_cache_entry_from_idx(cache_idx);
132 static inline bstr_cache_entry_t *get_cache_entry_from_alloc_size(SIZE_T alloc_size)
134 unsigned cache_idx;
135 if (alloc_size < BUCKET_SIZE) return NULL;
136 cache_idx = (alloc_size - BUCKET_SIZE) / BUCKET_SIZE;
137 return get_cache_entry_from_idx(cache_idx);
140 static bstr_t *alloc_bstr(size_t size)
142 bstr_cache_entry_t *cache_entry = get_cache_entry(size);
143 bstr_t *ret;
145 if(cache_entry) {
146 EnterCriticalSection(&cs_bstr_cache);
148 if(!cache_entry->cnt) {
149 cache_entry = get_cache_entry(size+BUCKET_SIZE);
150 if(cache_entry && !cache_entry->cnt)
151 cache_entry = NULL;
154 if(cache_entry) {
155 ret = cache_entry->buf[cache_entry->head++];
156 cache_entry->head %= BUCKET_BUFFER_SIZE;
157 cache_entry->cnt--;
160 LeaveCriticalSection(&cs_bstr_cache);
162 if(cache_entry) {
163 if(WARN_ON(heap)) {
164 size_t fill_size = (FIELD_OFFSET(bstr_t, u.ptr[size])+2*sizeof(WCHAR)-1) & ~(sizeof(WCHAR)-1);
165 memset(ret, ARENA_INUSE_FILLER, fill_size);
166 memset((char *)ret+fill_size, ARENA_TAIL_FILLER, bstr_alloc_size(size)-fill_size);
168 ret->size = size;
169 return ret;
173 ret = CoTaskMemAlloc(bstr_alloc_size(size));
174 if(ret)
175 ret->size = size;
176 return ret;
179 /******************************************************************************
180 * SysStringLen [OLEAUT32.7]
182 * Get the allocated length of a BSTR in wide characters.
184 * PARAMS
185 * str [I] BSTR to find the length of
187 * RETURNS
188 * The allocated length of str, or 0 if str is NULL.
190 * NOTES
191 * See BSTR.
192 * The returned length may be different from the length of the string as
193 * calculated by lstrlenW(), since it returns the length that was used to
194 * allocate the string by SysAllocStringLen().
196 UINT WINAPI SysStringLen(BSTR str)
198 return str ? bstr_from_str(str)->size/sizeof(WCHAR) : 0;
201 /******************************************************************************
202 * SysStringByteLen [OLEAUT32.149]
204 * Get the allocated length of a BSTR in bytes.
206 * PARAMS
207 * str [I] BSTR to find the length of
209 * RETURNS
210 * The allocated length of str, or 0 if str is NULL.
212 * NOTES
213 * See SysStringLen(), BSTR().
215 UINT WINAPI SysStringByteLen(BSTR str)
217 return str ? bstr_from_str(str)->size : 0;
220 /******************************************************************************
221 * SysAllocString [OLEAUT32.2]
223 * Create a BSTR from an OLESTR.
225 * PARAMS
226 * str [I] Source to create BSTR from
228 * RETURNS
229 * Success: A BSTR allocated with SysAllocStringLen().
230 * Failure: NULL, if oleStr is NULL.
232 * NOTES
233 * See BSTR.
234 * MSDN (October 2001) incorrectly states that NULL is returned if oleStr has
235 * a length of 0. Native Win32 and this implementation both return a valid
236 * empty BSTR in this case.
238 BSTR WINAPI SysAllocString(LPCOLESTR str)
240 if (!str) return 0;
242 /* Delegate this to the SysAllocStringLen32 method. */
243 return SysAllocStringLen(str, lstrlenW(str));
246 static inline IMalloc *get_malloc(void)
248 static IMalloc *malloc;
250 if (!malloc)
251 CoGetMalloc(1, &malloc);
253 return malloc;
256 /******************************************************************************
257 * SysFreeString [OLEAUT32.6]
259 * Free a BSTR.
261 * PARAMS
262 * str [I] BSTR to free.
264 * RETURNS
265 * Nothing.
267 * NOTES
268 * See BSTR.
269 * str may be NULL, in which case this function does nothing.
271 void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
273 bstr_cache_entry_t *cache_entry;
274 bstr_t *bstr;
275 IMalloc *malloc = get_malloc();
276 SIZE_T alloc_size;
278 if(!str)
279 return;
281 bstr = bstr_from_str(str);
283 alloc_size = IMalloc_GetSize(malloc, bstr);
284 if (alloc_size == ~0UL)
285 return;
287 cache_entry = get_cache_entry_from_alloc_size(alloc_size);
288 if(cache_entry) {
289 unsigned i;
291 EnterCriticalSection(&cs_bstr_cache);
293 /* According to tests, freeing a string that's already in cache doesn't corrupt anything.
294 * For that to work we need to search the cache. */
295 for(i=0; i < cache_entry->cnt; i++) {
296 if(cache_entry->buf[(cache_entry->head+i) % BUCKET_BUFFER_SIZE] == bstr) {
297 WARN_(heap)("String already is in cache!\n");
298 LeaveCriticalSection(&cs_bstr_cache);
299 return;
303 if(cache_entry->cnt < ARRAY_SIZE(cache_entry->buf)) {
304 cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr;
305 cache_entry->cnt++;
307 if(WARN_ON(heap)) {
308 unsigned n = (alloc_size-FIELD_OFFSET(bstr_t, u.ptr))/sizeof(DWORD);
309 for(i=0; i<n; i++)
310 bstr->u.dwptr[i] = ARENA_FREE_FILLER;
313 LeaveCriticalSection(&cs_bstr_cache);
314 return;
317 LeaveCriticalSection(&cs_bstr_cache);
320 CoTaskMemFree(bstr);
323 /******************************************************************************
324 * SysAllocStringLen [OLEAUT32.4]
326 * Create a BSTR from an OLESTR of a given wide character length.
328 * PARAMS
329 * str [I] Source to create BSTR from
330 * len [I] Length of oleStr in wide characters
332 * RETURNS
333 * Success: A newly allocated BSTR from SysAllocStringByteLen()
334 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
336 * NOTES
337 * See BSTR(), SysAllocStringByteLen().
339 BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
341 bstr_t *bstr;
342 DWORD size;
344 /* Detect integer overflow. */
345 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
346 return NULL;
348 TRACE("%s\n", debugstr_wn(str, len));
350 size = len*sizeof(WCHAR);
351 bstr = alloc_bstr(size);
352 if(!bstr)
353 return NULL;
355 if(str) {
356 memcpy(bstr->u.str, str, size);
357 bstr->u.str[len] = 0;
358 }else {
359 memset(bstr->u.str, 0, size+sizeof(WCHAR));
362 return bstr->u.str;
365 /******************************************************************************
366 * SysReAllocStringLen [OLEAUT32.5]
368 * Change the length of a previously created BSTR.
370 * PARAMS
371 * old [O] BSTR to change the length of
372 * str [I] New source for pbstr
373 * len [I] Length of oleStr in wide characters
375 * RETURNS
376 * Success: 1. The size of pbstr is updated.
377 * Failure: 0, if len >= 0x80000000 or memory allocation fails.
379 * NOTES
380 * See BSTR(), SysAllocStringByteLen().
381 * *old may be changed by this function.
383 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
385 /* Detect integer overflow. */
386 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
387 return FALSE;
389 if (*old!=NULL) {
390 DWORD newbytelen = len*sizeof(WCHAR);
391 bstr_t *old_bstr = bstr_from_str(*old);
392 bstr_t *bstr = CoTaskMemRealloc(old_bstr, bstr_alloc_size(newbytelen));
394 if (!bstr) return FALSE;
396 *old = bstr->u.str;
397 bstr->size = newbytelen;
398 /* The old string data is still there when str is NULL */
399 if (str && old_bstr->u.str != str) memmove(bstr->u.str, str, newbytelen);
400 bstr->u.str[len] = 0;
401 } else {
402 *old = SysAllocStringLen(str, len);
405 return TRUE;
408 /******************************************************************************
409 * SysAllocStringByteLen [OLEAUT32.150]
411 * Create a BSTR from an OLESTR of a given byte length.
413 * PARAMS
414 * str [I] Source to create BSTR from
415 * len [I] Length of oleStr in bytes
417 * RETURNS
418 * Success: A newly allocated BSTR
419 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
421 * NOTES
422 * -If len is 0 or oleStr is NULL the resulting string is empty ("").
423 * -This function always NUL terminates the resulting BSTR.
424 * -oleStr may be either an LPCSTR or LPCOLESTR, since it is copied
425 * without checking for a terminating NUL.
426 * See BSTR.
428 BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
430 bstr_t *bstr;
432 /* Detect integer overflow. */
433 if (len >= (UINT_MAX-sizeof(WCHAR)-sizeof(DWORD)))
434 return NULL;
436 bstr = alloc_bstr(len);
437 if(!bstr)
438 return NULL;
440 if(str) {
441 memcpy(bstr->u.ptr, str, len);
442 bstr->u.ptr[len] = 0;
443 }else {
444 memset(bstr->u.ptr, 0, len+1);
446 bstr->u.str[(len+sizeof(WCHAR)-1)/sizeof(WCHAR)] = 0;
448 return bstr->u.str;
451 /******************************************************************************
452 * SysReAllocString [OLEAUT32.3]
454 * Change the length of a previously created BSTR.
456 * PARAMS
457 * old [I/O] BSTR to change the length of
458 * str [I] New source for pbstr
460 * RETURNS
461 * Success: 1
462 * Failure: 0.
464 * NOTES
465 * See BSTR(), SysAllocStringStringLen().
467 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR str)
470 * Sanity check
472 if (old==NULL)
473 return 0;
476 * Make sure we free the old string.
478 SysFreeString(*old);
481 * Allocate the new string
483 *old = SysAllocString(str);
485 return 1;
488 /******************************************************************************
489 * SetOaNoCache (OLEAUT32.327)
491 * Instruct Ole Automation not to cache BSTR allocations.
493 * PARAMS
494 * None.
496 * RETURNS
497 * Nothing.
499 * NOTES
500 * SetOaNoCache does not release cached strings, so it leaks by design.
502 void WINAPI SetOaNoCache(void)
504 TRACE("\n");
505 bstr_cache_enabled = FALSE;
508 /***********************************************************************
509 * RegisterActiveObject (OLEAUT32.33)
511 * Registers an object in the global item table.
513 * PARAMS
514 * punk [I] Object to register.
515 * rcid [I] CLSID of the object.
516 * dwFlags [I] Flags.
517 * pdwRegister [O] Address to store cookie of object registration in.
519 * RETURNS
520 * Success: S_OK.
521 * Failure: HRESULT code.
523 HRESULT WINAPI DECLSPEC_HOTPATCH RegisterActiveObject(
524 LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
526 WCHAR guidbuf[80];
527 HRESULT ret;
528 LPRUNNINGOBJECTTABLE runobtable;
529 LPMONIKER moniker;
530 DWORD rot_flags = ROTFLAGS_REGISTRATIONKEEPSALIVE; /* default registration is strong */
532 StringFromGUID2(rcid,guidbuf,39);
533 ret = CreateItemMoniker(L"!", guidbuf, &moniker);
534 if (FAILED(ret))
535 return ret;
536 ret = GetRunningObjectTable(0,&runobtable);
537 if (FAILED(ret)) {
538 IMoniker_Release(moniker);
539 return ret;
541 if(dwFlags == ACTIVEOBJECT_WEAK)
542 rot_flags = 0;
543 ret = IRunningObjectTable_Register(runobtable,rot_flags,punk,moniker,pdwRegister);
544 IRunningObjectTable_Release(runobtable);
545 IMoniker_Release(moniker);
546 return ret;
549 /***********************************************************************
550 * RevokeActiveObject (OLEAUT32.34)
552 * Revokes an object from the global item table.
554 * PARAMS
555 * xregister [I] Registration cookie.
556 * reserved [I] Reserved. Set to NULL.
558 * RETURNS
559 * Success: S_OK.
560 * Failure: HRESULT code.
562 HRESULT WINAPI DECLSPEC_HOTPATCH RevokeActiveObject(DWORD xregister,LPVOID reserved)
564 LPRUNNINGOBJECTTABLE runobtable;
565 HRESULT ret;
567 ret = GetRunningObjectTable(0,&runobtable);
568 if (FAILED(ret)) return ret;
569 ret = IRunningObjectTable_Revoke(runobtable,xregister);
570 if (SUCCEEDED(ret)) ret = S_OK;
571 IRunningObjectTable_Release(runobtable);
572 return ret;
575 /***********************************************************************
576 * GetActiveObject (OLEAUT32.35)
578 * Gets an object from the global item table.
580 * PARAMS
581 * rcid [I] CLSID of the object.
582 * preserved [I] Reserved. Set to NULL.
583 * ppunk [O] Address to store object into.
585 * RETURNS
586 * Success: S_OK.
587 * Failure: HRESULT code.
589 HRESULT WINAPI DECLSPEC_HOTPATCH GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
591 WCHAR guidbuf[80];
592 HRESULT ret;
593 LPRUNNINGOBJECTTABLE runobtable;
594 LPMONIKER moniker;
596 StringFromGUID2(rcid,guidbuf,39);
597 ret = CreateItemMoniker(L"!", guidbuf, &moniker);
598 if (FAILED(ret))
599 return ret;
600 ret = GetRunningObjectTable(0,&runobtable);
601 if (FAILED(ret)) {
602 IMoniker_Release(moniker);
603 return ret;
605 ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk);
606 IRunningObjectTable_Release(runobtable);
607 IMoniker_Release(moniker);
608 return ret;
612 /***********************************************************************
613 * OaBuildVersion [OLEAUT32.170]
615 * Get the Ole Automation build version.
617 * PARAMS
618 * None
620 * RETURNS
621 * The build version.
623 * NOTES
624 * Known oleaut32.dll versions:
625 *| OLE Ver. Comments Date Build Ver.
626 *| -------- ------------------------- ---- ---------
627 *| OLE 2.1 NT 1993-95 10 3023
628 *| OLE 2.1 10 3027
629 *| Win32s Ver 1.1e 20 4049
630 *| OLE 2.20 W95/NT 1993-96 20 4112
631 *| OLE 2.20 W95/NT 1993-96 20 4118
632 *| OLE 2.20 W95/NT 1993-96 20 4122
633 *| OLE 2.30 W95/NT 1993-98 30 4265
634 *| OLE 2.40 NT?? 1993-98 40 4267
635 *| OLE 2.40 W98 SE orig. file 1993-98 40 4275
636 *| OLE 2.40 W2K orig. file 1993-XX 40 4514
638 * Currently the versions returned are 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
639 * and 2.40 for all later versions. The build number is maximum, i.e. 0xffff.
641 ULONG WINAPI OaBuildVersion(void)
643 switch(GetVersion() & 0x8000ffff) /* mask off build number */
645 case 0x80000a03: /* WIN31 */
646 return MAKELONG(0xffff, 20);
647 case 0x00003303: /* NT351 */
648 return MAKELONG(0xffff, 30);
649 case 0x80000004: /* WIN95; I'd like to use the "standard" w95 minor
650 version here (30), but as we still use w95
651 as default winver (which is good IMHO), I better
652 play safe and use the latest value for w95 for now.
653 Change this as soon as default winver gets changed
654 to something more recent */
655 case 0x80000a04: /* WIN98 */
656 case 0x00000004: /* NT40 */
657 case 0x00000005: /* W2K */
658 return MAKELONG(0xffff, 40);
659 case 0x00000105: /* WinXP */
660 case 0x00000006: /* Vista */
661 case 0x00000106: /* Win7 */
662 return MAKELONG(0xffff, 50);
663 default:
664 FIXME("Version value not known yet. Please investigate it !\n");
665 return MAKELONG(0xffff, 40); /* for now return the same value as for w2k */
669 /******************************************************************************
670 * OleTranslateColor [OLEAUT32.421]
672 * Convert an OLE_COLOR to a COLORREF.
674 * PARAMS
675 * clr [I] Color to convert
676 * hpal [I] Handle to a palette for the conversion
677 * pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok
679 * RETURNS
680 * Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL.
681 * Failure: E_INVALIDARG, if any argument is invalid.
683 * FIXME
684 * Document the conversion rules.
686 HRESULT WINAPI OleTranslateColor(
687 OLE_COLOR clr,
688 HPALETTE hpal,
689 COLORREF* pColorRef)
691 COLORREF colorref;
692 BYTE b = HIBYTE(HIWORD(clr));
694 TRACE("(%08x, %p, %p)\n", clr, hpal, pColorRef);
697 * In case pColorRef is NULL, provide our own to simplify the code.
699 if (pColorRef == NULL)
700 pColorRef = &colorref;
702 switch (b)
704 case 0x00:
706 if (hpal != 0)
707 *pColorRef = PALETTERGB(GetRValue(clr),
708 GetGValue(clr),
709 GetBValue(clr));
710 else
711 *pColorRef = clr;
713 break;
716 case 0x01:
718 if (hpal != 0)
720 PALETTEENTRY pe;
722 * Validate the palette index.
724 if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0)
725 return E_INVALIDARG;
728 *pColorRef = clr;
730 break;
733 case 0x02:
734 *pColorRef = clr;
735 break;
737 case 0x80:
739 int index = LOBYTE(LOWORD(clr));
742 * Validate GetSysColor index.
744 if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR))
745 return E_INVALIDARG;
747 *pColorRef = GetSysColor(index);
749 break;
752 default:
753 return E_INVALIDARG;
756 return S_OK;
759 extern HRESULT WINAPI OLEAUTPS_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN;
760 extern BOOL WINAPI OLEAUTPS_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
761 extern HRESULT WINAPI OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN;
762 extern HRESULT WINAPI OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN;
764 extern HRESULT WINAPI CreateProxyFromTypeInfo(ITypeInfo *typeinfo,
765 IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **obj);
766 extern HRESULT WINAPI CreateStubFromTypeInfo(ITypeInfo *typeinfo, REFIID iid,
767 IUnknown *server, IRpcStubBuffer **stub);
769 struct ifacepsredirect_data
771 ULONG size;
772 DWORD mask;
773 GUID iid;
774 ULONG nummethods;
775 GUID tlbid;
776 GUID base;
777 ULONG name_len;
778 ULONG name_offset;
781 struct tlibredirect_data
783 ULONG size;
784 DWORD res;
785 ULONG name_len;
786 ULONG name_offset;
787 LANGID langid;
788 WORD flags;
789 ULONG help_len;
790 ULONG help_offset;
791 WORD major_version;
792 WORD minor_version;
795 static BOOL actctx_get_typelib_module(REFIID iid, WCHAR *module, DWORD len)
797 struct ifacepsredirect_data *iface;
798 struct tlibredirect_data *tlib;
799 ACTCTX_SECTION_KEYED_DATA data;
800 WCHAR *ptrW;
802 data.cbSize = sizeof(data);
803 if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
804 iid, &data))
805 return FALSE;
807 iface = (struct ifacepsredirect_data *)data.lpData;
808 if (!FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION,
809 &iface->tlbid, &data))
810 return FALSE;
812 tlib = (struct tlibredirect_data *)data.lpData;
813 ptrW = (WCHAR *)((BYTE *)data.lpSectionBase + tlib->name_offset);
815 if (tlib->name_len/sizeof(WCHAR) >= len)
817 ERR("need larger module buffer, %u\n", tlib->name_len);
818 return FALSE;
821 memcpy(module, ptrW, tlib->name_len);
822 module[tlib->name_len/sizeof(WCHAR)] = 0;
823 return TRUE;
826 static HRESULT reg_get_typelib_module(REFIID iid, WCHAR *module, DWORD len)
828 REGSAM opposite = (sizeof(void*) == 8) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
829 char tlguid[200], typelibkey[316], interfacekey[300], ver[100], tlfn[260];
830 DWORD tlguidlen, verlen, type;
831 LONG tlfnlen, err;
832 BOOL is_wow64;
833 HKEY ikey;
835 sprintf( interfacekey, "Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
836 iid->Data1, iid->Data2, iid->Data3,
837 iid->Data4[0], iid->Data4[1], iid->Data4[2], iid->Data4[3],
838 iid->Data4[4], iid->Data4[5], iid->Data4[6], iid->Data4[7]
841 err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ,&ikey);
842 if (err && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64)
843 && is_wow64)))
844 err = RegOpenKeyExA(HKEY_CLASSES_ROOT,interfacekey,0,KEY_READ|opposite,&ikey);
846 if (err)
848 ERR("No %s key found.\n", interfacekey);
849 return E_FAIL;
852 tlguidlen = sizeof(tlguid);
853 if (RegQueryValueExA(ikey, NULL, NULL, &type, (BYTE *)tlguid, &tlguidlen))
855 ERR("Getting typelib guid failed.\n");
856 RegCloseKey(ikey);
857 return E_FAIL;
860 verlen = sizeof(ver);
861 if (RegQueryValueExA(ikey, "Version", NULL, &type, (BYTE *)ver, &verlen))
863 ERR("Could not get version value?\n");
864 RegCloseKey(ikey);
865 return E_FAIL;
868 RegCloseKey(ikey);
870 sprintf(typelibkey, "Typelib\\%s\\%s\\0\\win%u", tlguid, ver, sizeof(void *) == 8 ? 64 : 32);
871 tlfnlen = sizeof(tlfn);
872 if (RegQueryValueA(HKEY_CLASSES_ROOT, typelibkey, tlfn, &tlfnlen))
874 #ifdef _WIN64
875 sprintf(typelibkey, "Typelib\\%s\\%s\\0\\win32", tlguid, ver);
876 tlfnlen = sizeof(tlfn);
877 if (RegQueryValueA(HKEY_CLASSES_ROOT, typelibkey, tlfn, &tlfnlen))
879 #endif
880 ERR("Could not get typelib fn?\n");
881 return E_FAIL;
882 #ifdef _WIN64
884 #endif
886 MultiByteToWideChar(CP_ACP, 0, tlfn, -1, module, len);
887 return S_OK;
890 static HRESULT get_typeinfo_for_iid(REFIID iid, ITypeInfo **typeinfo)
892 WCHAR module[MAX_PATH];
893 ITypeLib *typelib;
894 HRESULT hr;
896 *typeinfo = NULL;
898 module[0] = 0;
899 if (!actctx_get_typelib_module(iid, module, ARRAY_SIZE(module)))
901 hr = reg_get_typelib_module(iid, module, ARRAY_SIZE(module));
902 if (FAILED(hr))
903 return hr;
906 hr = LoadTypeLib(module, &typelib);
907 if (hr != S_OK) {
908 ERR("Failed to load typelib for %s, but it should be there.\n", debugstr_guid(iid));
909 return hr;
912 hr = ITypeLib_GetTypeInfoOfGuid(typelib, iid, typeinfo);
913 ITypeLib_Release(typelib);
914 if (hr != S_OK)
915 ERR("typelib does not contain info for %s\n", debugstr_guid(iid));
917 return hr;
920 static HRESULT WINAPI dispatch_typelib_ps_QueryInterface(IPSFactoryBuffer *iface, REFIID iid, void **out)
922 if (IsEqualIID(iid, &IID_IPSFactoryBuffer) || IsEqualIID(iid, &IID_IUnknown))
924 *out = iface;
925 return S_OK;
928 FIXME("No interface for %s.\n", debugstr_guid(iid));
929 *out = NULL;
930 return E_NOINTERFACE;
933 static ULONG WINAPI dispatch_typelib_ps_AddRef(IPSFactoryBuffer *iface)
935 return 2;
938 static ULONG WINAPI dispatch_typelib_ps_Release(IPSFactoryBuffer *iface)
940 return 1;
943 static HRESULT dispatch_create_proxy(IUnknown *outer, IRpcProxyBuffer **proxy, void **out)
945 IPSFactoryBuffer *factory;
946 HRESULT hr;
948 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
949 if (FAILED(hr)) return hr;
951 hr = IPSFactoryBuffer_CreateProxy(factory, outer, &IID_IDispatch, proxy, out);
952 IPSFactoryBuffer_Release(factory);
953 return hr;
956 static HRESULT WINAPI dispatch_typelib_ps_CreateProxy(IPSFactoryBuffer *iface,
957 IUnknown *outer, REFIID iid, IRpcProxyBuffer **proxy, void **out)
959 ITypeInfo *typeinfo;
960 TYPEATTR *attr;
961 HRESULT hr;
963 if (IsEqualGUID(iid, &IID_IDispatch))
964 return dispatch_create_proxy(outer, proxy, out);
966 hr = get_typeinfo_for_iid(iid, &typeinfo);
967 if (FAILED(hr)) return hr;
969 hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
970 if (FAILED(hr))
972 ITypeInfo_Release(typeinfo);
973 return hr;
976 if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
977 hr = CreateProxyFromTypeInfo(typeinfo, outer, iid, proxy, out);
978 else
979 hr = dispatch_create_proxy(outer, proxy, out);
981 if (FAILED(hr))
982 ERR("Failed to create proxy, hr %#x.\n", hr);
984 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
985 ITypeInfo_Release(typeinfo);
986 return hr;
989 static HRESULT dispatch_create_stub(IUnknown *server, IRpcStubBuffer **stub)
991 IPSFactoryBuffer *factory;
992 HRESULT hr;
994 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&factory);
995 if (FAILED(hr)) return hr;
997 hr = IPSFactoryBuffer_CreateStub(factory, &IID_IDispatch, server, stub);
998 IPSFactoryBuffer_Release(factory);
999 return hr;
1002 static HRESULT WINAPI dispatch_typelib_ps_CreateStub(IPSFactoryBuffer *iface,
1003 REFIID iid, IUnknown *server, IRpcStubBuffer **stub)
1005 ITypeInfo *typeinfo;
1006 TYPEATTR *attr;
1007 HRESULT hr;
1009 if (IsEqualGUID(iid, &IID_IDispatch))
1010 return dispatch_create_stub(server, stub);
1012 hr = get_typeinfo_for_iid(iid, &typeinfo);
1013 if (FAILED(hr)) return hr;
1015 hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
1016 if (FAILED(hr))
1018 ITypeInfo_Release(typeinfo);
1019 return hr;
1022 if (attr->typekind == TKIND_INTERFACE || (attr->wTypeFlags & TYPEFLAG_FDUAL))
1023 hr = CreateStubFromTypeInfo(typeinfo, iid, server, stub);
1024 else
1025 hr = dispatch_create_stub(server, stub);
1027 if (FAILED(hr))
1028 ERR("Failed to create proxy, hr %#x.\n", hr);
1030 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
1031 ITypeInfo_Release(typeinfo);
1032 return hr;
1035 static const IPSFactoryBufferVtbl dispatch_typelib_ps_vtbl =
1037 dispatch_typelib_ps_QueryInterface,
1038 dispatch_typelib_ps_AddRef,
1039 dispatch_typelib_ps_Release,
1040 dispatch_typelib_ps_CreateProxy,
1041 dispatch_typelib_ps_CreateStub,
1044 static IPSFactoryBuffer dispatch_typelib_ps = { &dispatch_typelib_ps_vtbl };
1046 extern void _get_STDFONT_CF(LPVOID *);
1047 extern void _get_STDPIC_CF(LPVOID *);
1049 /***********************************************************************
1050 * DllGetClassObject (OLEAUT32.@)
1052 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1054 *ppv = NULL;
1055 if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
1056 if (IsEqualGUID(iid,&IID_IClassFactory)) {
1057 _get_STDFONT_CF(ppv);
1058 IClassFactory_AddRef((IClassFactory*)*ppv);
1059 return S_OK;
1062 if (IsEqualGUID(rclsid,&CLSID_StdPicture)) {
1063 if (IsEqualGUID(iid,&IID_IClassFactory)) {
1064 _get_STDPIC_CF(ppv);
1065 IClassFactory_AddRef((IClassFactory*)*ppv);
1066 return S_OK;
1070 if (IsEqualGUID(rclsid, &CLSID_PSDispatch) || IsEqualGUID(rclsid, &CLSID_PSOAInterface))
1071 return IPSFactoryBuffer_QueryInterface(&dispatch_typelib_ps, iid, ppv);
1073 if (IsEqualCLSID(rclsid, &CLSID_PSTypeComp) ||
1074 IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) ||
1075 IsEqualCLSID(rclsid, &CLSID_PSTypeLib) ||
1076 IsEqualCLSID(rclsid, &CLSID_PSDispatch) ||
1077 IsEqualCLSID(rclsid, &CLSID_PSEnumVariant))
1078 return OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, iid, ppv);
1080 return OLEAUTPS_DllGetClassObject(rclsid, iid, ppv);
1083 /***********************************************************************
1084 * DllCanUnloadNow (OLEAUT32.@)
1086 * Determine if this dll can be unloaded from the callers address space.
1088 * PARAMS
1089 * None.
1091 * RETURNS
1092 * Always returns S_FALSE. This dll cannot be unloaded.
1094 HRESULT WINAPI DllCanUnloadNow(void)
1096 return S_FALSE;
1099 /*****************************************************************************
1100 * DllMain [OLEAUT32.@]
1102 BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
1104 if(fdwReason == DLL_PROCESS_ATTACH)
1105 bstr_cache_enabled = !GetEnvironmentVariableW(L"oanocache", NULL, 0);
1107 return OLEAUTPS_DllMain( hInstDll, fdwReason, lpvReserved );
1110 /***********************************************************************
1111 * DllRegisterServer (OLEAUT32.@)
1113 HRESULT WINAPI DllRegisterServer(void)
1115 return OLEAUTPS_DllRegisterServer();
1118 /***********************************************************************
1119 * DllUnregisterServer (OLEAUT32.@)
1121 HRESULT WINAPI DllUnregisterServer(void)
1123 return OLEAUTPS_DllUnregisterServer();
1126 /***********************************************************************
1127 * OleIconToCursor (OLEAUT32.415)
1129 HCURSOR WINAPI OleIconToCursor( HINSTANCE hinstExe, HICON hIcon)
1131 FIXME("(%p,%p), partially implemented.\n",hinstExe,hIcon);
1132 /* FIXME: make an extended conversation from HICON to HCURSOR */
1133 return CopyCursor(hIcon);
1136 /***********************************************************************
1137 * GetAltMonthNames (OLEAUT32.@)
1139 HRESULT WINAPI GetAltMonthNames(LCID lcid, LPOLESTR **str)
1141 static const WCHAR *arabic_hijri[] =
1143 L"\x0645\x062d\x0631\x0645",
1144 L"\x0635\x0641\x0631",
1145 L"\x0631\x0628\x064a\x0639 \x0627\x0644\x0627\x0648\x0644",
1146 L"\x0631\x0628\x064a\x0639 \x0627\x0644\x062b\x0627\x0646\x064a",
1147 L"\x062c\x0645\x0627\x062f\x0649 \x0627\x0644\x0627\x0648\x0644\x0649",
1148 L"\x062c\x0645\x0627\x062f\x0649 \x0627\x0644\x062b\x0627\x0646\x064a\x0629",
1149 L"\x0631\x062c\x0628",
1150 L"\x0634\x0639\x0628\x0627\x0646",
1151 L"\x0631\x0645\x0636\x0627\x0646",
1152 L"\x0634\x0648\x0627\x0643",
1153 L"\x0630\x0648 \x0627\x0644\x0642\x0639\x062f\x0629",
1154 L"\x0630\x0648 \x0627\x0644\x062d\x062c\x0629",
1155 NULL
1158 static const WCHAR *polish_genitive_names[] =
1160 L"stycznia",
1161 L"lutego",
1162 L"marca",
1163 L"kwietnia",
1164 L"maja",
1165 L"czerwca",
1166 L"lipca",
1167 L"sierpnia",
1168 L"wrze\x015bnia",
1169 L"pa\x017a" "dziernika",
1170 L"listopada",
1171 L"grudnia",
1172 NULL
1175 static const WCHAR *russian_genitive_names[] =
1177 L"\x044f\x043d\x0432\x0430\x0440\x044f",
1178 L"\x0444\x0435\x0432\x0440\x0430\x043b\x044f",
1179 L"\x043c\x0430\x0440\x0442\x0430",
1180 L"\x0430\x043f\x0440\x0435\x043b\x044f",
1181 L"\x043c\x0430\x044f",
1182 L"\x0438\x044e\x043d\x044f",
1183 L"\x0438\x044e\x043b\x044f",
1184 L"\x0430\x0432\x0433\x0443\x0441\x0442\x0430",
1185 L"\x0441\x0435\x043d\x0442\x044f\x0431\x0440\x044f",
1186 L"\x043e\x043a\x0442\x044f\x0431\x0440\x044f",
1187 L"\x043d\x043e\x044f\x0431\x0440\x044f",
1188 L"\x0434\x0435\x043a\x0430\x0431\x0440\x044f",
1189 NULL
1192 TRACE("%#x, %p\n", lcid, str);
1194 if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_ARABIC)
1195 *str = (LPOLESTR *)arabic_hijri;
1196 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_POLISH)
1197 *str = (LPOLESTR *)polish_genitive_names;
1198 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_RUSSIAN)
1199 *str = (LPOLESTR *)russian_genitive_names;
1200 else
1201 *str = NULL;
1203 return S_OK;