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
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
44 #define WIN32_NO_STATUS
50 #define USE_COM_CONTEXT_DEF
59 #include "compobj_private.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
74 MiscStatusContent
= 4,
75 MiscStatusThumbnail
= 8,
76 MiscStatusDocPrint
= 16
79 struct comclassredirect_data
95 DWORD miscstatuscontent
;
96 DWORD miscstatusthumbnail
;
98 DWORD miscstatusdocprint
;
101 struct ifacepsredirect_data
113 struct progidredirect_data
120 enum class_reg_data_origin
126 struct class_reg_data
128 enum class_reg_data_origin origin
;
133 const WCHAR
*module_name
;
134 DWORD threading_model
;
141 static inline enum comclass_miscfields
dvaspect_to_miscfields(DWORD aspect
)
145 case DVASPECT_CONTENT
:
146 return MiscStatusContent
;
147 case DVASPECT_THUMBNAIL
:
148 return MiscStatusThumbnail
;
150 return MiscStatusIcon
;
151 case DVASPECT_DOCPRINT
:
152 return MiscStatusDocPrint
;
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
,
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
))
183 *status
= comclass
->miscstatus
;
186 *status
= comclass
->miscstatusicon
;
188 case MiscStatusContent
:
189 *status
= comclass
->miscstatuscontent
;
191 case MiscStatusThumbnail
:
192 *status
= comclass
->miscstatusthumbnail
;
194 case MiscStatusDocPrint
:
195 *status
= comclass
->miscstatusdocprint
;
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
);
219 while (i
< len
&& buffer
[i
] != '\\') i
++;
220 if (i
== len
) return status
;
222 attrs
= attr
->Attributes
;
223 attr
->ObjectName
= &str
;
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
++;
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
);
246 static HKEY classes_root_hkey
;
248 /* create the special HKEY_CLASSES_ROOT key */
249 static HKEY
create_classes_root_hkey(DWORD access
)
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
;
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 )))
269 NtClose( hkey
); /* somebody beat us to it */
276 /* map the hkey from special root to normal key if necessary */
277 static inline HKEY
get_classes_root_hkey( HKEY hkey
, REGSAM access
)
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
))
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
;
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
;
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
;
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
;
360 ERR("Unknown interface %s requested.\n", debugstr_guid(riid
));
362 return E_NOINTERFACE
;
365 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
386 CloseHandle(This
->event
);
387 HeapFree(GetProcessHeap(), 0, This
);
393 static HRESULT WINAPI
ISynchronize_fnWait(ISynchronize
*iface
, DWORD dwFlags
, DWORD dwMilliseconds
)
395 MREImpl
*This
= impl_from_ISynchronize(iface
);
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
);
405 SetEvent(This
->event
);
409 static HRESULT WINAPI
ISynchronize_fnReset(ISynchronize
*iface
)
411 MREImpl
*This
= impl_from_ISynchronize(iface
);
413 ResetEvent(This
->event
);
417 static ISynchronizeVtbl vt_ISynchronize
= {
418 ISynchronize_fnQueryInterface
,
419 ISynchronize_fnAddRef
,
420 ISynchronize_fnRelease
,
422 ISynchronize_fnSignal
,
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
);
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
));
470 FIXME("Aggregation not implemented.\n");
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
);
482 /******************************************************************************
483 * CoBuildVersion [OLE32.@]
485 * Gets the build version of the DLL.
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.
505 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
508 * Success: S_OK if not already initialized, S_FALSE otherwise.
509 * Failure: HRESULT code.
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];
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
;
543 res
= open_classes_key(key
, keyname
, access
, subkey
);
545 if (res
== ERROR_FILE_NOT_FOUND
)
546 return REGDB_E_KEYMISSING
;
547 else if (res
!= ERROR_SUCCESS
)
548 return REGDB_E_READREGDB
;
553 /***********************************************************************
554 * CoLoadLibrary (OLE32.@)
559 * lpszLibName [I] Path to library.
560 * bAutoFree [I] Whether the library should automatically be freed.
563 * Success: Handle to loaded library.
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.
582 * hLibrary [I] Handle to library to unload.
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.
605 * CoLoadLibrary, CoFreeLibrary, CoFreeUnusedLibraries
607 void WINAPI
CoFreeAllLibraries(void)
612 /***********************************************************************
613 * CoGetState [OLE32.@]
615 * Retrieves the thread state object previously stored by CoSetState().
618 * ppv [I] Address where pointer to object will be stored.
622 * Failure: E_OUTOFMEMORY.
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.
632 HRESULT WINAPI
CoGetState(IUnknown
** ppv
)
634 struct oletls
*info
= COM_CurrentInfo();
635 if (!info
) return E_OUTOFMEMORY
;
641 IUnknown_AddRef(info
->state
);
643 TRACE("apt->state=%p\n", info
->state
);
649 /***********************************************************************
650 * CoSetState [OLE32.@]
652 * Sets the thread state object.
655 * pv [I] Pointer to state object to be stored.
658 * The system keeps a reference on the object while the object stored.
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
);
673 TRACE("-- release %p now\n", info
->state
);
674 IUnknown_Release(info
->state
);
683 /******************************************************************************
684 * CoTreatAsClass [OLE32.@]
686 * Sets the TreatAs value of a class.
689 * clsidOld [I] Class to set TreatAs value on.
690 * clsidNew [I] The class the clsidOld should be treated as.
694 * Failure: HRESULT code.
699 HRESULT WINAPI
CoTreatAsClass(REFCLSID clsidOld
, REFCLSID clsidNew
)
702 WCHAR szClsidNew
[CHARS_IN_GUID
];
704 WCHAR auto_treat_as
[CHARS_IN_GUID
];
705 LONG auto_treat_as_size
= sizeof(auto_treat_as
);
708 res
= COM_OpenKeyForCLSID(clsidOld
, NULL
, KEY_READ
| KEY_WRITE
, &hkey
);
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
;
725 if (RegDeleteKeyW(hkey
, L
"TreatAs"))
726 res
= REGDB_E_WRITEREGDB
;
732 if(IsEqualGUID(clsidNew
, &CLSID_NULL
)){
733 RegDeleteKeyW(hkey
, L
"TreatAs");
735 if(!StringFromGUID2(clsidNew
, szClsidNew
, ARRAY_SIZE(szClsidNew
))){
736 WARN("StringFromGUID2 failed\n");
741 if (RegSetValueW(hkey
, L
"TreatAs", REG_SZ
, szClsidNew
, sizeof(szClsidNew
)) != ERROR_SUCCESS
){
742 WARN("RegSetValue failed\n");
743 res
= REGDB_E_WRITEREGDB
;
750 if (hkey
) RegCloseKey(hkey
);
754 /***********************************************************************
755 * CoIsOle1Class [OLE32.@]
757 * Determines whether the specified class an OLE v1 class.
760 * clsid [I] Class to test.
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
));
771 /***********************************************************************
772 * IsEqualGUID [OLE32.@]
774 * Compares two Unique Identifiers.
777 * rguid1 [I] The first GUID to compare.
778 * rguid2 [I] The other GUID to compare.
784 BOOL WINAPI
IsEqualGUID(
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
);
801 /***********************************************************************
802 * CoGetObject [OLE32.@]
804 * Gets the object named by converting the name to a moniker and binding to it.
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
815 * Failure: HRESULT code.
818 * MkParseDisplayName.
820 HRESULT WINAPI
CoGetObject(LPCWSTR pszName
, BIND_OPTS
*pBindOptions
,
821 REFIID riid
, void **ppv
)
828 hr
= CreateBindCtx(0, &pbc
);
832 hr
= IBindCtx_SetBindOptions(pbc
, pBindOptions
);
839 hr
= MkParseDisplayName(pbc
, pszName
, &chEaten
, &pmk
);
842 hr
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppv
);
843 IMoniker_Release(pmk
);
847 IBindCtx_Release(pbc
);
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
)
857 if (regdata
->origin
== CLASS_REG_REGISTRY
)
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
;
867 const WCHAR
*quote_start
;
868 quote_start
= wcschr(src
, '\"');
870 const WCHAR
*quote_end
= wcschr(quote_start
+ 1, '\"');
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
);
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
);
894 HRESULT
Handler_DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
899 hres
= COM_OpenKeyForCLSID(rclsid
, L
"InprocHandler32", KEY_READ
, &hkey
);
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(®data
, dllpath
, ARRAY_SIZE(dllpath
)))
910 if (!wcsicmp(dllpath
, L
"ole32.dll"))
913 return HandlerCF_Create(rclsid
, riid
, ppv
);
917 WARN("not creating object for inproc handler path %s\n", debugstr_w(dllpath
));
921 return CLASS_E_CLASSNOTAVAILABLE
;
924 /***********************************************************************
927 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID reserved
)
929 TRACE("%p, %#lx, %p.\n", hinstDLL
, fdwReason
, reserved
);
932 case DLL_PROCESS_ATTACH
:
933 hProxyDll
= hinstDLL
;
936 case DLL_PROCESS_DETACH
:
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();