wined3d/glsl: Flush NaN to zero in ftoi.
[wine.git] / dlls / ole32 / compobj.c
blobf90b269fafaf58f68852fd99beea47cc6e4b352f
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 #include "ntstatus.h"
44 #define WIN32_NO_STATUS
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winerror.h"
48 #include "winreg.h"
49 #include "winuser.h"
50 #define USE_COM_CONTEXT_DEF
51 #include "objbase.h"
52 #include "ole2.h"
53 #include "ole2ver.h"
54 #include "ctxtcall.h"
55 #include "dde.h"
56 #include "servprov.h"
58 #include "initguid.h"
59 #include "compobj_private.h"
60 #include "moniker.h"
62 #include "wine/debug.h"
64 WINE_DEFAULT_DEBUG_CHANNEL(ole);
66 /****************************************************************************
67 * This section defines variables internal to the COM module.
70 enum comclass_miscfields
72 MiscStatus = 1,
73 MiscStatusIcon = 2,
74 MiscStatusContent = 4,
75 MiscStatusThumbnail = 8,
76 MiscStatusDocPrint = 16
79 struct comclassredirect_data
81 ULONG size;
82 ULONG flags;
83 DWORD model;
84 GUID clsid;
85 GUID alias;
86 GUID clsid2;
87 GUID tlbid;
88 ULONG name_len;
89 ULONG name_offset;
90 ULONG progid_len;
91 ULONG progid_offset;
92 ULONG clrdata_len;
93 ULONG clrdata_offset;
94 DWORD miscstatus;
95 DWORD miscstatuscontent;
96 DWORD miscstatusthumbnail;
97 DWORD miscstatusicon;
98 DWORD miscstatusdocprint;
101 struct ifacepsredirect_data
103 ULONG size;
104 DWORD mask;
105 GUID iid;
106 ULONG nummethods;
107 GUID tlbid;
108 GUID base;
109 ULONG name_len;
110 ULONG name_offset;
113 struct progidredirect_data
115 ULONG size;
116 DWORD reserved;
117 ULONG clsid_offset;
120 enum class_reg_data_origin
122 CLASS_REG_ACTCTX,
123 CLASS_REG_REGISTRY,
126 struct class_reg_data
128 enum class_reg_data_origin origin;
129 union
131 struct
133 const WCHAR *module_name;
134 DWORD threading_model;
135 HANDLE hactctx;
136 } actctx;
137 HKEY hkey;
138 } u;
141 static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
143 switch (aspect)
145 case DVASPECT_CONTENT:
146 return MiscStatusContent;
147 case DVASPECT_THUMBNAIL:
148 return MiscStatusThumbnail;
149 case DVASPECT_ICON:
150 return MiscStatusIcon;
151 case DVASPECT_DOCPRINT:
152 return MiscStatusDocPrint;
153 default:
154 return MiscStatus;
158 BOOL actctx_get_miscstatus(const CLSID *clsid, DWORD aspect, DWORD *status)
160 ACTCTX_SECTION_KEYED_DATA data;
162 data.cbSize = sizeof(data);
163 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
164 clsid, &data))
166 struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData;
167 enum comclass_miscfields misc = dvaspect_to_miscfields(aspect);
168 ULONG miscmask = (comclass->flags >> 8) & 0xff;
170 if (!(miscmask & misc))
172 if (!(miscmask & MiscStatus))
174 *status = 0;
175 return TRUE;
177 misc = MiscStatus;
180 switch (misc)
182 case MiscStatus:
183 *status = comclass->miscstatus;
184 break;
185 case MiscStatusIcon:
186 *status = comclass->miscstatusicon;
187 break;
188 case MiscStatusContent:
189 *status = comclass->miscstatuscontent;
190 break;
191 case MiscStatusThumbnail:
192 *status = comclass->miscstatusthumbnail;
193 break;
194 case MiscStatusDocPrint:
195 *status = comclass->miscstatusdocprint;
196 break;
197 default:
201 return TRUE;
203 else
204 return FALSE;
207 /* wrapper for NtCreateKey that creates the key recursively if necessary */
208 static NTSTATUS create_key( HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
210 NTSTATUS status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, NULL, 0, NULL );
212 if (status == STATUS_OBJECT_NAME_NOT_FOUND)
214 HANDLE subkey, root = attr->RootDirectory;
215 WCHAR *buffer = attr->ObjectName->Buffer;
216 DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
217 UNICODE_STRING str;
219 while (i < len && buffer[i] != '\\') i++;
220 if (i == len) return status;
222 attrs = attr->Attributes;
223 attr->ObjectName = &str;
225 while (i < len)
227 str.Buffer = buffer + pos;
228 str.Length = (i - pos) * sizeof(WCHAR);
229 status = NtCreateKey( &subkey, access, attr, 0, NULL, 0, NULL );
230 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
231 if (status) return status;
232 attr->RootDirectory = subkey;
233 while (i < len && buffer[i] == '\\') i++;
234 pos = i;
235 while (i < len && buffer[i] != '\\') i++;
237 str.Buffer = buffer + pos;
238 str.Length = (i - pos) * sizeof(WCHAR);
239 attr->Attributes = attrs;
240 status = NtCreateKey( (PHANDLE)retkey, access, attr, 0, NULL, 0, NULL );
241 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
243 return status;
246 static HKEY classes_root_hkey;
248 /* create the special HKEY_CLASSES_ROOT key */
249 static HKEY create_classes_root_hkey(DWORD access)
251 HKEY hkey, ret = 0;
252 OBJECT_ATTRIBUTES attr;
253 UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Classes");
255 attr.Length = sizeof(attr);
256 attr.RootDirectory = 0;
257 attr.ObjectName = &name;
258 attr.Attributes = 0;
259 attr.SecurityDescriptor = NULL;
260 attr.SecurityQualityOfService = NULL;
261 if (create_key( &hkey, access, &attr )) return 0;
262 TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
264 if (!(access & KEY_WOW64_64KEY))
266 if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
267 ret = hkey;
268 else
269 NtClose( hkey ); /* somebody beat us to it */
271 else
272 ret = hkey;
273 return ret;
276 /* map the hkey from special root to normal key if necessary */
277 static inline HKEY get_classes_root_hkey( HKEY hkey, REGSAM access )
279 HKEY ret = hkey;
280 const BOOL is_win64 = sizeof(void*) > sizeof(int);
281 const BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY);
283 if (hkey == HKEY_CLASSES_ROOT &&
284 ((access & KEY_WOW64_64KEY) || !(ret = classes_root_hkey)))
285 ret = create_classes_root_hkey(MAXIMUM_ALLOWED | (access & KEY_WOW64_64KEY));
286 if (force_wow32 && ret && ret == classes_root_hkey)
288 access &= ~KEY_WOW64_32KEY;
289 if (create_classes_key(classes_root_hkey, L"Wow6432Node", access, &hkey))
290 return 0;
291 ret = hkey;
294 return ret;
297 LSTATUS create_classes_key( HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey )
299 OBJECT_ATTRIBUTES attr;
300 UNICODE_STRING nameW;
302 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
304 attr.Length = sizeof(attr);
305 attr.RootDirectory = hkey;
306 attr.ObjectName = &nameW;
307 attr.Attributes = 0;
308 attr.SecurityDescriptor = NULL;
309 attr.SecurityQualityOfService = NULL;
310 RtlInitUnicodeString( &nameW, name );
312 return RtlNtStatusToDosError( create_key( retkey, access, &attr ) );
315 LSTATUS open_classes_key( HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey )
317 OBJECT_ATTRIBUTES attr;
318 UNICODE_STRING nameW;
320 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
322 attr.Length = sizeof(attr);
323 attr.RootDirectory = hkey;
324 attr.ObjectName = &nameW;
325 attr.Attributes = 0;
326 attr.SecurityDescriptor = NULL;
327 attr.SecurityQualityOfService = NULL;
328 RtlInitUnicodeString( &nameW, name );
330 return RtlNtStatusToDosError( NtOpenKey( (HANDLE *)retkey, access, &attr ) );
333 /******************************************************************************
334 * Implementation of the manual reset event object. (CLSID_ManualResetEvent)
337 typedef struct ManualResetEvent {
338 ISynchronize ISynchronize_iface;
339 ISynchronizeHandle ISynchronizeHandle_iface;
340 LONG ref;
341 HANDLE event;
342 } MREImpl;
344 static inline MREImpl *impl_from_ISynchronize(ISynchronize *iface)
346 return CONTAINING_RECORD(iface, MREImpl, ISynchronize_iface);
349 static HRESULT WINAPI ISynchronize_fnQueryInterface(ISynchronize *iface, REFIID riid, void **ppv)
351 MREImpl *This = impl_from_ISynchronize(iface);
353 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppv);
355 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISynchronize)) {
356 *ppv = &This->ISynchronize_iface;
357 }else if(IsEqualGUID(riid, &IID_ISynchronizeHandle)) {
358 *ppv = &This->ISynchronizeHandle_iface;
359 }else {
360 ERR("Unknown interface %s requested.\n", debugstr_guid(riid));
361 *ppv = NULL;
362 return E_NOINTERFACE;
365 IUnknown_AddRef((IUnknown*)*ppv);
366 return S_OK;
369 static ULONG WINAPI ISynchronize_fnAddRef(ISynchronize *iface)
371 MREImpl *This = impl_from_ISynchronize(iface);
372 LONG ref = InterlockedIncrement(&This->ref);
373 TRACE("%p, refcount %ld.\n", iface, ref);
375 return ref;
378 static ULONG WINAPI ISynchronize_fnRelease(ISynchronize *iface)
380 MREImpl *This = impl_from_ISynchronize(iface);
381 LONG ref = InterlockedDecrement(&This->ref);
382 TRACE("%p, refcount %ld.\n", iface, ref);
384 if(!ref)
386 CloseHandle(This->event);
387 HeapFree(GetProcessHeap(), 0, This);
390 return ref;
393 static HRESULT WINAPI ISynchronize_fnWait(ISynchronize *iface, DWORD dwFlags, DWORD dwMilliseconds)
395 MREImpl *This = impl_from_ISynchronize(iface);
396 DWORD index;
397 TRACE("%p, %#lx, %#lx.\n", iface, dwFlags, dwMilliseconds);
398 return CoWaitForMultipleHandles(dwFlags, dwMilliseconds, 1, &This->event, &index);
401 static HRESULT WINAPI ISynchronize_fnSignal(ISynchronize *iface)
403 MREImpl *This = impl_from_ISynchronize(iface);
404 TRACE("%p\n", This);
405 SetEvent(This->event);
406 return S_OK;
409 static HRESULT WINAPI ISynchronize_fnReset(ISynchronize *iface)
411 MREImpl *This = impl_from_ISynchronize(iface);
412 TRACE("%p\n", This);
413 ResetEvent(This->event);
414 return S_OK;
417 static ISynchronizeVtbl vt_ISynchronize = {
418 ISynchronize_fnQueryInterface,
419 ISynchronize_fnAddRef,
420 ISynchronize_fnRelease,
421 ISynchronize_fnWait,
422 ISynchronize_fnSignal,
423 ISynchronize_fnReset
426 static inline MREImpl *impl_from_ISynchronizeHandle(ISynchronizeHandle *iface)
428 return CONTAINING_RECORD(iface, MREImpl, ISynchronizeHandle_iface);
431 static HRESULT WINAPI SynchronizeHandle_QueryInterface(ISynchronizeHandle *iface, REFIID riid, void **ppv)
433 MREImpl *This = impl_from_ISynchronizeHandle(iface);
434 return ISynchronize_QueryInterface(&This->ISynchronize_iface, riid, ppv);
437 static ULONG WINAPI SynchronizeHandle_AddRef(ISynchronizeHandle *iface)
439 MREImpl *This = impl_from_ISynchronizeHandle(iface);
440 return ISynchronize_AddRef(&This->ISynchronize_iface);
443 static ULONG WINAPI SynchronizeHandle_Release(ISynchronizeHandle *iface)
445 MREImpl *This = impl_from_ISynchronizeHandle(iface);
446 return ISynchronize_Release(&This->ISynchronize_iface);
449 static HRESULT WINAPI SynchronizeHandle_GetHandle(ISynchronizeHandle *iface, HANDLE *ph)
451 MREImpl *This = impl_from_ISynchronizeHandle(iface);
453 *ph = This->event;
454 return S_OK;
457 static const ISynchronizeHandleVtbl SynchronizeHandleVtbl = {
458 SynchronizeHandle_QueryInterface,
459 SynchronizeHandle_AddRef,
460 SynchronizeHandle_Release,
461 SynchronizeHandle_GetHandle
464 HRESULT WINAPI ManualResetEvent_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **ppv)
466 MREImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MREImpl));
467 HRESULT hr;
469 if (outer)
470 FIXME("Aggregation not implemented.\n");
472 This->ref = 1;
473 This->ISynchronize_iface.lpVtbl = &vt_ISynchronize;
474 This->ISynchronizeHandle_iface.lpVtbl = &SynchronizeHandleVtbl;
475 This->event = CreateEventW(NULL, TRUE, FALSE, NULL);
477 hr = ISynchronize_QueryInterface(&This->ISynchronize_iface, iid, ppv);
478 ISynchronize_Release(&This->ISynchronize_iface);
479 return hr;
482 /******************************************************************************
483 * CoBuildVersion [OLE32.@]
485 * Gets the build version of the DLL.
487 * PARAMS
489 * RETURNS
490 * Current build version, hiword is majornumber, loword is minornumber
492 DWORD WINAPI CoBuildVersion(void)
494 TRACE("Returning version %d, build %d.\n", rmm, rup);
495 return (rmm<<16)+rup;
498 /******************************************************************************
499 * CoInitialize [OLE32.@]
501 * Initializes the COM libraries by calling CoInitializeEx with
502 * COINIT_APARTMENTTHREADED, ie it enters a STA thread.
504 * PARAMS
505 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
507 * RETURNS
508 * Success: S_OK if not already initialized, S_FALSE otherwise.
509 * Failure: HRESULT code.
511 * SEE ALSO
512 * CoInitializeEx
514 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
517 * Just delegate to the newer method.
519 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
522 /* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */
523 HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey)
525 WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(L"CLSID\\") - 1];
526 LONG res;
527 HKEY key;
529 lstrcpyW(path, L"CLSID\\");
530 StringFromGUID2(clsid, path + lstrlenW(L"CLSID\\"), CHARS_IN_GUID);
531 res = open_classes_key(HKEY_CLASSES_ROOT, path, keyname ? KEY_READ : access, &key);
532 if (res == ERROR_FILE_NOT_FOUND)
533 return REGDB_E_CLASSNOTREG;
534 else if (res != ERROR_SUCCESS)
535 return REGDB_E_READREGDB;
537 if (!keyname)
539 *subkey = key;
540 return S_OK;
543 res = open_classes_key(key, keyname, access, subkey);
544 RegCloseKey(key);
545 if (res == ERROR_FILE_NOT_FOUND)
546 return REGDB_E_KEYMISSING;
547 else if (res != ERROR_SUCCESS)
548 return REGDB_E_READREGDB;
550 return S_OK;
553 /***********************************************************************
554 * CoLoadLibrary (OLE32.@)
556 * Loads a library.
558 * PARAMS
559 * lpszLibName [I] Path to library.
560 * bAutoFree [I] Whether the library should automatically be freed.
562 * RETURNS
563 * Success: Handle to loaded library.
564 * Failure: NULL.
566 * SEE ALSO
567 * CoFreeLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
569 HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
571 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
573 return LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
576 /***********************************************************************
577 * CoFreeLibrary [OLE32.@]
579 * Unloads a library from memory.
581 * PARAMS
582 * hLibrary [I] Handle to library to unload.
584 * RETURNS
585 * Nothing
587 * SEE ALSO
588 * CoLoadLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
590 void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
592 FreeLibrary(hLibrary);
596 /***********************************************************************
597 * CoFreeAllLibraries [OLE32.@]
599 * Function for backwards compatibility only. Does nothing.
601 * RETURNS
602 * Nothing.
604 * SEE ALSO
605 * CoLoadLibrary, CoFreeLibrary, CoFreeUnusedLibraries
607 void WINAPI CoFreeAllLibraries(void)
609 /* NOP */
612 /***********************************************************************
613 * CoGetState [OLE32.@]
615 * Retrieves the thread state object previously stored by CoSetState().
617 * PARAMS
618 * ppv [I] Address where pointer to object will be stored.
620 * RETURNS
621 * Success: S_OK.
622 * Failure: E_OUTOFMEMORY.
624 * NOTES
625 * Crashes on all invalid ppv addresses, including NULL.
626 * If the function returns a non-NULL object then the caller must release its
627 * reference on the object when the object is no longer required.
629 * SEE ALSO
630 * CoSetState().
632 HRESULT WINAPI CoGetState(IUnknown ** ppv)
634 struct oletls *info = COM_CurrentInfo();
635 if (!info) return E_OUTOFMEMORY;
637 *ppv = NULL;
639 if (info->state)
641 IUnknown_AddRef(info->state);
642 *ppv = info->state;
643 TRACE("apt->state=%p\n", info->state);
646 return S_OK;
649 /***********************************************************************
650 * CoSetState [OLE32.@]
652 * Sets the thread state object.
654 * PARAMS
655 * pv [I] Pointer to state object to be stored.
657 * NOTES
658 * The system keeps a reference on the object while the object stored.
660 * RETURNS
661 * Success: S_OK.
662 * Failure: E_OUTOFMEMORY.
664 HRESULT WINAPI CoSetState(IUnknown * pv)
666 struct oletls *info = COM_CurrentInfo();
667 if (!info) return E_OUTOFMEMORY;
669 if (pv) IUnknown_AddRef(pv);
671 if (info->state)
673 TRACE("-- release %p now\n", info->state);
674 IUnknown_Release(info->state);
677 info->state = pv;
679 return S_OK;
683 /******************************************************************************
684 * CoTreatAsClass [OLE32.@]
686 * Sets the TreatAs value of a class.
688 * PARAMS
689 * clsidOld [I] Class to set TreatAs value on.
690 * clsidNew [I] The class the clsidOld should be treated as.
692 * RETURNS
693 * Success: S_OK.
694 * Failure: HRESULT code.
696 * SEE ALSO
697 * CoGetTreatAsClass
699 HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
701 HKEY hkey = NULL;
702 WCHAR szClsidNew[CHARS_IN_GUID];
703 HRESULT res = S_OK;
704 WCHAR auto_treat_as[CHARS_IN_GUID];
705 LONG auto_treat_as_size = sizeof(auto_treat_as);
706 CLSID id;
708 res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
709 if (FAILED(res))
710 goto done;
712 if (IsEqualGUID( clsidOld, clsidNew ))
714 if (!RegQueryValueW(hkey, L"AutoTreatAs", auto_treat_as, &auto_treat_as_size) &&
715 CLSIDFromString(auto_treat_as, &id) == S_OK)
717 if (RegSetValueW(hkey, L"TreatAs", REG_SZ, auto_treat_as, sizeof(auto_treat_as)))
719 res = REGDB_E_WRITEREGDB;
720 goto done;
723 else
725 if (RegDeleteKeyW(hkey, L"TreatAs"))
726 res = REGDB_E_WRITEREGDB;
727 goto done;
730 else
732 if(IsEqualGUID(clsidNew, &CLSID_NULL)){
733 RegDeleteKeyW(hkey, L"TreatAs");
734 }else{
735 if(!StringFromGUID2(clsidNew, szClsidNew, ARRAY_SIZE(szClsidNew))){
736 WARN("StringFromGUID2 failed\n");
737 res = E_FAIL;
738 goto done;
741 if (RegSetValueW(hkey, L"TreatAs", REG_SZ, szClsidNew, sizeof(szClsidNew)) != ERROR_SUCCESS){
742 WARN("RegSetValue failed\n");
743 res = REGDB_E_WRITEREGDB;
744 goto done;
749 done:
750 if (hkey) RegCloseKey(hkey);
751 return res;
754 /***********************************************************************
755 * CoIsOle1Class [OLE32.@]
757 * Determines whether the specified class an OLE v1 class.
759 * PARAMS
760 * clsid [I] Class to test.
762 * RETURNS
763 * TRUE if the class is an OLE v1 class, or FALSE otherwise.
765 BOOL WINAPI CoIsOle1Class(REFCLSID clsid)
767 FIXME("%s\n", debugstr_guid(clsid));
768 return FALSE;
771 /***********************************************************************
772 * IsEqualGUID [OLE32.@]
774 * Compares two Unique Identifiers.
776 * PARAMS
777 * rguid1 [I] The first GUID to compare.
778 * rguid2 [I] The other GUID to compare.
780 * RETURNS
781 * TRUE if equal
783 #undef IsEqualGUID
784 BOOL WINAPI IsEqualGUID(
785 REFGUID rguid1,
786 REFGUID rguid2)
788 return !memcmp(rguid1,rguid2,sizeof(GUID));
791 /***********************************************************************
792 * CoAllowSetForegroundWindow [OLE32.@]
795 HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved)
797 FIXME("(%p, %p): stub\n", pUnk, pvReserved);
798 return S_OK;
801 /***********************************************************************
802 * CoGetObject [OLE32.@]
804 * Gets the object named by converting the name to a moniker and binding to it.
806 * PARAMS
807 * pszName [I] String representing the object.
808 * pBindOptions [I] Parameters affecting the binding to the named object.
809 * riid [I] Interface to bind to on the object.
810 * ppv [O] On output, the interface riid of the object represented
811 * by pszName.
813 * RETURNS
814 * Success: S_OK.
815 * Failure: HRESULT code.
817 * SEE ALSO
818 * MkParseDisplayName.
820 HRESULT WINAPI CoGetObject(LPCWSTR pszName, BIND_OPTS *pBindOptions,
821 REFIID riid, void **ppv)
823 IBindCtx *pbc;
824 HRESULT hr;
826 *ppv = NULL;
828 hr = CreateBindCtx(0, &pbc);
829 if (SUCCEEDED(hr))
831 if (pBindOptions)
832 hr = IBindCtx_SetBindOptions(pbc, pBindOptions);
834 if (SUCCEEDED(hr))
836 ULONG chEaten;
837 IMoniker *pmk;
839 hr = MkParseDisplayName(pbc, pszName, &chEaten, &pmk);
840 if (SUCCEEDED(hr))
842 hr = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppv);
843 IMoniker_Release(pmk);
847 IBindCtx_Release(pbc);
849 return hr;
852 /* Returns expanded dll path from the registry or activation context. */
853 static BOOL get_object_dll_path(const struct class_reg_data *regdata, WCHAR *dst, DWORD dstlen)
855 DWORD ret;
857 if (regdata->origin == CLASS_REG_REGISTRY)
859 DWORD keytype;
860 WCHAR src[MAX_PATH];
861 DWORD dwLength = dstlen * sizeof(WCHAR);
863 if( (ret = RegQueryValueExW(regdata->u.hkey, NULL, NULL, &keytype, (BYTE*)src, &dwLength)) == ERROR_SUCCESS ) {
864 if (keytype == REG_EXPAND_SZ) {
865 if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA;
866 } else {
867 const WCHAR *quote_start;
868 quote_start = wcschr(src, '\"');
869 if (quote_start) {
870 const WCHAR *quote_end = wcschr(quote_start + 1, '\"');
871 if (quote_end) {
872 memmove(src, quote_start + 1,
873 (quote_end - quote_start - 1) * sizeof(WCHAR));
874 src[quote_end - quote_start - 1] = '\0';
877 lstrcpynW(dst, src, dstlen);
880 return !ret;
882 else
884 ULONG_PTR cookie;
886 *dst = 0;
887 ActivateActCtx(regdata->u.actctx.hactctx, &cookie);
888 ret = SearchPathW(NULL, regdata->u.actctx.module_name, L".dll", dstlen, dst, NULL);
889 DeactivateActCtx(0, cookie);
890 return *dst != 0;
894 HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
896 HKEY hkey;
897 HRESULT hres;
899 hres = COM_OpenKeyForCLSID(rclsid, L"InprocHandler32", KEY_READ, &hkey);
900 if (SUCCEEDED(hres))
902 struct class_reg_data regdata;
903 WCHAR dllpath[MAX_PATH+1];
905 regdata.u.hkey = hkey;
906 regdata.origin = CLASS_REG_REGISTRY;
908 if (get_object_dll_path(&regdata, dllpath, ARRAY_SIZE(dllpath)))
910 if (!wcsicmp(dllpath, L"ole32.dll"))
912 RegCloseKey(hkey);
913 return HandlerCF_Create(rclsid, riid, ppv);
916 else
917 WARN("not creating object for inproc handler path %s\n", debugstr_w(dllpath));
918 RegCloseKey(hkey);
921 return CLASS_E_CLASSNOTAVAILABLE;
924 /***********************************************************************
925 * DllMain (OLE32.@)
927 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
929 TRACE("%p, %#lx, %p.\n", hinstDLL, fdwReason, reserved);
931 switch(fdwReason) {
932 case DLL_PROCESS_ATTACH:
933 hProxyDll = hinstDLL;
934 break;
936 case DLL_PROCESS_DETACH:
937 clipbrd_destroy();
938 if (reserved) break;
939 release_std_git();
940 break;
942 return TRUE;
945 /***********************************************************************
946 * DllRegisterServer (OLE32.@)
948 HRESULT WINAPI DllRegisterServer(void)
950 return OLE32_DllRegisterServer();
953 /***********************************************************************
954 * DllUnregisterServer (OLE32.@)
956 HRESULT WINAPI DllUnregisterServer(void)
958 return OLE32_DllUnregisterServer();