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
43 #define NONAMELESSUNION
46 #define WIN32_NO_STATUS
52 #define USE_COM_CONTEXT_DEF
61 #include "compobj_private.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
76 MiscStatusContent
= 4,
77 MiscStatusThumbnail
= 8,
78 MiscStatusDocPrint
= 16
81 struct comclassredirect_data
97 DWORD miscstatuscontent
;
98 DWORD miscstatusthumbnail
;
100 DWORD miscstatusdocprint
;
103 struct ifacepsredirect_data
115 struct progidredirect_data
122 enum class_reg_data_origin
128 struct class_reg_data
130 enum class_reg_data_origin origin
;
135 const WCHAR
*module_name
;
136 DWORD threading_model
;
143 static inline enum comclass_miscfields
dvaspect_to_miscfields(DWORD aspect
)
147 case DVASPECT_CONTENT
:
148 return MiscStatusContent
;
149 case DVASPECT_THUMBNAIL
:
150 return MiscStatusThumbnail
;
152 return MiscStatusIcon
;
153 case DVASPECT_DOCPRINT
:
154 return MiscStatusDocPrint
;
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
,
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
))
185 *status
= comclass
->miscstatus
;
188 *status
= comclass
->miscstatusicon
;
190 case MiscStatusContent
:
191 *status
= comclass
->miscstatuscontent
;
193 case MiscStatusThumbnail
:
194 *status
= comclass
->miscstatusthumbnail
;
196 case MiscStatusDocPrint
:
197 *status
= comclass
->miscstatusdocprint
;
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
);
221 while (i
< len
&& buffer
[i
] != '\\') i
++;
222 if (i
== len
) return status
;
224 attrs
= attr
->Attributes
;
225 attr
->ObjectName
= &str
;
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
++;
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
);
248 static HKEY classes_root_hkey
;
250 /* create the special HKEY_CLASSES_ROOT key */
251 static HKEY
create_classes_root_hkey(DWORD access
)
254 OBJECT_ATTRIBUTES attr
;
257 attr
.Length
= sizeof(attr
);
258 attr
.RootDirectory
= 0;
259 attr
.ObjectName
= &name
;
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 )))
272 NtClose( hkey
); /* somebody beat us to it */
279 /* map the hkey from special root to normal key if necessary */
280 static inline HKEY
get_classes_root_hkey( HKEY hkey
, REGSAM access
)
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
))
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
;
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
;
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
;
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
;
363 ERR("Unknown interface %s requested.\n", debugstr_guid(riid
));
365 return E_NOINTERFACE
;
368 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
389 CloseHandle(This
->event
);
390 HeapFree(GetProcessHeap(), 0, This
);
396 static HRESULT WINAPI
ISynchronize_fnWait(ISynchronize
*iface
, DWORD dwFlags
, DWORD dwMilliseconds
)
398 MREImpl
*This
= impl_from_ISynchronize(iface
);
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
);
408 SetEvent(This
->event
);
412 static HRESULT WINAPI
ISynchronize_fnReset(ISynchronize
*iface
)
414 MREImpl
*This
= impl_from_ISynchronize(iface
);
416 ResetEvent(This
->event
);
420 static ISynchronizeVtbl vt_ISynchronize
= {
421 ISynchronize_fnQueryInterface
,
422 ISynchronize_fnAddRef
,
423 ISynchronize_fnRelease
,
425 ISynchronize_fnSignal
,
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
);
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
));
473 FIXME("Aggregation not implemented.\n");
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
);
485 /******************************************************************************
486 * CoBuildVersion [OLE32.@]
488 * Gets the build version of the DLL.
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.
508 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
511 * Success: S_OK if not already initialized, S_FALSE otherwise.
512 * Failure: HRESULT code.
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];
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
;
546 res
= open_classes_key(key
, keyname
, access
, subkey
);
548 if (res
== ERROR_FILE_NOT_FOUND
)
549 return REGDB_E_KEYMISSING
;
550 else if (res
!= ERROR_SUCCESS
)
551 return REGDB_E_READREGDB
;
556 /***********************************************************************
557 * CoLoadLibrary (OLE32.@)
562 * lpszLibName [I] Path to library.
563 * bAutoFree [I] Whether the library should automatically be freed.
566 * Success: Handle to loaded library.
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.
585 * hLibrary [I] Handle to library to unload.
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.
608 * CoLoadLibrary, CoFreeLibrary, CoFreeUnusedLibraries
610 void WINAPI
CoFreeAllLibraries(void)
615 /***********************************************************************
616 * CoGetState [OLE32.@]
618 * Retrieves the thread state object previously stored by CoSetState().
621 * ppv [I] Address where pointer to object will be stored.
625 * Failure: E_OUTOFMEMORY.
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.
635 HRESULT WINAPI
CoGetState(IUnknown
** ppv
)
637 struct oletls
*info
= COM_CurrentInfo();
638 if (!info
) return E_OUTOFMEMORY
;
644 IUnknown_AddRef(info
->state
);
646 TRACE("apt->state=%p\n", info
->state
);
652 /***********************************************************************
653 * CoSetState [OLE32.@]
655 * Sets the thread state object.
658 * pv [I] Pointer to state object to be stored.
661 * The system keeps a reference on the object while the object stored.
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
);
676 TRACE("-- release %p now\n", info
->state
);
677 IUnknown_Release(info
->state
);
686 /******************************************************************************
687 * CoTreatAsClass [OLE32.@]
689 * Sets the TreatAs value of a class.
692 * clsidOld [I] Class to set TreatAs value on.
693 * clsidNew [I] The class the clsidOld should be treated as.
697 * Failure: HRESULT code.
702 HRESULT WINAPI
CoTreatAsClass(REFCLSID clsidOld
, REFCLSID clsidNew
)
705 WCHAR szClsidNew
[CHARS_IN_GUID
];
707 WCHAR auto_treat_as
[CHARS_IN_GUID
];
708 LONG auto_treat_as_size
= sizeof(auto_treat_as
);
711 res
= COM_OpenKeyForCLSID(clsidOld
, NULL
, KEY_READ
| KEY_WRITE
, &hkey
);
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
;
728 if (RegDeleteKeyW(hkey
, L
"TreatAs"))
729 res
= REGDB_E_WRITEREGDB
;
735 if(IsEqualGUID(clsidNew
, &CLSID_NULL
)){
736 RegDeleteKeyW(hkey
, L
"TreatAs");
738 if(!StringFromGUID2(clsidNew
, szClsidNew
, ARRAY_SIZE(szClsidNew
))){
739 WARN("StringFromGUID2 failed\n");
744 if (RegSetValueW(hkey
, L
"TreatAs", REG_SZ
, szClsidNew
, sizeof(szClsidNew
)) != ERROR_SUCCESS
){
745 WARN("RegSetValue failed\n");
746 res
= REGDB_E_WRITEREGDB
;
753 if (hkey
) RegCloseKey(hkey
);
757 /***********************************************************************
758 * CoIsOle1Class [OLE32.@]
760 * Determines whether the specified class an OLE v1 class.
763 * clsid [I] Class to test.
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
));
774 /***********************************************************************
775 * IsEqualGUID [OLE32.@]
777 * Compares two Unique Identifiers.
780 * rguid1 [I] The first GUID to compare.
781 * rguid2 [I] The other GUID to compare.
787 BOOL WINAPI
IsEqualGUID(
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
);
804 /***********************************************************************
805 * CoGetObject [OLE32.@]
807 * Gets the object named by converting the name to a moniker and binding to it.
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
818 * Failure: HRESULT code.
821 * MkParseDisplayName.
823 HRESULT WINAPI
CoGetObject(LPCWSTR pszName
, BIND_OPTS
*pBindOptions
,
824 REFIID riid
, void **ppv
)
831 hr
= CreateBindCtx(0, &pbc
);
835 hr
= IBindCtx_SetBindOptions(pbc
, pBindOptions
);
842 hr
= MkParseDisplayName(pbc
, pszName
, &chEaten
, &pmk
);
845 hr
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppv
);
846 IMoniker_Release(pmk
);
850 IBindCtx_Release(pbc
);
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
)
860 if (regdata
->origin
== CLASS_REG_REGISTRY
)
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
;
870 const WCHAR
*quote_start
;
871 quote_start
= wcschr(src
, '\"');
873 const WCHAR
*quote_end
= wcschr(quote_start
+ 1, '\"');
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
);
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
);
897 HRESULT
Handler_DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
902 hres
= COM_OpenKeyForCLSID(rclsid
, L
"InprocHandler32", KEY_READ
, &hkey
);
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(®data
, dllpath
, ARRAY_SIZE(dllpath
)))
913 if (!wcsicmp(dllpath
, L
"ole32.dll"))
916 return HandlerCF_Create(rclsid
, riid
, ppv
);
920 WARN("not creating object for inproc handler path %s\n", debugstr_w(dllpath
));
924 return CLASS_E_CLASSNOTAVAILABLE
;
927 /***********************************************************************
930 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID reserved
)
932 TRACE("%p 0x%x %p\n", hinstDLL
, fdwReason
, reserved
);
935 case DLL_PROCESS_ATTACH
:
936 hProxyDll
= hinstDLL
;
939 case DLL_PROCESS_DETACH
:
948 /***********************************************************************
949 * DllRegisterServer (OLE32.@)
951 HRESULT WINAPI
DllRegisterServer(void)
953 return OLE32_DllRegisterServer();
956 /***********************************************************************
957 * DllUnregisterServer (OLE32.@)
959 HRESULT WINAPI
DllUnregisterServer(void)
961 return OLE32_DllUnregisterServer();