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
41 #include "oleaut32_oaidl.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
46 WINE_DECLARE_DEBUG_CHANNEL(heap
);
48 /******************************************************************************
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.
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.
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.
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().
68 * BSTR's are cached by Ole Automation by default. To override this behaviour
69 * either set the environment variable 'OANOCACHE', or call SetOaNoCache().
72 * 'Inside OLE, second edition' by Kraig Brockshmidt.
75 static BOOL bstr_cache_enabled
;
77 static CRITICAL_SECTION cs_bstr_cache
;
78 static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg
=
81 { &cs_bstr_cache_dbg
.ProcessLocksList
, &cs_bstr_cache_dbg
.ProcessLocksList
},
82 0, 0, { (DWORD_PTR
)(__FILE__
": bstr_cache") }
84 static CRITICAL_SECTION cs_bstr_cache
= { &cs_bstr_cache_dbg
, -1, 0, 0, 0, 0 };
98 #define BUCKET_SIZE 16
99 #define BUCKET_BUFFER_SIZE 6
104 bstr_t
*buf
[BUCKET_BUFFER_SIZE
];
105 } bstr_cache_entry_t
;
107 #define ARENA_INUSE_FILLER 0x55
108 #define ARENA_TAIL_FILLER 0xab
109 #define ARENA_FREE_FILLER 0xfeeefeee
111 static bstr_cache_entry_t bstr_cache
[0x10000/BUCKET_SIZE
];
113 static inline size_t bstr_alloc_size(size_t size
)
115 return (FIELD_OFFSET(bstr_t
, u
.ptr
[size
]) + sizeof(WCHAR
) + BUCKET_SIZE
-1) & ~(BUCKET_SIZE
-1);
118 static inline bstr_t
*bstr_from_str(BSTR str
)
120 return CONTAINING_RECORD(str
, bstr_t
, u
.str
);
123 static inline bstr_cache_entry_t
*get_cache_entry_from_idx(unsigned cache_idx
)
125 return bstr_cache_enabled
&& cache_idx
< ARRAY_SIZE(bstr_cache
) ? bstr_cache
+ cache_idx
: NULL
;
128 static inline bstr_cache_entry_t
*get_cache_entry(size_t size
)
130 unsigned cache_idx
= FIELD_OFFSET(bstr_t
, u
.ptr
[size
+sizeof(WCHAR
)-1])/BUCKET_SIZE
;
131 return get_cache_entry_from_idx(cache_idx
);
134 static inline bstr_cache_entry_t
*get_cache_entry_from_alloc_size(SIZE_T alloc_size
)
137 if (alloc_size
< BUCKET_SIZE
) return NULL
;
138 cache_idx
= (alloc_size
- BUCKET_SIZE
) / BUCKET_SIZE
;
139 return get_cache_entry_from_idx(cache_idx
);
142 static bstr_t
*alloc_bstr(size_t size
)
144 bstr_cache_entry_t
*cache_entry
= get_cache_entry(size
);
148 EnterCriticalSection(&cs_bstr_cache
);
150 if(!cache_entry
->cnt
) {
151 cache_entry
= get_cache_entry(size
+BUCKET_SIZE
);
152 if(cache_entry
&& !cache_entry
->cnt
)
157 ret
= cache_entry
->buf
[cache_entry
->head
++];
158 cache_entry
->head
%= BUCKET_BUFFER_SIZE
;
162 LeaveCriticalSection(&cs_bstr_cache
);
166 size_t fill_size
= (FIELD_OFFSET(bstr_t
, u
.ptr
[size
])+2*sizeof(WCHAR
)-1) & ~(sizeof(WCHAR
)-1);
167 memset(ret
, ARENA_INUSE_FILLER
, fill_size
);
168 memset((char *)ret
+fill_size
, ARENA_TAIL_FILLER
, bstr_alloc_size(size
)-fill_size
);
175 ret
= CoTaskMemAlloc(bstr_alloc_size(size
));
181 /******************************************************************************
182 * SysStringLen [OLEAUT32.7]
184 * Get the allocated length of a BSTR in wide characters.
187 * str [I] BSTR to find the length of
190 * The allocated length of str, or 0 if str is NULL.
194 * The returned length may be different from the length of the string as
195 * calculated by lstrlenW(), since it returns the length that was used to
196 * allocate the string by SysAllocStringLen().
198 UINT WINAPI
SysStringLen(BSTR str
)
200 return str
? bstr_from_str(str
)->size
/sizeof(WCHAR
) : 0;
203 /******************************************************************************
204 * SysStringByteLen [OLEAUT32.149]
206 * Get the allocated length of a BSTR in bytes.
209 * str [I] BSTR to find the length of
212 * The allocated length of str, or 0 if str is NULL.
215 * See SysStringLen(), BSTR().
217 UINT WINAPI
SysStringByteLen(BSTR str
)
219 return str
? bstr_from_str(str
)->size
: 0;
222 /******************************************************************************
223 * SysAllocString [OLEAUT32.2]
225 * Create a BSTR from an OLESTR.
228 * str [I] Source to create BSTR from
231 * Success: A BSTR allocated with SysAllocStringLen().
232 * Failure: NULL, if oleStr is NULL.
236 * MSDN (October 2001) incorrectly states that NULL is returned if oleStr has
237 * a length of 0. Native Win32 and this implementation both return a valid
238 * empty BSTR in this case.
240 BSTR WINAPI
SysAllocString(LPCOLESTR str
)
244 /* Delegate this to the SysAllocStringLen32 method. */
245 return SysAllocStringLen(str
, lstrlenW(str
));
248 static inline IMalloc
*get_malloc(void)
250 static IMalloc
*malloc
;
253 CoGetMalloc(1, &malloc
);
258 /******************************************************************************
259 * SysFreeString [OLEAUT32.6]
264 * str [I] BSTR to free.
271 * str may be NULL, in which case this function does nothing.
273 void WINAPI DECLSPEC_HOTPATCH
SysFreeString(BSTR str
)
275 bstr_cache_entry_t
*cache_entry
;
277 IMalloc
*malloc
= get_malloc();
283 bstr
= bstr_from_str(str
);
285 alloc_size
= IMalloc_GetSize(malloc
, bstr
);
286 if (alloc_size
== ~0UL)
289 cache_entry
= get_cache_entry_from_alloc_size(alloc_size
);
293 EnterCriticalSection(&cs_bstr_cache
);
295 /* According to tests, freeing a string that's already in cache doesn't corrupt anything.
296 * For that to work we need to search the cache. */
297 for(i
=0; i
< cache_entry
->cnt
; i
++) {
298 if(cache_entry
->buf
[(cache_entry
->head
+i
) % BUCKET_BUFFER_SIZE
] == bstr
) {
299 WARN_(heap
)("String already is in cache!\n");
300 LeaveCriticalSection(&cs_bstr_cache
);
305 if(cache_entry
->cnt
< ARRAY_SIZE(cache_entry
->buf
)) {
306 cache_entry
->buf
[(cache_entry
->head
+cache_entry
->cnt
) % BUCKET_BUFFER_SIZE
] = bstr
;
310 unsigned n
= (alloc_size
-FIELD_OFFSET(bstr_t
, u
.ptr
))/sizeof(DWORD
);
312 bstr
->u
.dwptr
[i
] = ARENA_FREE_FILLER
;
315 LeaveCriticalSection(&cs_bstr_cache
);
319 LeaveCriticalSection(&cs_bstr_cache
);
325 /******************************************************************************
326 * SysAllocStringLen [OLEAUT32.4]
328 * Create a BSTR from an OLESTR of a given wide character length.
331 * str [I] Source to create BSTR from
332 * len [I] Length of oleStr in wide characters
335 * Success: A newly allocated BSTR from SysAllocStringByteLen()
336 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
339 * See BSTR(), SysAllocStringByteLen().
341 BSTR WINAPI
SysAllocStringLen(const OLECHAR
*str
, unsigned int len
)
346 /* Detect integer overflow. */
347 if (len
>= ((UINT_MAX
-sizeof(WCHAR
)-sizeof(DWORD
))/sizeof(WCHAR
)))
350 TRACE("%s\n", debugstr_wn(str
, len
));
352 size
= len
*sizeof(WCHAR
);
353 bstr
= alloc_bstr(size
);
358 memcpy(bstr
->u
.str
, str
, size
);
359 bstr
->u
.str
[len
] = 0;
361 memset(bstr
->u
.str
, 0, size
+sizeof(WCHAR
));
367 /******************************************************************************
368 * SysReAllocStringLen [OLEAUT32.5]
370 * Change the length of a previously created BSTR.
373 * old [O] BSTR to change the length of
374 * str [I] New source for pbstr
375 * len [I] Length of oleStr in wide characters
378 * Success: 1. The size of pbstr is updated.
379 * Failure: 0, if len >= 0x80000000 or memory allocation fails.
382 * See BSTR(), SysAllocStringByteLen().
383 * *old may be changed by this function.
385 int WINAPI
SysReAllocStringLen(BSTR
* old
, const OLECHAR
* str
, unsigned int len
)
387 /* Detect integer overflow. */
388 if (len
>= ((UINT_MAX
-sizeof(WCHAR
)-sizeof(DWORD
))/sizeof(WCHAR
)))
392 DWORD newbytelen
= len
*sizeof(WCHAR
);
393 bstr_t
*old_bstr
= bstr_from_str(*old
);
394 bstr_t
*bstr
= CoTaskMemRealloc(old_bstr
, bstr_alloc_size(newbytelen
));
396 if (!bstr
) return FALSE
;
399 bstr
->size
= newbytelen
;
400 /* The old string data is still there when str is NULL */
401 if (str
&& old_bstr
->u
.str
!= str
) memmove(bstr
->u
.str
, str
, newbytelen
);
402 bstr
->u
.str
[len
] = 0;
404 *old
= SysAllocStringLen(str
, len
);
410 /******************************************************************************
411 * SysAllocStringByteLen [OLEAUT32.150]
413 * Create a BSTR from an OLESTR of a given byte length.
416 * str [I] Source to create BSTR from
417 * len [I] Length of oleStr in bytes
420 * Success: A newly allocated BSTR
421 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails.
424 * -If len is 0 or oleStr is NULL the resulting string is empty ("").
425 * -This function always NUL terminates the resulting BSTR.
426 * -oleStr may be either an LPCSTR or LPCOLESTR, since it is copied
427 * without checking for a terminating NUL.
430 BSTR WINAPI DECLSPEC_HOTPATCH
SysAllocStringByteLen(LPCSTR str
, UINT len
)
434 /* Detect integer overflow. */
435 if (len
>= (UINT_MAX
-sizeof(WCHAR
)-sizeof(DWORD
)))
438 bstr
= alloc_bstr(len
);
443 memcpy(bstr
->u
.ptr
, str
, len
);
444 bstr
->u
.ptr
[len
] = 0;
446 memset(bstr
->u
.ptr
, 0, len
+1);
448 bstr
->u
.str
[(len
+sizeof(WCHAR
)-1)/sizeof(WCHAR
)] = 0;
453 /******************************************************************************
454 * SysReAllocString [OLEAUT32.3]
456 * Change the length of a previously created BSTR.
459 * old [I/O] BSTR to change the length of
460 * str [I] New source for pbstr
467 * See BSTR(), SysAllocStringStringLen().
469 INT WINAPI
SysReAllocString(LPBSTR old
,LPCOLESTR str
)
478 * Make sure we free the old string.
483 * Allocate the new string
485 *old
= SysAllocString(str
);
490 /******************************************************************************
491 * SetOaNoCache (OLEAUT32.327)
493 * Instruct Ole Automation not to cache BSTR allocations.
502 * SetOaNoCache does not release cached strings, so it leaks by design.
504 void WINAPI
SetOaNoCache(void)
507 bstr_cache_enabled
= FALSE
;
510 /***********************************************************************
511 * RegisterActiveObject (OLEAUT32.33)
513 * Registers an object in the global item table.
516 * punk [I] Object to register.
517 * rcid [I] CLSID of the object.
519 * pdwRegister [O] Address to store cookie of object registration in.
523 * Failure: HRESULT code.
525 HRESULT WINAPI DECLSPEC_HOTPATCH
RegisterActiveObject(
526 LPUNKNOWN punk
,REFCLSID rcid
,DWORD dwFlags
,LPDWORD pdwRegister
530 LPRUNNINGOBJECTTABLE runobtable
;
532 DWORD rot_flags
= ROTFLAGS_REGISTRATIONKEEPSALIVE
; /* default registration is strong */
534 StringFromGUID2(rcid
,guidbuf
,39);
535 ret
= CreateItemMoniker(L
"!", guidbuf
, &moniker
);
538 ret
= GetRunningObjectTable(0,&runobtable
);
540 IMoniker_Release(moniker
);
543 if(dwFlags
== ACTIVEOBJECT_WEAK
)
545 ret
= IRunningObjectTable_Register(runobtable
,rot_flags
,punk
,moniker
,pdwRegister
);
546 IRunningObjectTable_Release(runobtable
);
547 IMoniker_Release(moniker
);
551 /***********************************************************************
552 * RevokeActiveObject (OLEAUT32.34)
554 * Revokes an object from the global item table.
557 * xregister [I] Registration cookie.
558 * reserved [I] Reserved. Set to NULL.
562 * Failure: HRESULT code.
564 HRESULT WINAPI DECLSPEC_HOTPATCH
RevokeActiveObject(DWORD xregister
,LPVOID reserved
)
566 LPRUNNINGOBJECTTABLE runobtable
;
569 ret
= GetRunningObjectTable(0,&runobtable
);
570 if (FAILED(ret
)) return ret
;
571 ret
= IRunningObjectTable_Revoke(runobtable
,xregister
);
572 if (SUCCEEDED(ret
)) ret
= S_OK
;
573 IRunningObjectTable_Release(runobtable
);
577 /***********************************************************************
578 * GetActiveObject (OLEAUT32.35)
580 * Gets an object from the global item table.
583 * rcid [I] CLSID of the object.
584 * preserved [I] Reserved. Set to NULL.
585 * ppunk [O] Address to store object into.
589 * Failure: HRESULT code.
591 HRESULT WINAPI DECLSPEC_HOTPATCH
GetActiveObject(REFCLSID rcid
,LPVOID preserved
,LPUNKNOWN
*ppunk
)
595 LPRUNNINGOBJECTTABLE runobtable
;
598 StringFromGUID2(rcid
,guidbuf
,39);
599 ret
= CreateItemMoniker(L
"!", guidbuf
, &moniker
);
602 ret
= GetRunningObjectTable(0,&runobtable
);
604 IMoniker_Release(moniker
);
607 ret
= IRunningObjectTable_GetObject(runobtable
,moniker
,ppunk
);
608 IRunningObjectTable_Release(runobtable
);
609 IMoniker_Release(moniker
);
614 /***********************************************************************
615 * OaBuildVersion [OLEAUT32.170]
617 * Get the Ole Automation build version.
626 * Known oleaut32.dll versions:
627 *| OLE Ver. Comments Date Build Ver.
628 *| -------- ------------------------- ---- ---------
629 *| OLE 2.1 NT 1993-95 10 3023
631 *| Win32s Ver 1.1e 20 4049
632 *| OLE 2.20 W95/NT 1993-96 20 4112
633 *| OLE 2.20 W95/NT 1993-96 20 4118
634 *| OLE 2.20 W95/NT 1993-96 20 4122
635 *| OLE 2.30 W95/NT 1993-98 30 4265
636 *| OLE 2.40 NT?? 1993-98 40 4267
637 *| OLE 2.40 W98 SE orig. file 1993-98 40 4275
638 *| OLE 2.40 W2K orig. file 1993-XX 40 4514
640 * Currently the versions returned are 2.20 for Win3.1, 2.30 for Win95 & NT 3.51,
641 * and 2.40 for all later versions. The build number is maximum, i.e. 0xffff.
643 ULONG WINAPI
OaBuildVersion(void)
645 switch(GetVersion() & 0x8000ffff) /* mask off build number */
647 case 0x80000a03: /* WIN31 */
648 return MAKELONG(0xffff, 20);
649 case 0x00003303: /* NT351 */
650 return MAKELONG(0xffff, 30);
651 case 0x80000004: /* WIN95; I'd like to use the "standard" w95 minor
652 version here (30), but as we still use w95
653 as default winver (which is good IMHO), I better
654 play safe and use the latest value for w95 for now.
655 Change this as soon as default winver gets changed
656 to something more recent */
657 case 0x80000a04: /* WIN98 */
658 case 0x00000004: /* NT40 */
659 case 0x00000005: /* W2K */
660 return MAKELONG(0xffff, 40);
661 case 0x00000105: /* WinXP */
662 case 0x00000006: /* Vista */
663 case 0x00000106: /* Win7 */
664 return MAKELONG(0xffff, 50);
666 FIXME("Version value not known yet. Please investigate it !\n");
667 return MAKELONG(0xffff, 40); /* for now return the same value as for w2k */
671 /******************************************************************************
672 * OleTranslateColor [OLEAUT32.421]
674 * Convert an OLE_COLOR to a COLORREF.
677 * clr [I] Color to convert
678 * hpal [I] Handle to a palette for the conversion
679 * pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok
682 * Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL.
683 * Failure: E_INVALIDARG, if any argument is invalid.
686 * Document the conversion rules.
688 HRESULT WINAPI
OleTranslateColor(
694 BYTE b
= HIBYTE(HIWORD(clr
));
696 TRACE("%#lx, %p, %p.\n", clr
, hpal
, pColorRef
);
699 * In case pColorRef is NULL, provide our own to simplify the code.
701 if (pColorRef
== NULL
)
702 pColorRef
= &colorref
;
709 *pColorRef
= PALETTERGB(GetRValue(clr
),
724 * Validate the palette index.
726 if (GetPaletteEntries(hpal
, LOWORD(clr
), 1, &pe
) == 0)
741 int index
= LOBYTE(LOWORD(clr
));
744 * Validate GetSysColor index.
746 if ((index
< COLOR_SCROLLBAR
) || (index
> COLOR_MENUBAR
))
749 *pColorRef
= GetSysColor(index
);
761 extern HRESULT WINAPI
OLEAUTPS_DllGetClassObject(REFCLSID
, REFIID
, LPVOID
*) DECLSPEC_HIDDEN
;
762 extern BOOL WINAPI
OLEAUTPS_DllMain(HINSTANCE
, DWORD
, LPVOID
) DECLSPEC_HIDDEN
;
763 extern HRESULT WINAPI
OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN
;
764 extern HRESULT WINAPI
OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN
;
766 extern HRESULT WINAPI
CreateProxyFromTypeInfo(ITypeInfo
*typeinfo
,
767 IUnknown
*outer
, REFIID iid
, IRpcProxyBuffer
**proxy
, void **obj
);
768 extern HRESULT WINAPI
CreateStubFromTypeInfo(ITypeInfo
*typeinfo
, REFIID iid
,
769 IUnknown
*server
, IRpcStubBuffer
**stub
);
771 struct ifacepsredirect_data
783 struct tlibredirect_data
797 static BOOL
actctx_get_typelib_module(REFIID iid
, WCHAR
*module
, DWORD len
)
799 struct ifacepsredirect_data
*iface
;
800 struct tlibredirect_data
*tlib
;
801 ACTCTX_SECTION_KEYED_DATA data
;
804 data
.cbSize
= sizeof(data
);
805 if (!FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
,
809 iface
= (struct ifacepsredirect_data
*)data
.lpData
;
810 if (!FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
,
811 &iface
->tlbid
, &data
))
814 tlib
= (struct tlibredirect_data
*)data
.lpData
;
815 ptrW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
817 if (tlib
->name_len
/sizeof(WCHAR
) >= len
)
819 ERR("need larger module buffer, %lu.\n", tlib
->name_len
);
823 memcpy(module
, ptrW
, tlib
->name_len
);
824 module
[tlib
->name_len
/sizeof(WCHAR
)] = 0;
828 static HRESULT
reg_get_typelib_module(REFIID iid
, WCHAR
*module
, DWORD len
)
830 REGSAM opposite
= (sizeof(void*) == 8) ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
831 char tlguid
[200], typelibkey
[316], interfacekey
[300], ver
[100], tlfn
[260];
832 DWORD tlguidlen
, verlen
, type
;
837 sprintf( interfacekey
, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
838 iid
->Data1
, iid
->Data2
, iid
->Data3
,
839 iid
->Data4
[0], iid
->Data4
[1], iid
->Data4
[2], iid
->Data4
[3],
840 iid
->Data4
[4], iid
->Data4
[5], iid
->Data4
[6], iid
->Data4
[7]
843 err
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,interfacekey
,0,KEY_READ
,&ikey
);
844 if (err
&& (opposite
== KEY_WOW64_32KEY
|| (IsWow64Process(GetCurrentProcess(), &is_wow64
)
846 err
= RegOpenKeyExA(HKEY_CLASSES_ROOT
,interfacekey
,0,KEY_READ
|opposite
,&ikey
);
850 ERR("No %s key found.\n", interfacekey
);
854 tlguidlen
= sizeof(tlguid
);
855 if (RegQueryValueExA(ikey
, NULL
, NULL
, &type
, (BYTE
*)tlguid
, &tlguidlen
))
857 ERR("Getting typelib guid failed.\n");
862 verlen
= sizeof(ver
);
863 if (RegQueryValueExA(ikey
, "Version", NULL
, &type
, (BYTE
*)ver
, &verlen
))
865 ERR("Could not get version value?\n");
872 sprintf(typelibkey
, "Typelib\\%s\\%s\\0\\win%u", tlguid
, ver
, sizeof(void *) == 8 ? 64 : 32);
873 tlfnlen
= sizeof(tlfn
);
874 if (RegQueryValueA(HKEY_CLASSES_ROOT
, typelibkey
, tlfn
, &tlfnlen
))
877 sprintf(typelibkey
, "Typelib\\%s\\%s\\0\\win32", tlguid
, ver
);
878 tlfnlen
= sizeof(tlfn
);
879 if (RegQueryValueA(HKEY_CLASSES_ROOT
, typelibkey
, tlfn
, &tlfnlen
))
882 ERR("Could not get typelib fn?\n");
888 MultiByteToWideChar(CP_ACP
, 0, tlfn
, -1, module
, len
);
892 static HRESULT
get_typeinfo_for_iid(REFIID iid
, ITypeInfo
**typeinfo
)
894 WCHAR module
[MAX_PATH
];
901 if (!actctx_get_typelib_module(iid
, module
, ARRAY_SIZE(module
)))
903 hr
= reg_get_typelib_module(iid
, module
, ARRAY_SIZE(module
));
908 hr
= LoadTypeLib(module
, &typelib
);
910 ERR("Failed to load typelib for %s, but it should be there.\n", debugstr_guid(iid
));
914 hr
= ITypeLib_GetTypeInfoOfGuid(typelib
, iid
, typeinfo
);
915 ITypeLib_Release(typelib
);
917 ERR("typelib does not contain info for %s\n", debugstr_guid(iid
));
922 static HRESULT WINAPI
dispatch_typelib_ps_QueryInterface(IPSFactoryBuffer
*iface
, REFIID iid
, void **out
)
924 if (IsEqualIID(iid
, &IID_IPSFactoryBuffer
) || IsEqualIID(iid
, &IID_IUnknown
))
930 FIXME("No interface for %s.\n", debugstr_guid(iid
));
932 return E_NOINTERFACE
;
935 static ULONG WINAPI
dispatch_typelib_ps_AddRef(IPSFactoryBuffer
*iface
)
940 static ULONG WINAPI
dispatch_typelib_ps_Release(IPSFactoryBuffer
*iface
)
945 static HRESULT
dispatch_create_proxy(IUnknown
*outer
, IRpcProxyBuffer
**proxy
, void **out
)
947 IPSFactoryBuffer
*factory
;
950 hr
= OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer
, &IID_IPSFactoryBuffer
, (void **)&factory
);
951 if (FAILED(hr
)) return hr
;
953 hr
= IPSFactoryBuffer_CreateProxy(factory
, outer
, &IID_IDispatch
, proxy
, out
);
954 IPSFactoryBuffer_Release(factory
);
958 static HRESULT WINAPI
dispatch_typelib_ps_CreateProxy(IPSFactoryBuffer
*iface
,
959 IUnknown
*outer
, REFIID iid
, IRpcProxyBuffer
**proxy
, void **out
)
965 if (IsEqualGUID(iid
, &IID_IDispatch
))
966 return dispatch_create_proxy(outer
, proxy
, out
);
968 hr
= get_typeinfo_for_iid(iid
, &typeinfo
);
969 if (FAILED(hr
)) return hr
;
971 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &attr
);
974 ITypeInfo_Release(typeinfo
);
978 if (attr
->typekind
== TKIND_INTERFACE
|| (attr
->wTypeFlags
& TYPEFLAG_FDUAL
))
979 hr
= CreateProxyFromTypeInfo(typeinfo
, outer
, iid
, proxy
, out
);
981 hr
= dispatch_create_proxy(outer
, proxy
, out
);
984 ERR("Failed to create proxy, hr %#lx.\n", hr
);
986 ITypeInfo_ReleaseTypeAttr(typeinfo
, attr
);
987 ITypeInfo_Release(typeinfo
);
991 static HRESULT
dispatch_create_stub(IUnknown
*server
, IRpcStubBuffer
**stub
)
993 IPSFactoryBuffer
*factory
;
996 hr
= OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer
, &IID_IPSFactoryBuffer
, (void **)&factory
);
997 if (FAILED(hr
)) return hr
;
999 hr
= IPSFactoryBuffer_CreateStub(factory
, &IID_IDispatch
, server
, stub
);
1000 IPSFactoryBuffer_Release(factory
);
1004 struct dispinterface_stub
1006 CInterfaceStubVtbl stub_vtbl
;
1007 CStdStubBuffer stub_buffer
;
1010 static struct dispinterface_stub
*impl_from_IRpcStubBuffer(IRpcStubBuffer
*iface
)
1012 return CONTAINING_RECORD(&iface
->lpVtbl
, struct dispinterface_stub
, stub_buffer
.lpVtbl
);
1015 static ULONG WINAPI
dispinterface_stub_Release(IRpcStubBuffer
*iface
)
1017 struct dispinterface_stub
*stub
= impl_from_IRpcStubBuffer(iface
);
1018 unsigned int refcount
= InterlockedDecrement(&stub
->stub_buffer
.RefCount
);
1020 TRACE("%p decreasing refcount to %u.\n", stub
, refcount
);
1024 /* Copied from NdrCStdStubBuffer_Release(), but supposedly incorrect
1025 * according to the comment there. */
1026 IRpcStubBuffer_Disconnect(iface
);
1033 extern const ExtendedProxyFileInfo oleaut32_oaidl_ProxyFileInfo
;
1035 static const CInterfaceStubVtbl
*find_idispatch_stub_vtbl(void)
1037 CInterfaceStubVtbl
*const *vtbl
;
1039 for (vtbl
= oleaut32_oaidl_ProxyFileInfo
.pStubVtblList
; *vtbl
; ++vtbl
)
1041 if (IsEqualGUID((*vtbl
)->header
.piid
, &IID_IDispatch
))
1049 /* Normal dispinterfaces have an IID specified by the IDL compiler as DIID_*,
1050 * but are otherwise identical to IDispatch. Unfortunately, such interfaces may
1051 * not actually support IDispatch in QueryInterface.
1053 * This becomes a problem, since CreateStub() was designed such that, for some
1054 * reason, the caller need not actually pass the interface matching "iid". As
1055 * such the standard rpcrt4 implementation will query the server for the
1058 * This means that we cannot just pass IID_IDispatch with the object, even
1059 * though it is in theory an IDispatch. However, while the standard stub
1060 * constructor is not exported from rpcrt4, all of the vtbl methods are, and
1061 * the type is public, so we *can* manually create it ourselves, bypassing the
1062 * QueryInterface check.
1064 * This relies on some rpcrt4 implementation details.
1066 static HRESULT
dispinterface_create_stub(IUnknown
*server
, const GUID
*iid
, IRpcStubBuffer
**stub
)
1068 const CInterfaceStubVtbl
*stub_vtbl
= find_idispatch_stub_vtbl();
1069 struct dispinterface_stub
*object
;
1073 if (!(object
= calloc(1, sizeof(*object
))))
1074 return E_OUTOFMEMORY
;
1076 /* It's possible we can just assume that "server" is already the
1077 * dispinterface type—we don't have tests for this—but since rpcrt4 queries
1078 * (which we do have tests for) it makes sense for us to match that
1080 if (FAILED(hr
= IUnknown_QueryInterface(server
, iid
, &dispatch
)))
1082 ERR("Object does not support interface %s.\n", debugstr_guid(iid
));
1087 object
->stub_vtbl
.header
= stub_vtbl
->header
;
1088 object
->stub_vtbl
.Vtbl
.QueryInterface
= CStdStubBuffer_QueryInterface
;
1089 object
->stub_vtbl
.Vtbl
.AddRef
= CStdStubBuffer_AddRef
;
1090 object
->stub_vtbl
.Vtbl
.Release
= dispinterface_stub_Release
;
1091 object
->stub_vtbl
.Vtbl
.Connect
= CStdStubBuffer_Connect
;
1092 object
->stub_vtbl
.Vtbl
.Disconnect
= CStdStubBuffer_Disconnect
;
1093 object
->stub_vtbl
.Vtbl
.Invoke
= CStdStubBuffer_Invoke
;
1094 object
->stub_vtbl
.Vtbl
.IsIIDSupported
= CStdStubBuffer_IsIIDSupported
;
1095 object
->stub_vtbl
.Vtbl
.CountRefs
= CStdStubBuffer_CountRefs
;
1096 object
->stub_vtbl
.Vtbl
.DebugServerQueryInterface
= CStdStubBuffer_DebugServerQueryInterface
;
1097 object
->stub_vtbl
.Vtbl
.DebugServerRelease
= CStdStubBuffer_DebugServerRelease
;
1098 object
->stub_buffer
.lpVtbl
= &object
->stub_vtbl
.Vtbl
;
1099 object
->stub_buffer
.RefCount
= 1;
1100 object
->stub_buffer
.pvServerObject
= dispatch
;
1101 /* rpcrt4 will also fill pPSFactory, but it never uses it except in the
1102 * Release method (which we reimplement). It's only to keep a reference to
1103 * the module to implement NdrDllCanUnloadNow(). We use the default
1104 * DllCanUnloadNow() from winecrt0, which always returns S_FALSE, so don't
1105 * bother filling pPSFactory. */
1107 TRACE("Created stub %p.\n", object
);
1108 *stub
= (IRpcStubBuffer
*)&object
->stub_buffer
.lpVtbl
;
1112 static HRESULT WINAPI
dispatch_typelib_ps_CreateStub(IPSFactoryBuffer
*iface
,
1113 REFIID iid
, IUnknown
*server
, IRpcStubBuffer
**stub
)
1115 ITypeInfo
*typeinfo
;
1119 if (IsEqualGUID(iid
, &IID_IDispatch
))
1120 return dispatch_create_stub(server
, stub
);
1122 hr
= get_typeinfo_for_iid(iid
, &typeinfo
);
1123 if (FAILED(hr
)) return hr
;
1125 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &attr
);
1128 ITypeInfo_Release(typeinfo
);
1132 if (attr
->typekind
== TKIND_INTERFACE
|| (attr
->wTypeFlags
& TYPEFLAG_FDUAL
))
1133 hr
= CreateStubFromTypeInfo(typeinfo
, iid
, server
, stub
);
1135 hr
= dispinterface_create_stub(server
, iid
, stub
);
1138 ERR("Failed to create stub, hr %#lx.\n", hr
);
1140 ITypeInfo_ReleaseTypeAttr(typeinfo
, attr
);
1141 ITypeInfo_Release(typeinfo
);
1145 static const IPSFactoryBufferVtbl dispatch_typelib_ps_vtbl
=
1147 dispatch_typelib_ps_QueryInterface
,
1148 dispatch_typelib_ps_AddRef
,
1149 dispatch_typelib_ps_Release
,
1150 dispatch_typelib_ps_CreateProxy
,
1151 dispatch_typelib_ps_CreateStub
,
1154 static IPSFactoryBuffer dispatch_typelib_ps
= { &dispatch_typelib_ps_vtbl
};
1156 extern void _get_STDFONT_CF(LPVOID
*);
1157 extern void _get_STDPIC_CF(LPVOID
*);
1159 /***********************************************************************
1160 * DllGetClassObject (OLEAUT32.@)
1162 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID iid
, LPVOID
*ppv
)
1165 if (IsEqualGUID(rclsid
,&CLSID_StdFont
)) {
1166 if (IsEqualGUID(iid
,&IID_IClassFactory
)) {
1167 _get_STDFONT_CF(ppv
);
1168 IClassFactory_AddRef((IClassFactory
*)*ppv
);
1172 if (IsEqualGUID(rclsid
,&CLSID_StdPicture
)) {
1173 if (IsEqualGUID(iid
,&IID_IClassFactory
)) {
1174 _get_STDPIC_CF(ppv
);
1175 IClassFactory_AddRef((IClassFactory
*)*ppv
);
1180 if (IsEqualGUID(rclsid
, &CLSID_PSDispatch
) || IsEqualGUID(rclsid
, &CLSID_PSOAInterface
))
1181 return IPSFactoryBuffer_QueryInterface(&dispatch_typelib_ps
, iid
, ppv
);
1183 if (IsEqualCLSID(rclsid
, &CLSID_PSTypeComp
) ||
1184 IsEqualCLSID(rclsid
, &CLSID_PSTypeInfo
) ||
1185 IsEqualCLSID(rclsid
, &CLSID_PSTypeLib
) ||
1186 IsEqualCLSID(rclsid
, &CLSID_PSDispatch
) ||
1187 IsEqualCLSID(rclsid
, &CLSID_PSEnumVariant
))
1188 return OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer
, iid
, ppv
);
1190 return OLEAUTPS_DllGetClassObject(rclsid
, iid
, ppv
);
1193 /*****************************************************************************
1194 * DllMain [OLEAUT32.@]
1196 BOOL WINAPI
DllMain(HINSTANCE hInstDll
, DWORD fdwReason
, LPVOID lpvReserved
)
1198 if(fdwReason
== DLL_PROCESS_ATTACH
)
1199 bstr_cache_enabled
= !GetEnvironmentVariableW(L
"oanocache", NULL
, 0);
1201 return OLEAUTPS_DllMain( hInstDll
, fdwReason
, lpvReserved
);
1204 /***********************************************************************
1205 * DllRegisterServer (OLEAUT32.@)
1207 HRESULT WINAPI
DllRegisterServer(void)
1209 return OLEAUTPS_DllRegisterServer();
1212 /***********************************************************************
1213 * DllUnregisterServer (OLEAUT32.@)
1215 HRESULT WINAPI
DllUnregisterServer(void)
1217 return OLEAUTPS_DllUnregisterServer();
1220 /***********************************************************************
1221 * OleIconToCursor (OLEAUT32.415)
1223 HCURSOR WINAPI
OleIconToCursor( HINSTANCE hinstExe
, HICON hIcon
)
1225 FIXME("(%p,%p), partially implemented.\n",hinstExe
,hIcon
);
1226 /* FIXME: make an extended conversation from HICON to HCURSOR */
1227 return CopyCursor(hIcon
);
1230 /***********************************************************************
1231 * GetAltMonthNames (OLEAUT32.@)
1233 HRESULT WINAPI
GetAltMonthNames(LCID lcid
, LPOLESTR
**str
)
1235 static const WCHAR
*arabic_hijri
[] =
1237 L
"\x0645\x062d\x0631\x0645",
1238 L
"\x0635\x0641\x0631",
1239 L
"\x0631\x0628\x064a\x0639 \x0627\x0644\x0627\x0648\x0644",
1240 L
"\x0631\x0628\x064a\x0639 \x0627\x0644\x062b\x0627\x0646\x064a",
1241 L
"\x062c\x0645\x0627\x062f\x0649 \x0627\x0644\x0627\x0648\x0644\x0649",
1242 L
"\x062c\x0645\x0627\x062f\x0649 \x0627\x0644\x062b\x0627\x0646\x064a\x0629",
1243 L
"\x0631\x062c\x0628",
1244 L
"\x0634\x0639\x0628\x0627\x0646",
1245 L
"\x0631\x0645\x0636\x0627\x0646",
1246 L
"\x0634\x0648\x0627\x0643",
1247 L
"\x0630\x0648 \x0627\x0644\x0642\x0639\x062f\x0629",
1248 L
"\x0630\x0648 \x0627\x0644\x062d\x062c\x0629",
1252 static const WCHAR
*polish_genitive_names
[] =
1263 L
"pa\x017a" "dziernika",
1269 static const WCHAR
*russian_genitive_names
[] =
1271 L
"\x044f\x043d\x0432\x0430\x0440\x044f",
1272 L
"\x0444\x0435\x0432\x0440\x0430\x043b\x044f",
1273 L
"\x043c\x0430\x0440\x0442\x0430",
1274 L
"\x0430\x043f\x0440\x0435\x043b\x044f",
1275 L
"\x043c\x0430\x044f",
1276 L
"\x0438\x044e\x043d\x044f",
1277 L
"\x0438\x044e\x043b\x044f",
1278 L
"\x0430\x0432\x0433\x0443\x0441\x0442\x0430",
1279 L
"\x0441\x0435\x043d\x0442\x044f\x0431\x0440\x044f",
1280 L
"\x043e\x043a\x0442\x044f\x0431\x0440\x044f",
1281 L
"\x043d\x043e\x044f\x0431\x0440\x044f",
1282 L
"\x0434\x0435\x043a\x0430\x0431\x0440\x044f",
1286 TRACE("%#lx, %p.\n", lcid
, str
);
1288 if (PRIMARYLANGID(LANGIDFROMLCID(lcid
)) == LANG_ARABIC
)
1289 *str
= (LPOLESTR
*)arabic_hijri
;
1290 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid
)) == LANG_POLISH
)
1291 *str
= (LPOLESTR
*)polish_genitive_names
;
1292 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid
)) == LANG_RUSSIAN
)
1293 *str
= (LPOLESTR
*)russian_genitive_names
;