ucrtbase: Store sse and x87 exception in fexcept_t.
[wine.git] / dlls / ole32 / compobj.c
blobc40d8d03b2dbcccae82358374ef0fabb7f4a7b27
1 /*
2 * COMPOBJ library
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 Justin Bradford
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Sylvain St-Germain
8 * Copyright 2002 Marcus Meissner
9 * Copyright 2004 Mike Hearn
10 * Copyright 2005-2006 Robert Shearman (for CodeWeavers)
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Note
27 * 1. COINIT_MULTITHREADED is 0; it is the lack of COINIT_APARTMENTTHREADED
28 * Therefore do not test against COINIT_MULTITHREADED
30 * TODO list: (items bunched together depend on each other)
32 * - Implement the OXID resolver so we don't need magic endpoint names for
33 * clients and servers to meet up
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <assert.h>
42 #define COBJMACROS
43 #define NONAMELESSUNION
45 #include "ntstatus.h"
46 #define WIN32_NO_STATUS
47 #include "windef.h"
48 #include "winbase.h"
49 #include "winerror.h"
50 #include "winreg.h"
51 #include "winuser.h"
52 #define USE_COM_CONTEXT_DEF
53 #include "objbase.h"
54 #include "ole2.h"
55 #include "ole2ver.h"
56 #include "ctxtcall.h"
57 #include "dde.h"
58 #include "servprov.h"
60 #include "initguid.h"
61 #include "compobj_private.h"
62 #include "moniker.h"
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(ole);
68 /****************************************************************************
69 * This section defines variables internal to the COM module.
72 enum comclass_miscfields
74 MiscStatus = 1,
75 MiscStatusIcon = 2,
76 MiscStatusContent = 4,
77 MiscStatusThumbnail = 8,
78 MiscStatusDocPrint = 16
81 struct comclassredirect_data
83 ULONG size;
84 ULONG flags;
85 DWORD model;
86 GUID clsid;
87 GUID alias;
88 GUID clsid2;
89 GUID tlbid;
90 ULONG name_len;
91 ULONG name_offset;
92 ULONG progid_len;
93 ULONG progid_offset;
94 ULONG clrdata_len;
95 ULONG clrdata_offset;
96 DWORD miscstatus;
97 DWORD miscstatuscontent;
98 DWORD miscstatusthumbnail;
99 DWORD miscstatusicon;
100 DWORD miscstatusdocprint;
103 struct ifacepsredirect_data
105 ULONG size;
106 DWORD mask;
107 GUID iid;
108 ULONG nummethods;
109 GUID tlbid;
110 GUID base;
111 ULONG name_len;
112 ULONG name_offset;
115 struct progidredirect_data
117 ULONG size;
118 DWORD reserved;
119 ULONG clsid_offset;
122 enum class_reg_data_origin
124 CLASS_REG_ACTCTX,
125 CLASS_REG_REGISTRY,
128 struct class_reg_data
130 enum class_reg_data_origin origin;
131 union
133 struct
135 const WCHAR *module_name;
136 DWORD threading_model;
137 HANDLE hactctx;
138 } actctx;
139 HKEY hkey;
140 } u;
143 static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
145 switch (aspect)
147 case DVASPECT_CONTENT:
148 return MiscStatusContent;
149 case DVASPECT_THUMBNAIL:
150 return MiscStatusThumbnail;
151 case DVASPECT_ICON:
152 return MiscStatusIcon;
153 case DVASPECT_DOCPRINT:
154 return MiscStatusDocPrint;
155 default:
156 return MiscStatus;
160 BOOL actctx_get_miscstatus(const CLSID *clsid, DWORD aspect, DWORD *status)
162 ACTCTX_SECTION_KEYED_DATA data;
164 data.cbSize = sizeof(data);
165 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
166 clsid, &data))
168 struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData;
169 enum comclass_miscfields misc = dvaspect_to_miscfields(aspect);
170 ULONG miscmask = (comclass->flags >> 8) & 0xff;
172 if (!(miscmask & misc))
174 if (!(miscmask & MiscStatus))
176 *status = 0;
177 return TRUE;
179 misc = MiscStatus;
182 switch (misc)
184 case MiscStatus:
185 *status = comclass->miscstatus;
186 break;
187 case MiscStatusIcon:
188 *status = comclass->miscstatusicon;
189 break;
190 case MiscStatusContent:
191 *status = comclass->miscstatuscontent;
192 break;
193 case MiscStatusThumbnail:
194 *status = comclass->miscstatusthumbnail;
195 break;
196 case MiscStatusDocPrint:
197 *status = comclass->miscstatusdocprint;
198 break;
199 default:
203 return TRUE;
205 else
206 return FALSE;
209 /* wrapper for NtCreateKey that creates the key recursively if necessary */
210 static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
212 NTSTATUS status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, NULL, 0, NULL );
214 if (status == STATUS_OBJECT_NAME_NOT_FOUND)
216 HANDLE subkey, root = attr->RootDirectory;
217 WCHAR *buffer = attr->ObjectName->Buffer;
218 DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
219 UNICODE_STRING str;
221 while (i < len && buffer[i] != '\\') i++;
222 if (i == len) return status;
224 attrs = attr->Attributes;
225 attr->ObjectName = &str;
227 while (i < len)
229 str.Buffer = buffer + pos;
230 str.Length = (i - pos) * sizeof(WCHAR);
231 status = NtCreateKey( &subkey, access, attr, 0, NULL, 0, NULL );
232 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
233 if (status) return status;
234 attr->RootDirectory = subkey;
235 while (i < len && buffer[i] == '\\') i++;
236 pos = i;
237 while (i < len && buffer[i] != '\\') i++;
239 str.Buffer = buffer + pos;
240 str.Length = (i - pos) * sizeof(WCHAR);
241 attr->Attributes = attrs;
242 status = NtCreateKey( (PHANDLE)retkey, access, attr, 0, NULL, 0, NULL );
243 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
245 return status;
248 static HKEY classes_root_hkey;
250 /* create the special HKEY_CLASSES_ROOT key */
251 static HKEY create_classes_root_hkey(DWORD access)
253 HKEY hkey, ret = 0;
254 OBJECT_ATTRIBUTES attr;
255 UNICODE_STRING name;
257 attr.Length = sizeof(attr);
258 attr.RootDirectory = 0;
259 attr.ObjectName = &name;
260 attr.Attributes = 0;
261 attr.SecurityDescriptor = NULL;
262 attr.SecurityQualityOfService = NULL;
263 RtlInitUnicodeString( &name, L"\\Registry\\Machine\\Software\\Classes" );
264 if (create_key( &hkey, access, &attr )) return 0;
265 TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
267 if (!(access & KEY_WOW64_64KEY))
269 if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
270 ret = hkey;
271 else
272 NtClose( hkey ); /* somebody beat us to it */
274 else
275 ret = hkey;
276 return ret;
279 /* map the hkey from special root to normal key if necessary */
280 static inline HKEY get_classes_root_hkey( HKEY hkey, REGSAM access )
282 HKEY ret = hkey;
283 const BOOL is_win64 = sizeof(void*) > sizeof(int);
284 const BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY);
286 if (hkey == HKEY_CLASSES_ROOT &&
287 ((access & KEY_WOW64_64KEY) || !(ret = classes_root_hkey)))
288 ret = create_classes_root_hkey(MAXIMUM_ALLOWED | (access & KEY_WOW64_64KEY));
289 if (force_wow32 && ret && ret == classes_root_hkey)
291 access &= ~KEY_WOW64_32KEY;
292 if (create_classes_key(classes_root_hkey, L"Wow6432Node", access, &hkey))
293 return 0;
294 ret = hkey;
297 return ret;
300 LSTATUS create_classes_key( HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey )
302 OBJECT_ATTRIBUTES attr;
303 UNICODE_STRING nameW;
305 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
307 attr.Length = sizeof(attr);
308 attr.RootDirectory = hkey;
309 attr.ObjectName = &nameW;
310 attr.Attributes = 0;
311 attr.SecurityDescriptor = NULL;
312 attr.SecurityQualityOfService = NULL;
313 RtlInitUnicodeString( &nameW, name );
315 return RtlNtStatusToDosError( create_key( retkey, access, &attr ) );
318 LSTATUS open_classes_key( HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey )
320 OBJECT_ATTRIBUTES attr;
321 UNICODE_STRING nameW;
323 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
325 attr.Length = sizeof(attr);
326 attr.RootDirectory = hkey;
327 attr.ObjectName = &nameW;
328 attr.Attributes = 0;
329 attr.SecurityDescriptor = NULL;
330 attr.SecurityQualityOfService = NULL;
331 RtlInitUnicodeString( &nameW, name );
333 return RtlNtStatusToDosError( NtOpenKey( (HANDLE *)retkey, access, &attr ) );
336 /******************************************************************************
337 * Implementation of the manual reset event object. (CLSID_ManualResetEvent)
340 typedef struct ManualResetEvent {
341 ISynchronize ISynchronize_iface;
342 ISynchronizeHandle ISynchronizeHandle_iface;
343 LONG ref;
344 HANDLE event;
345 } MREImpl;
347 static inline MREImpl *impl_from_ISynchronize(ISynchronize *iface)
349 return CONTAINING_RECORD(iface, MREImpl, ISynchronize_iface);
352 static HRESULT WINAPI ISynchronize_fnQueryInterface(ISynchronize *iface, REFIID riid, void **ppv)
354 MREImpl *This = impl_from_ISynchronize(iface);
356 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppv);
358 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISynchronize)) {
359 *ppv = &This->ISynchronize_iface;
360 }else if(IsEqualGUID(riid, &IID_ISynchronizeHandle)) {
361 *ppv = &This->ISynchronizeHandle_iface;
362 }else {
363 ERR("Unknown interface %s requested.\n", debugstr_guid(riid));
364 *ppv = NULL;
365 return E_NOINTERFACE;
368 IUnknown_AddRef((IUnknown*)*ppv);
369 return S_OK;
372 static ULONG WINAPI ISynchronize_fnAddRef(ISynchronize *iface)
374 MREImpl *This = impl_from_ISynchronize(iface);
375 LONG ref = InterlockedIncrement(&This->ref);
376 TRACE("%p - ref %d\n", This, ref);
378 return ref;
381 static ULONG WINAPI ISynchronize_fnRelease(ISynchronize *iface)
383 MREImpl *This = impl_from_ISynchronize(iface);
384 LONG ref = InterlockedDecrement(&This->ref);
385 TRACE("%p - ref %d\n", This, ref);
387 if(!ref)
389 CloseHandle(This->event);
390 HeapFree(GetProcessHeap(), 0, This);
393 return ref;
396 static HRESULT WINAPI ISynchronize_fnWait(ISynchronize *iface, DWORD dwFlags, DWORD dwMilliseconds)
398 MREImpl *This = impl_from_ISynchronize(iface);
399 UINT index;
400 TRACE("%p (%08x, %08x)\n", This, dwFlags, dwMilliseconds);
401 return CoWaitForMultipleHandles(dwFlags, dwMilliseconds, 1, &This->event, &index);
404 static HRESULT WINAPI ISynchronize_fnSignal(ISynchronize *iface)
406 MREImpl *This = impl_from_ISynchronize(iface);
407 TRACE("%p\n", This);
408 SetEvent(This->event);
409 return S_OK;
412 static HRESULT WINAPI ISynchronize_fnReset(ISynchronize *iface)
414 MREImpl *This = impl_from_ISynchronize(iface);
415 TRACE("%p\n", This);
416 ResetEvent(This->event);
417 return S_OK;
420 static ISynchronizeVtbl vt_ISynchronize = {
421 ISynchronize_fnQueryInterface,
422 ISynchronize_fnAddRef,
423 ISynchronize_fnRelease,
424 ISynchronize_fnWait,
425 ISynchronize_fnSignal,
426 ISynchronize_fnReset
429 static inline MREImpl *impl_from_ISynchronizeHandle(ISynchronizeHandle *iface)
431 return CONTAINING_RECORD(iface, MREImpl, ISynchronizeHandle_iface);
434 static HRESULT WINAPI SynchronizeHandle_QueryInterface(ISynchronizeHandle *iface, REFIID riid, void **ppv)
436 MREImpl *This = impl_from_ISynchronizeHandle(iface);
437 return ISynchronize_QueryInterface(&This->ISynchronize_iface, riid, ppv);
440 static ULONG WINAPI SynchronizeHandle_AddRef(ISynchronizeHandle *iface)
442 MREImpl *This = impl_from_ISynchronizeHandle(iface);
443 return ISynchronize_AddRef(&This->ISynchronize_iface);
446 static ULONG WINAPI SynchronizeHandle_Release(ISynchronizeHandle *iface)
448 MREImpl *This = impl_from_ISynchronizeHandle(iface);
449 return ISynchronize_Release(&This->ISynchronize_iface);
452 static HRESULT WINAPI SynchronizeHandle_GetHandle(ISynchronizeHandle *iface, HANDLE *ph)
454 MREImpl *This = impl_from_ISynchronizeHandle(iface);
456 *ph = This->event;
457 return S_OK;
460 static const ISynchronizeHandleVtbl SynchronizeHandleVtbl = {
461 SynchronizeHandle_QueryInterface,
462 SynchronizeHandle_AddRef,
463 SynchronizeHandle_Release,
464 SynchronizeHandle_GetHandle
467 HRESULT WINAPI ManualResetEvent_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **ppv)
469 MREImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MREImpl));
470 HRESULT hr;
472 if (outer)
473 FIXME("Aggregation not implemented.\n");
475 This->ref = 1;
476 This->ISynchronize_iface.lpVtbl = &vt_ISynchronize;
477 This->ISynchronizeHandle_iface.lpVtbl = &SynchronizeHandleVtbl;
478 This->event = CreateEventW(NULL, TRUE, FALSE, NULL);
480 hr = ISynchronize_QueryInterface(&This->ISynchronize_iface, iid, ppv);
481 ISynchronize_Release(&This->ISynchronize_iface);
482 return hr;
485 /******************************************************************************
486 * CoBuildVersion [OLE32.@]
488 * Gets the build version of the DLL.
490 * PARAMS
492 * RETURNS
493 * Current build version, hiword is majornumber, loword is minornumber
495 DWORD WINAPI CoBuildVersion(void)
497 TRACE("Returning version %d, build %d.\n", rmm, rup);
498 return (rmm<<16)+rup;
501 /******************************************************************************
502 * CoInitialize [OLE32.@]
504 * Initializes the COM libraries by calling CoInitializeEx with
505 * COINIT_APARTMENTTHREADED, ie it enters a STA thread.
507 * PARAMS
508 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
510 * RETURNS
511 * Success: S_OK if not already initialized, S_FALSE otherwise.
512 * Failure: HRESULT code.
514 * SEE ALSO
515 * CoInitializeEx
517 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
520 * Just delegate to the newer method.
522 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
525 /* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */
526 HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey)
528 WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(L"CLSID\\") - 1];
529 LONG res;
530 HKEY key;
532 lstrcpyW(path, L"CLSID\\");
533 StringFromGUID2(clsid, path + lstrlenW(L"CLSID\\"), CHARS_IN_GUID);
534 res = open_classes_key(HKEY_CLASSES_ROOT, path, keyname ? KEY_READ : access, &key);
535 if (res == ERROR_FILE_NOT_FOUND)
536 return REGDB_E_CLASSNOTREG;
537 else if (res != ERROR_SUCCESS)
538 return REGDB_E_READREGDB;
540 if (!keyname)
542 *subkey = key;
543 return S_OK;
546 res = open_classes_key(key, keyname, access, subkey);
547 RegCloseKey(key);
548 if (res == ERROR_FILE_NOT_FOUND)
549 return REGDB_E_KEYMISSING;
550 else if (res != ERROR_SUCCESS)
551 return REGDB_E_READREGDB;
553 return S_OK;
556 /***********************************************************************
557 * CoLoadLibrary (OLE32.@)
559 * Loads a library.
561 * PARAMS
562 * lpszLibName [I] Path to library.
563 * bAutoFree [I] Whether the library should automatically be freed.
565 * RETURNS
566 * Success: Handle to loaded library.
567 * Failure: NULL.
569 * SEE ALSO
570 * CoFreeLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
572 HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
574 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
576 return LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
579 /***********************************************************************
580 * CoFreeLibrary [OLE32.@]
582 * Unloads a library from memory.
584 * PARAMS
585 * hLibrary [I] Handle to library to unload.
587 * RETURNS
588 * Nothing
590 * SEE ALSO
591 * CoLoadLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
593 void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
595 FreeLibrary(hLibrary);
599 /***********************************************************************
600 * CoFreeAllLibraries [OLE32.@]
602 * Function for backwards compatibility only. Does nothing.
604 * RETURNS
605 * Nothing.
607 * SEE ALSO
608 * CoLoadLibrary, CoFreeLibrary, CoFreeUnusedLibraries
610 void WINAPI CoFreeAllLibraries(void)
612 /* NOP */
615 /***********************************************************************
616 * CoGetState [OLE32.@]
618 * Retrieves the thread state object previously stored by CoSetState().
620 * PARAMS
621 * ppv [I] Address where pointer to object will be stored.
623 * RETURNS
624 * Success: S_OK.
625 * Failure: E_OUTOFMEMORY.
627 * NOTES
628 * Crashes on all invalid ppv addresses, including NULL.
629 * If the function returns a non-NULL object then the caller must release its
630 * reference on the object when the object is no longer required.
632 * SEE ALSO
633 * CoSetState().
635 HRESULT WINAPI CoGetState(IUnknown ** ppv)
637 struct oletls *info = COM_CurrentInfo();
638 if (!info) return E_OUTOFMEMORY;
640 *ppv = NULL;
642 if (info->state)
644 IUnknown_AddRef(info->state);
645 *ppv = info->state;
646 TRACE("apt->state=%p\n", info->state);
649 return S_OK;
652 /***********************************************************************
653 * CoSetState [OLE32.@]
655 * Sets the thread state object.
657 * PARAMS
658 * pv [I] Pointer to state object to be stored.
660 * NOTES
661 * The system keeps a reference on the object while the object stored.
663 * RETURNS
664 * Success: S_OK.
665 * Failure: E_OUTOFMEMORY.
667 HRESULT WINAPI CoSetState(IUnknown * pv)
669 struct oletls *info = COM_CurrentInfo();
670 if (!info) return E_OUTOFMEMORY;
672 if (pv) IUnknown_AddRef(pv);
674 if (info->state)
676 TRACE("-- release %p now\n", info->state);
677 IUnknown_Release(info->state);
680 info->state = pv;
682 return S_OK;
686 /******************************************************************************
687 * CoTreatAsClass [OLE32.@]
689 * Sets the TreatAs value of a class.
691 * PARAMS
692 * clsidOld [I] Class to set TreatAs value on.
693 * clsidNew [I] The class the clsidOld should be treated as.
695 * RETURNS
696 * Success: S_OK.
697 * Failure: HRESULT code.
699 * SEE ALSO
700 * CoGetTreatAsClass
702 HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
704 HKEY hkey = NULL;
705 WCHAR szClsidNew[CHARS_IN_GUID];
706 HRESULT res = S_OK;
707 WCHAR auto_treat_as[CHARS_IN_GUID];
708 LONG auto_treat_as_size = sizeof(auto_treat_as);
709 CLSID id;
711 res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
712 if (FAILED(res))
713 goto done;
715 if (IsEqualGUID( clsidOld, clsidNew ))
717 if (!RegQueryValueW(hkey, L"AutoTreatAs", auto_treat_as, &auto_treat_as_size) &&
718 CLSIDFromString(auto_treat_as, &id) == S_OK)
720 if (RegSetValueW(hkey, L"TreatAs", REG_SZ, auto_treat_as, sizeof(auto_treat_as)))
722 res = REGDB_E_WRITEREGDB;
723 goto done;
726 else
728 if (RegDeleteKeyW(hkey, L"TreatAs"))
729 res = REGDB_E_WRITEREGDB;
730 goto done;
733 else
735 if(IsEqualGUID(clsidNew, &CLSID_NULL)){
736 RegDeleteKeyW(hkey, L"TreatAs");
737 }else{
738 if(!StringFromGUID2(clsidNew, szClsidNew, ARRAY_SIZE(szClsidNew))){
739 WARN("StringFromGUID2 failed\n");
740 res = E_FAIL;
741 goto done;
744 if (RegSetValueW(hkey, L"TreatAs", REG_SZ, szClsidNew, sizeof(szClsidNew)) != ERROR_SUCCESS){
745 WARN("RegSetValue failed\n");
746 res = REGDB_E_WRITEREGDB;
747 goto done;
752 done:
753 if (hkey) RegCloseKey(hkey);
754 return res;
757 /***********************************************************************
758 * CoIsOle1Class [OLE32.@]
760 * Determines whether the specified class an OLE v1 class.
762 * PARAMS
763 * clsid [I] Class to test.
765 * RETURNS
766 * TRUE if the class is an OLE v1 class, or FALSE otherwise.
768 BOOL WINAPI CoIsOle1Class(REFCLSID clsid)
770 FIXME("%s\n", debugstr_guid(clsid));
771 return FALSE;
774 /***********************************************************************
775 * IsEqualGUID [OLE32.@]
777 * Compares two Unique Identifiers.
779 * PARAMS
780 * rguid1 [I] The first GUID to compare.
781 * rguid2 [I] The other GUID to compare.
783 * RETURNS
784 * TRUE if equal
786 #undef IsEqualGUID
787 BOOL WINAPI IsEqualGUID(
788 REFGUID rguid1,
789 REFGUID rguid2)
791 return !memcmp(rguid1,rguid2,sizeof(GUID));
794 /***********************************************************************
795 * CoAllowSetForegroundWindow [OLE32.@]
798 HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved)
800 FIXME("(%p, %p): stub\n", pUnk, pvReserved);
801 return S_OK;
804 /***********************************************************************
805 * CoGetObject [OLE32.@]
807 * Gets the object named by converting the name to a moniker and binding to it.
809 * PARAMS
810 * pszName [I] String representing the object.
811 * pBindOptions [I] Parameters affecting the binding to the named object.
812 * riid [I] Interface to bind to on the object.
813 * ppv [O] On output, the interface riid of the object represented
814 * by pszName.
816 * RETURNS
817 * Success: S_OK.
818 * Failure: HRESULT code.
820 * SEE ALSO
821 * MkParseDisplayName.
823 HRESULT WINAPI CoGetObject(LPCWSTR pszName, BIND_OPTS *pBindOptions,
824 REFIID riid, void **ppv)
826 IBindCtx *pbc;
827 HRESULT hr;
829 *ppv = NULL;
831 hr = CreateBindCtx(0, &pbc);
832 if (SUCCEEDED(hr))
834 if (pBindOptions)
835 hr = IBindCtx_SetBindOptions(pbc, pBindOptions);
837 if (SUCCEEDED(hr))
839 ULONG chEaten;
840 IMoniker *pmk;
842 hr = MkParseDisplayName(pbc, pszName, &chEaten, &pmk);
843 if (SUCCEEDED(hr))
845 hr = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppv);
846 IMoniker_Release(pmk);
850 IBindCtx_Release(pbc);
852 return hr;
855 /* Returns expanded dll path from the registry or activation context. */
856 static BOOL get_object_dll_path(const struct class_reg_data *regdata, WCHAR *dst, DWORD dstlen)
858 DWORD ret;
860 if (regdata->origin == CLASS_REG_REGISTRY)
862 DWORD keytype;
863 WCHAR src[MAX_PATH];
864 DWORD dwLength = dstlen * sizeof(WCHAR);
866 if( (ret = RegQueryValueExW(regdata->u.hkey, NULL, NULL, &keytype, (BYTE*)src, &dwLength)) == ERROR_SUCCESS ) {
867 if (keytype == REG_EXPAND_SZ) {
868 if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA;
869 } else {
870 const WCHAR *quote_start;
871 quote_start = wcschr(src, '\"');
872 if (quote_start) {
873 const WCHAR *quote_end = wcschr(quote_start + 1, '\"');
874 if (quote_end) {
875 memmove(src, quote_start + 1,
876 (quote_end - quote_start - 1) * sizeof(WCHAR));
877 src[quote_end - quote_start - 1] = '\0';
880 lstrcpynW(dst, src, dstlen);
883 return !ret;
885 else
887 ULONG_PTR cookie;
889 *dst = 0;
890 ActivateActCtx(regdata->u.actctx.hactctx, &cookie);
891 ret = SearchPathW(NULL, regdata->u.actctx.module_name, L".dll", dstlen, dst, NULL);
892 DeactivateActCtx(0, cookie);
893 return *dst != 0;
897 HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
899 HKEY hkey;
900 HRESULT hres;
902 hres = COM_OpenKeyForCLSID(rclsid, L"InprocHandler32", KEY_READ, &hkey);
903 if (SUCCEEDED(hres))
905 struct class_reg_data regdata;
906 WCHAR dllpath[MAX_PATH+1];
908 regdata.u.hkey = hkey;
909 regdata.origin = CLASS_REG_REGISTRY;
911 if (get_object_dll_path(&regdata, dllpath, ARRAY_SIZE(dllpath)))
913 if (!wcsicmp(dllpath, L"ole32.dll"))
915 RegCloseKey(hkey);
916 return HandlerCF_Create(rclsid, riid, ppv);
919 else
920 WARN("not creating object for inproc handler path %s\n", debugstr_w(dllpath));
921 RegCloseKey(hkey);
924 return CLASS_E_CLASSNOTAVAILABLE;
927 /***********************************************************************
928 * DllMain (OLE32.@)
930 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
932 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, reserved);
934 switch(fdwReason) {
935 case DLL_PROCESS_ATTACH:
936 hProxyDll = hinstDLL;
937 break;
939 case DLL_PROCESS_DETACH:
940 if (reserved) break;
941 release_std_git();
942 break;
944 return TRUE;
947 /***********************************************************************
948 * DllRegisterServer (OLE32.@)
950 HRESULT WINAPI DllRegisterServer(void)
952 return OLE32_DllRegisterServer();
955 /***********************************************************************
956 * DllUnregisterServer (OLE32.@)
958 HRESULT WINAPI DllUnregisterServer(void)
960 return OLE32_DllUnregisterServer();