Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/compobj.c | 10 +-- dlls/ole32/compobj_private.h | 9 +- dlls/ole32/moniker.c | 170 +++++++---------------------------- dlls/ole32/ole32.spec | 1 + 4 files changed, 37 insertions(+), 153 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 55d06f197f7..88482392d5e 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -758,16 +758,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoIni * And crank-up that lock count. */ if (InterlockedExchangeAdd(&s_COMLockCount,1)==0) - { - /* - * Initialize the various COM libraries and data structures. - */ TRACE("() - Initializing the COM libraries\n");
- /* we may need to defer this until after apartment initialisation */ - RunningObjectTableImpl_Initialize(); - } - lock_init_spies(info); LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) { @@ -849,7 +841,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) TRACE("() - Releasing the COM libraries\n");
InternalRevokeAllPSClsids(); - RunningObjectTableImpl_UnInitialize(); + DestroyRunningObjectTable(); } else if (lCOMRefCnt<1) { ERR( "CoUninitialize() - not CoInitialized.\n" ); diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 29e4cac3623..e910746fefd 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -234,12 +234,6 @@ HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook) DECLSPEC_HIDD void RPC_UnregisterAllChannelHooks(void) DECLSPEC_HIDDEN; HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info) DECLSPEC_HIDDEN;
-/* This function initialize the Running Object Table */ -HRESULT WINAPI RunningObjectTableImpl_Initialize(void) DECLSPEC_HIDDEN; - -/* This function uninitialize the Running Object Table */ -HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void) DECLSPEC_HIDDEN; - /* Drag and drop */ void OLEDD_UnInitialize(void) DECLSPEC_HIDDEN;
@@ -365,4 +359,7 @@ static inline HRESULT copy_formatetc(FORMATETC *dst, const FORMATETC *src) extern HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, BOOL copy, IEnumSTATDATA **ppenum) DECLSPEC_HIDDEN;
+extern BOOL WINAPI InternalIsInitialized(void); +extern void WINAPI DestroyRunningObjectTable(void); + #endif /* __WINE_OLE_COMPOBJ_H */ diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index b143b1bc6c6..874b58f99e7 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -63,15 +63,10 @@ struct rot_entry typedef struct RunningObjectTableImpl { IRunningObjectTable IRunningObjectTable_iface; - LONG ref; - struct list rot; /* list of ROT entries */ CRITICAL_SECTION lock; } RunningObjectTableImpl;
-static RunningObjectTableImpl* runningObjectTableInstance = NULL; -static IrotHandle irot_handle; - /* define the EnumMonikerImpl structure */ typedef struct EnumMonikerImpl { @@ -256,85 +251,18 @@ RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface, return S_OK; }
-/*********************************************************************** - * RunningObjectTable_AddRef - */ -static ULONG WINAPI -RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) -{ - RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); - - TRACE("(%p)\n",This); - - return InterlockedIncrement(&This->ref); -} - -/*********************************************************************** - * RunningObjectTable_Destroy - */ -static HRESULT -RunningObjectTableImpl_Destroy(void) +static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable *iface) { - struct list *cursor, *cursor2; - IrotHandle old_handle; - - TRACE("()\n"); - - if (runningObjectTableInstance==NULL) - return E_INVALIDARG; - - /* free the ROT table memory */ - LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot) - { - struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); - list_remove(&rot_entry->entry); - rot_entry_delete(rot_entry); - } - - DEBUG_CLEAR_CRITSEC_NAME(&runningObjectTableInstance->lock); - DeleteCriticalSection(&runningObjectTableInstance->lock); + TRACE("%p\n", iface);
- /* free the ROT structure memory */ - HeapFree(GetProcessHeap(),0,runningObjectTableInstance); - runningObjectTableInstance = NULL; - - old_handle = irot_handle; - irot_handle = NULL; - if (old_handle) - RpcBindingFree(&old_handle); - - return S_OK; + return 2; }
-/*********************************************************************** - * RunningObjectTable_Release - */ -static ULONG WINAPI -RunningObjectTableImpl_Release(IRunningObjectTable* iface) +static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable *iface) { - RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); - ULONG ref; - - TRACE("(%p)\n",This); - - ref = InterlockedDecrement(&This->ref); - - /* uninitialize ROT structure if there are no more references to it */ - if (ref == 0) - { - struct list *cursor, *cursor2; - LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot) - { - struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); - list_remove(&rot_entry->entry); - rot_entry_delete(rot_entry); - } - /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only - * when RunningObjectTableImpl_UnInitialize function is called - */ - } + TRACE("%p\n", iface);
- return ref; + return 1; }
/*********************************************************************** @@ -775,82 +703,48 @@ static const IRunningObjectTableVtbl VT_RunningObjectTableImpl = RunningObjectTableImpl_EnumRunning };
-/*********************************************************************** - * RunningObjectTable_Initialize - */ -HRESULT WINAPI RunningObjectTableImpl_Initialize(void) +static RunningObjectTableImpl rot = { - TRACE("\n"); - - /* create the unique instance of the RunningObjectTableImpl structure */ - runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); - - if (!runningObjectTableInstance) - return E_OUTOFMEMORY; - - /* initialize the virtual table function */ - runningObjectTableInstance->IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl; - - /* the initial reference is set to "1" so that it isn't destroyed after its - * first use until the process is destroyed, as the running object table is - * a process-wide cache of a global table */ - runningObjectTableInstance->ref = 1; - - list_init(&runningObjectTableInstance->rot); - InitializeCriticalSection(&runningObjectTableInstance->lock); - DEBUG_SET_CRITSEC_NAME(&runningObjectTableInstance->lock, "RunningObjectTableImpl.lock"); - - return S_OK; -} + .IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl, + .lock.LockCount = -1, + .rot = LIST_INIT(rot.rot), +};
/*********************************************************************** - * RunningObjectTable_UnInitialize + * GetRunningObjectTable (OLE32.@) */ -HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void) +HRESULT WINAPI GetRunningObjectTable(DWORD reserved, IRunningObjectTable **ret) { - TRACE("\n"); + TRACE("%#x, %p\n", reserved, ret);
- if (runningObjectTableInstance==NULL) - return E_POINTER; + if (reserved!=0) + return E_UNEXPECTED;
- RunningObjectTableImpl_Release(&runningObjectTableInstance->IRunningObjectTable_iface); + if (!InternalIsInitialized()) + return CO_E_NOTINITIALIZED;
- RunningObjectTableImpl_Destroy(); + *ret = &rot.IRunningObjectTable_iface; + IRunningObjectTable_AddRef(*ret);
return S_OK; }
/*********************************************************************** - * GetRunningObjectTable (OLE32.@) - * - * Retrieves the global running object table. - * - * PARAMS - * reserved [I] Reserved. Set to 0. - * pprot [O] Address that receives the pointer to the running object table. - * - * RETURNS - * Success: S_OK. - * Failure: Any HRESULT code. - */ -HRESULT WINAPI -GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) + * DestroyRunningObjectTable (ole32.@) +*/ +void WINAPI DestroyRunningObjectTable(void) { - IID riid=IID_IRunningObjectTable; - HRESULT res; - - TRACE("()\n"); - - if (reserved!=0) - return E_UNEXPECTED; - - if(runningObjectTableInstance==NULL) - return CO_E_NOTINITIALIZED; + struct rot_entry *rot_entry, *cursor2;
- res = IRunningObjectTable_QueryInterface(&runningObjectTableInstance->IRunningObjectTable_iface, - &riid,(void**)pprot); + TRACE("\n");
- return res; + EnterCriticalSection(&rot.lock); + LIST_FOR_EACH_ENTRY_SAFE(rot_entry, cursor2, &rot.rot, struct rot_entry, entry) + { + list_remove(&rot_entry->entry); + rot_entry_delete(rot_entry); + } + LeaveCriticalSection(&rot.lock); }
static HRESULT get_moniker_for_progid_display_name(LPBC pbc, diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 4908729d1f0..c102bce1776 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -106,6 +106,7 @@ @ stdcall CreateOleAdviseHolder(ptr) @ stdcall CreatePointerMoniker(ptr ptr) @ stdcall CreateStreamOnHGlobal(ptr long ptr) +@ stdcall DestroyRunningObjectTable() @ stdcall DllDebugObjectRPCHook(long ptr) @ stdcall -private DllGetClassObject (ptr ptr ptr) @ stub DllGetClassObjectWOW
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 136 ++++++++++++++++++++++++- dlls/combase/combase.spec | 5 +- dlls/combase/combase_private.h | 3 + dlls/ole32/compobj.c | 179 --------------------------------- dlls/ole32/ole32.spec | 4 +- 5 files changed, 142 insertions(+), 185 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 4ce43717fb4..cddc9e23067 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -40,6 +40,13 @@ HINSTANCE hProxyDll;
#define CHARS_IN_GUID 39
+extern void WINAPI DestroyRunningObjectTable(void); + +/* + * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed + */ +static LONG com_lockcount; + struct comclassredirect_data { ULONG size; @@ -1757,7 +1764,7 @@ HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter ** return S_OK; }
-void WINAPI InternalRevokeAllPSClsids(void) +static void com_revoke_all_ps_clsids(void) { struct registered_ps *cur, *cur2;
@@ -2267,6 +2274,133 @@ void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibrariesEx(DWORD unload_delay, DWORD apartment_freeunusedlibraries(apt, unload_delay); }
+/* + * When locked, don't modify list (unless we add a new head), so that it's + * safe to iterate it. Freeing of list entries is delayed and done on unlock. + */ +static inline void lock_init_spies(struct tlsdata *tlsdata) +{ + tlsdata->spies_lock++; +} + +static void unlock_init_spies(struct tlsdata *tlsdata) +{ + struct init_spy *spy, *next; + + if (--tlsdata->spies_lock) return; + + LIST_FOR_EACH_ENTRY_SAFE(spy, next, &tlsdata->spies, struct init_spy, entry) + { + if (spy->spy) continue; + list_remove(&spy->entry); + heap_free(spy); + } +} + +/****************************************************************************** + * CoInitializeEx (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(void *reserved, DWORD model) +{ + struct tlsdata *tlsdata; + struct init_spy *cursor; + HRESULT hr; + + TRACE("%p, %#x\n", reserved, model); + + if (reserved) + WARN("Unexpected reserved argument %p\n", reserved); + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + if (InterlockedExchangeAdd(&com_lockcount, 1) == 0) + TRACE("Initializing the COM libraries\n"); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, model, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + hr = enter_apartment(tlsdata, model); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, model, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + return hr; +} + +/*********************************************************************** + * CoUninitialize (combase.@) + */ +void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) +{ + struct tlsdata *tlsdata; + struct init_spy *cursor, *next; + LONG lockcount; + + TRACE("\n"); + + if (FAILED(com_get_tlsdata(&tlsdata))) + return; + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + /* sanity check */ + if (!tlsdata->inits) + { + ERR("Mismatched CoUninitialize\n"); + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); + + return; + } + + leave_apartment(tlsdata); + + /* + * Decrease the reference count. + * If we are back to 0 locks on the COM library, make sure we free + * all the associated data structures. + */ + lockcount = InterlockedExchangeAdd(&com_lockcount, -1); + if (lockcount == 1) + { + TRACE("Releasing the COM libraries\n"); + + com_revoke_all_ps_clsids(); + DestroyRunningObjectTable(); + } + else if (lockcount < 1) + { + ERR("Unbalanced lock count %d\n", lockcount); + InterlockedExchangeAdd(&com_lockcount, 1); + } + + lock_init_spies(tlsdata); + LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry) + { + if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits); + } + unlock_init_spies(tlsdata); +} + /*********************************************************************** * DllMain (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 00aea556d94..01377c8045e 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -123,7 +123,7 @@ @ stdcall CoGetTreatAsClass(ptr ptr) @ stdcall CoImpersonateClient() @ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage -@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx +@ stdcall CoInitializeEx(ptr long) @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) @ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW @ stub CoInvalidateRemoteMachineBindings @@ -163,7 +163,7 @@ @ stdcall CoTaskMemFree(ptr) @ stdcall CoTaskMemRealloc(ptr long) @ stub CoTestCancel -@ stdcall CoUninitialize() ole32.CoUninitialize +@ stdcall CoUninitialize() @ stub CoUnloadingWOW @ stdcall CoUnmarshalHresult(ptr ptr) @ stdcall CoUnmarshalInterface(ptr ptr ptr) ole32.CoUnmarshalInterface @@ -268,7 +268,6 @@ @ stub InternalNotifyDDStartOrStop @ stub InternalOleModalLoopBlockFn @ stub InternalRegisterWindowPropInterface -@ stdcall InternalRevokeAllPSClsids() @ stub InternalReleaseMarshalObjRef @ stub InternalSTAInvoke @ stub InternalServerExceptionFilter diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 7fe548af593..122522baad5 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -131,6 +131,9 @@ struct stub_manager BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */ };
+HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model); +void WINAPI leave_apartment(struct tlsdata *data); + /* Stub Manager */
ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN; diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 88482392d5e..5afacf3ee3f 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -142,12 +142,6 @@ struct class_reg_data } u; };
-/* - * This lock count counts the number of times CoInitialize is called. It is - * decreased every time CoUninitialize is called. When it hits 0, the COM - * libraries are freed - */ -static LONG s_COMLockCount = 0; /* Reference count used by CoAddRefServerProcess/CoReleaseServerProcess */ static LONG s_COMServerProcessReferences = 0;
@@ -182,8 +176,6 @@ static CRITICAL_SECTION_DEBUG class_cs_debug = }; static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
-extern void WINAPI InternalRevokeAllPSClsids(void); - static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect) { switch (aspect) @@ -661,29 +653,6 @@ DWORD WINAPI CoBuildVersion(void) return (rmm<<16)+rup; }
-/* - * When locked, don't modify list (unless we add a new head), so that it's - * safe to iterate it. Freeing of list entries is delayed and done on unlock. - */ -static inline void lock_init_spies(struct oletls *info) -{ - info->spies_lock++; -} - -static void unlock_init_spies(struct oletls *info) -{ - struct init_spy *spy, *next; - - if (--info->spies_lock) return; - - LIST_FOR_EACH_ENTRY_SAFE(spy, next, &info->spies, struct init_spy, entry) - { - if (spy->spy) continue; - list_remove(&spy->entry); - heap_free(spy); - } -} - /****************************************************************************** * CoInitialize [OLE32.@] * @@ -708,154 +677,6 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved) return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED); }
-/****************************************************************************** - * CoInitializeEx [OLE32.@] - * - * Initializes the COM libraries. - * - * PARAMS - * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL). - * dwCoInit [I] One or more flags from the COINIT enumeration. See notes. - * - * RETURNS - * S_OK if successful, - * S_FALSE if this function was called already. - * RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another - * threading model. - * - * NOTES - * - * The behavior used to set the IMalloc used for memory management is - * obsolete. - * The dwCoInit parameter must specify one of the following apartment - * threading models: - *| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA). - *| COINIT_MULTITHREADED - A multi-threaded apartment (MTA). - * The parameter may also specify zero or more of the following flags: - *| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support. - *| COINIT_SPEED_OVER_MEMORY - Trade memory for speed. - * - * SEE ALSO - * CoUninitialize - */ -HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit) -{ - struct oletls *info = COM_CurrentInfo(); - struct init_spy *cursor; - HRESULT hr; - - TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit); - - if (lpReserved!=NULL) - { - ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved); - } - - /* - * Check the lock count. If this is the first time going through the initialize - * process, we have to initialize the libraries. - * - * And crank-up that lock count. - */ - if (InterlockedExchangeAdd(&s_COMLockCount,1)==0) - TRACE("() - Initializing the COM libraries\n"); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits); - } - unlock_init_spies(info); - - hr = enter_apartment( info, dwCoInit ); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits); - } - unlock_init_spies(info); - - return hr; -} - -/*********************************************************************** - * CoUninitialize [OLE32.@] - * - * This method will decrement the refcount on the current apartment, freeing - * the resources associated with it if it is the last thread in the apartment. - * If the last apartment is freed, the function will additionally release - * any COM resources associated with the process. - * - * PARAMS - * - * RETURNS - * Nothing. - * - * SEE ALSO - * CoInitializeEx - */ -void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) -{ - struct oletls * info = COM_CurrentInfo(); - struct init_spy *cursor, *next; - LONG lCOMRefCnt; - - TRACE("()\n"); - - /* will only happen on OOM */ - if (!info) return; - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); - - /* sanity check */ - if (!info->inits) - { - ERR("Mismatched CoUninitialize\n"); - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); - - return; - } - - leave_apartment( info ); - - /* - * Decrease the reference count. - * If we are back to 0 locks on the COM library, make sure we free - * all the associated data structures. - */ - lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1); - if (lCOMRefCnt==1) - { - TRACE("() - Releasing the COM libraries\n"); - - InternalRevokeAllPSClsids(); - DestroyRunningObjectTable(); - } - else if (lCOMRefCnt<1) { - ERR( "CoUninitialize() - not CoInitialized.\n" ); - InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */ - } - - lock_init_spies(info); - LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry) - { - if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits); - } - unlock_init_spies(info); -} - /****************************************************************************** * CoDisconnectObject [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index c102bce1776..e80cafd3663 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -50,7 +50,7 @@ @ stdcall CoImpersonateClient() combase.CoImpersonateClient @ stdcall CoIncrementMTAUsage(ptr) @ stdcall CoInitialize(ptr) -@ stdcall CoInitializeEx(ptr long) +@ stdcall CoInitializeEx(ptr long) combase.CoInitializeEx @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) combase.CoInitializeSecurity @ stdcall CoInitializeWOW(long long) @ stdcall CoIsHandlerConnected(ptr) @@ -87,7 +87,7 @@ @ stdcall CoTaskMemFree(ptr) combase.CoTaskMemFree @ stdcall CoTaskMemRealloc(ptr long) combase.CoTaskMemRealloc @ stdcall CoTreatAsClass(ptr ptr) -@ stdcall CoUninitialize() +@ stdcall CoUninitialize() combase.CoUninitialize @ stub CoUnloadingWOW @ stdcall CoUnmarshalHresult(ptr ptr) combase.CoUnmarshalHresult @ stdcall CoUnmarshalInterface(ptr ptr ptr)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/apartment.c | 4 ++-- dlls/combase/combase.c | 21 +++++++++++++++++++++ dlls/combase/combase.spec | 6 ++---- dlls/combase/combase_private.h | 2 ++ dlls/ole32/compobj.c | 21 --------------------- dlls/ole32/compobj_private.h | 2 -- dlls/ole32/ole32.spec | 4 ++-- 7 files changed, 29 insertions(+), 31 deletions(-)
diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c index 81071563c09..1ce7021bef9 100644 --- a/dlls/combase/apartment.c +++ b/dlls/combase/apartment.c @@ -1187,7 +1187,7 @@ struct mta_cookie struct list entry; };
-HRESULT WINAPI apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) +HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) { struct mta_cookie *mta_cookie;
@@ -1211,7 +1211,7 @@ HRESULT WINAPI apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) return S_OK; }
-void WINAPI apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) +void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) { struct mta_cookie *mta_cookie = (struct mta_cookie *)cookie;
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index cddc9e23067..7d61faefa92 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -2401,6 +2401,27 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) unlock_init_spies(tlsdata); }
+/*********************************************************************** + * CoIncrementMTAUsage (combase.@) + */ +HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE *cookie) +{ + TRACE("%p\n", cookie); + + return apartment_increment_mta_usage(cookie); +} + +/*********************************************************************** + * CoDecrementMTAUsage (combase.@) + */ +HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie) +{ + TRACE("%p\n", cookie); + + apartment_decrement_mta_usage(cookie); + return S_OK; +} + /*********************************************************************** * DllMain (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 01377c8045e..52c4ef51b2e 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -86,7 +86,7 @@ @ stub CoCreateObjectInContext @ stub CoDeactivateObject @ stub CoDecodeProxy -@ stdcall CoDecrementMTAUsage(ptr) ole32.CoDecrementMTAUsage +@ stdcall CoDecrementMTAUsage(ptr) @ stdcall CoDisableCallCancellation(ptr) ole32.CoDisableCallCancellation @ stub CoDisconnectContext @ stdcall CoDisconnectObject(ptr long) ole32.CoDisconnectObject @@ -122,7 +122,7 @@ @ stub CoGetSystemSecurityPermissions @ stdcall CoGetTreatAsClass(ptr ptr) @ stdcall CoImpersonateClient() -@ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage +@ stdcall CoIncrementMTAUsage(ptr) @ stdcall CoInitializeEx(ptr long) @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) @ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW @@ -357,8 +357,6 @@ @ stdcall leave_apartment(ptr) @ stdcall apartment_get_inproc_class_object(ptr ptr ptr ptr long ptr) @ stdcall apartment_get_mta() -@ stdcall apartment_decrement_mta_usage(ptr) -@ stdcall apartment_increment_mta_usage(ptr) @ stdcall apartment_findfromoxid(int64) @ stdcall apartment_getwindow(ptr) @ stdcall apartment_global_cleanup() diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 122522baad5..32ffba0df89 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -133,6 +133,8 @@ struct stub_manager
HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model); void WINAPI leave_apartment(struct tlsdata *data); +HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) DECLSPEC_HIDDEN; +void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) DECLSPEC_HIDDEN;
/* Stub Manager */
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 5afacf3ee3f..5adcd94b2cd 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1809,27 +1809,6 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) return info->apt ? S_OK : CO_E_NOTINITIALIZED; }
-/*********************************************************************** - * CoIncrementMTAUsage [OLE32.@] - */ -HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE *cookie) -{ - TRACE("%p\n", cookie); - - return apartment_increment_mta_usage(cookie); -} - -/*********************************************************************** - * CoDecrementMTAUsage [OLE32.@] - */ -HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie) -{ - TRACE("%p\n", cookie); - - apartment_decrement_mta_usage(cookie); - return S_OK; -} - /*********************************************************************** * CoDisableCallCancellation [OLE32.@] */ diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index e910746fefd..2c8c337c643 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -257,8 +257,6 @@ struct class_reg_data; extern HRESULT WINAPI apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) DECLSPEC_HIDDEN;
-extern void WINAPI apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) DECLSPEC_HIDDEN; -extern HRESULT WINAPI apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) DECLSPEC_HIDDEN; extern struct apartment * WINAPI apartment_get_mta(void) DECLSPEC_HIDDEN; extern HRESULT WINAPI apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN; extern void WINAPI apartment_global_cleanup(void) DECLSPEC_HIDDEN; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index e80cafd3663..7d3d1e2e6e3 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -14,7 +14,7 @@ @ stdcall CoCreateGuid(ptr) combase.CoCreateGuid @ stdcall CoCreateInstance(ptr ptr long ptr ptr) combase.CoCreateInstance @ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) combase.CoCreateInstanceEx -@ stdcall CoDecrementMTAUsage(ptr) +@ stdcall CoDecrementMTAUsage(ptr) combase.CoDecrementMTAUsage @ stdcall CoDisableCallCancellation(ptr) @ stdcall CoDisconnectObject(ptr long) @ stdcall CoDosDateTimeToFileTime(long long ptr) kernel32.DosDateTimeToFileTime @@ -48,7 +48,7 @@ @ stub CoGetTIDFromIPID @ stdcall CoGetTreatAsClass(ptr ptr) combase.CoGetTreatAsClass @ stdcall CoImpersonateClient() combase.CoImpersonateClient -@ stdcall CoIncrementMTAUsage(ptr) +@ stdcall CoIncrementMTAUsage(ptr) combase.CoIncrementMTAUsage @ stdcall CoInitialize(ptr) @ stdcall CoInitializeEx(ptr long) combase.CoInitializeEx @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) combase.CoInitializeSecurity
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/apartment.c | 2 +- dlls/combase/combase.c | 39 ++++++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 3 +-- dlls/combase/combase_private.h | 2 ++ dlls/ole32/compobj.c | 38 --------------------------------- dlls/ole32/compobj_private.h | 1 - dlls/ole32/ole32.spec | 2 +- 7 files changed, 44 insertions(+), 43 deletions(-)
diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c index 1ce7021bef9..2d1f7a75744 100644 --- a/dlls/combase/apartment.c +++ b/dlls/combase/apartment.c @@ -627,7 +627,7 @@ static struct apartment *apartment_get_or_create(DWORD model) return apt; }
-struct apartment * WINAPI apartment_get_mta(void) +struct apartment * apartment_get_mta(void) { struct apartment *apt;
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 7d61faefa92..47e31ebad14 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -2422,6 +2422,45 @@ HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie) return S_OK; }
+/*********************************************************************** + * CoGetApartmentType (combase.@) + */ +HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) +{ + struct tlsdata *tlsdata; + struct apartment *apt; + HRESULT hr; + + TRACE("%p, %p\n", type, qualifier); + + if (!type || !qualifier) + return E_INVALIDARG; + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + if (!tlsdata->apt) + *type = APTTYPE_CURRENT; + else if (tlsdata->apt->multi_threaded) + *type = APTTYPE_MTA; + else if (tlsdata->apt->main) + *type = APTTYPE_MAINSTA; + else + *type = APTTYPE_STA; + + *qualifier = APTTYPEQUALIFIER_NONE; + + if (!tlsdata->apt && (apt = apartment_get_mta())) + { + apartment_release(apt); + *type = APTTYPE_MTA; + *qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA; + return S_OK; + } + + return tlsdata->apt ? S_OK : CO_E_NOTINITIALIZED; +} + /*********************************************************************** * DllMain (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 52c4ef51b2e..143de28d7d6 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -96,7 +96,7 @@ @ stdcall CoFreeUnusedLibrariesEx(long long) @ stdcall CoGetActivationState(int128 long ptr) @ stub CoGetApartmentID -@ stdcall CoGetApartmentType(ptr ptr) ole32.CoGetApartmentType +@ stdcall CoGetApartmentType(ptr ptr) @ stdcall CoGetCallContext(ptr ptr) @ stdcall CoGetCallState(long ptr) @ stdcall CoGetCallerTID(ptr) ole32.CoGetCallerTID @@ -356,7 +356,6 @@ @ stdcall enter_apartment(ptr long) @ stdcall leave_apartment(ptr) @ stdcall apartment_get_inproc_class_object(ptr ptr ptr ptr long ptr) -@ stdcall apartment_get_mta() @ stdcall apartment_findfromoxid(int64) @ stdcall apartment_getwindow(ptr) @ stdcall apartment_global_cleanup() diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 32ffba0df89..1f80f1a12be 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -133,8 +133,10 @@ struct stub_manager
HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model); void WINAPI leave_apartment(struct tlsdata *data); +void WINAPI apartment_release(struct apartment *apt); HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) DECLSPEC_HIDDEN; void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) DECLSPEC_HIDDEN; +struct apartment * apartment_get_mta(void) DECLSPEC_HIDDEN;
/* Stub Manager */
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 5adcd94b2cd..975af46f854 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1771,44 +1771,6 @@ HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) return CLASS_E_CLASSNOTAVAILABLE; }
-/*********************************************************************** - * CoGetApartmentType [OLE32.@] - */ -HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) -{ - struct oletls *info = COM_CurrentInfo(); - struct apartment *apt; - - TRACE("(%p, %p)\n", type, qualifier); - - if (!type || !qualifier) - return E_INVALIDARG; - - if (!info) - return E_OUTOFMEMORY; - - if (!info->apt) - *type = APTTYPE_CURRENT; - else if (info->apt->multi_threaded) - *type = APTTYPE_MTA; - else if (info->apt->main) - *type = APTTYPE_MAINSTA; - else - *type = APTTYPE_STA; - - *qualifier = APTTYPEQUALIFIER_NONE; - - if (!info->apt && (apt = apartment_get_mta())) - { - apartment_release(apt); - *type = APTTYPE_MTA; - *qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA; - return S_OK; - } - - return info->apt ? S_OK : CO_E_NOTINITIALIZED; -} - /*********************************************************************** * CoDisableCallCancellation [OLE32.@] */ diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 2c8c337c643..9d6a1d1b794 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -257,7 +257,6 @@ struct class_reg_data; extern HRESULT WINAPI apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) DECLSPEC_HIDDEN;
-extern struct apartment * WINAPI apartment_get_mta(void) DECLSPEC_HIDDEN; extern HRESULT WINAPI apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN; extern void WINAPI apartment_global_cleanup(void) DECLSPEC_HIDDEN;
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 7d3d1e2e6e3..0b38e74388a 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -26,7 +26,7 @@ @ stdcall CoFreeUnusedLibraries() combase.CoFreeUnusedLibraries @ stdcall CoFreeUnusedLibrariesEx(long long) combase.CoFreeUnusedLibrariesEx @ stdcall CoGetActivationState(int128 long ptr) combase.CoGetActivationState -@ stdcall CoGetApartmentType(ptr ptr) +@ stdcall CoGetApartmentType(ptr ptr) combase.CoGetApartmentType @ stdcall CoGetCallContext(ptr ptr) combase.CoGetCallContext @ stdcall CoGetCallState(long ptr) combase.CoGetCallState @ stdcall CoGetCallerTID(ptr)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/apartment.c | 23 +--- dlls/combase/combase.c | 209 ++++++++++++++++++++++++++++- dlls/combase/combase.spec | 3 +- dlls/combase/combase_private.h | 34 +++++ dlls/combase/rpc.c | 238 +++++++++++++++++++++++++++++++++ dlls/ole32/compobj.c | 203 ---------------------------- dlls/ole32/compobj_private.h | 5 - dlls/ole32/ole32.spec | 2 +- dlls/ole32/rpc.c | 228 ------------------------------- 9 files changed, 481 insertions(+), 464 deletions(-)
diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c index 2d1f7a75744..3df8b165c13 100644 --- a/dlls/combase/apartment.c +++ b/dlls/combase/apartment.c @@ -49,27 +49,6 @@ enum comclass_threadingmodel ThreadingModel_Neutral = 5 };
-enum class_reg_data_origin -{ - CLASS_REG_ACTCTX, - CLASS_REG_REGISTRY, -}; - -struct class_reg_data -{ - enum class_reg_data_origin origin; - union - { - struct - { - const WCHAR *module_name; - DWORD threading_model; - HANDLE hactctx; - } actctx; - HKEY hkey; - } u; -}; - static struct apartment *mta; static struct apartment *main_sta; /* the first STA */ static struct list apts = LIST_INIT(apts); @@ -1048,7 +1027,7 @@ static enum comclass_threadingmodel get_threading_model(const struct class_reg_d return data->u.actctx.threading_model; }
-HRESULT WINAPI apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, +HRESULT apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) { WCHAR dllpath[MAX_PATH+1]; diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 47e31ebad14..228260ba214 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -38,9 +38,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
HINSTANCE hProxyDll;
-#define CHARS_IN_GUID 39 - +/* Ole32 exports */ extern void WINAPI DestroyRunningObjectTable(void); +extern HRESULT WINAPI Ole32DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj);
/* * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed @@ -257,7 +257,7 @@ static LSTATUS open_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKE return RtlNtStatusToDosError(NtOpenKey((HANDLE *)retkey, access, &attr)); }
-static HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey) +HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey) { static const WCHAR clsidW[] = L"CLSID\"; WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(clsidW) - 1]; @@ -288,6 +288,42 @@ static HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM a return S_OK; }
+/* open HKCR\AppId\{string form of appid clsid} key */ +HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey) +{ + static const WCHAR appidkeyW[] = L"AppId\"; + DWORD res; + WCHAR buf[CHARS_IN_GUID]; + WCHAR keyname[ARRAY_SIZE(appidkeyW) + CHARS_IN_GUID]; + DWORD size; + HKEY hkey; + DWORD type; + HRESULT hr; + + /* read the AppID value under the class's key */ + hr = open_key_for_clsid(clsid, NULL, KEY_READ, &hkey); + if (FAILED(hr)) + return hr; + + size = sizeof(buf); + res = RegQueryValueExW(hkey, L"AppId", NULL, &type, (LPBYTE)buf, &size); + RegCloseKey(hkey); + if (res == ERROR_FILE_NOT_FOUND) + return REGDB_E_KEYMISSING; + else if (res != ERROR_SUCCESS || type!=REG_SZ) + return REGDB_E_READREGDB; + + lstrcpyW(keyname, appidkeyW); + lstrcatW(keyname, buf); + res = open_classes_key(HKEY_CLASSES_ROOT, keyname, access, subkey); + if (res == ERROR_FILE_NOT_FOUND) + return REGDB_E_KEYMISSING; + else if (res != ERROR_SUCCESS) + return REGDB_E_READREGDB; + + return S_OK; +} + /*********************************************************************** * InternalTlsAllocData (combase.@) */ @@ -1443,6 +1479,173 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx(REFCLSID rclsid, IUnknown *o return return_multi_qi(unk, count, results, TRUE); }
+/*********************************************************************** + * CoGetClassObject (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD clscontext, + COSERVERINFO *server_info, REFIID riid, void **obj) +{ + struct class_reg_data clsreg = { 0 }; + IUnknown *regClassObject; + HRESULT hr = E_UNEXPECTED; + struct apartment *apt; + + TRACE("%s, %s\n", debugstr_guid(rclsid), debugstr_guid(riid)); + + if (!obj) + return E_INVALIDARG; + + *obj = NULL; + + if (!(apt = apartment_get_current_or_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + + if (server_info) + FIXME("server_info name %s, authinfo %p\n", debugstr_w(server_info->pwszName), server_info->pAuthInfo); + + if (clscontext & CLSCTX_INPROC_SERVER) + { + if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler) || + IsEqualCLSID(rclsid, &CLSID_GlobalOptions) || + IsEqualCLSID(rclsid, &CLSID_ManualResetEvent) || + IsEqualCLSID(rclsid, &CLSID_StdGlobalInterfaceTable)) + { + apartment_release(apt); + return Ole32DllGetClassObject(rclsid, riid, obj); + } + } + + if (clscontext & CLSCTX_INPROC) + { + ACTCTX_SECTION_KEYED_DATA data; + + data.cbSize = sizeof(data); + /* search activation context first */ + if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, + ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, rclsid, &data)) + { + struct comclassredirect_data *comclass = (struct comclassredirect_data *)data.lpData; + + clsreg.u.actctx.module_name = (WCHAR *)((BYTE *)data.lpSectionBase + comclass->name_offset); + clsreg.u.actctx.hactctx = data.hActCtx; + clsreg.u.actctx.threading_model = comclass->model; + clsreg.origin = CLASS_REG_ACTCTX; + + hr = apartment_get_inproc_class_object(apt, &clsreg, &comclass->clsid, riid, + !(clscontext & WINE_CLSCTX_DONT_HOST), obj); + ReleaseActCtx(data.hActCtx); + apartment_release(apt); + return hr; + } + } + + /* + * First, try and see if we can't match the class ID with one of the + * registered classes. + */ + if (InternalGetRegisteredClassObject(apt, rclsid, clscontext, ®ClassObject) == S_OK) + { + hr = IUnknown_QueryInterface(regClassObject, riid, obj); + IUnknown_Release(regClassObject); + apartment_release(apt); + return hr; + } + + /* First try in-process server */ + if (clscontext & CLSCTX_INPROC_SERVER) + { + HKEY hkey; + + hr = open_key_for_clsid(rclsid, L"InprocServer32", KEY_READ, &hkey); + if (FAILED(hr)) + { + if (hr == REGDB_E_CLASSNOTREG) + ERR("class %s not registered\n", debugstr_guid(rclsid)); + else if (hr == REGDB_E_KEYMISSING) + { + WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid)); + hr = REGDB_E_CLASSNOTREG; + } + } + + if (SUCCEEDED(hr)) + { + clsreg.u.hkey = hkey; + clsreg.origin = CLASS_REG_REGISTRY; + + hr = apartment_get_inproc_class_object(apt, &clsreg, rclsid, riid, !(clscontext & WINE_CLSCTX_DONT_HOST), obj); + RegCloseKey(hkey); + } + + /* return if we got a class, otherwise fall through to one of the + * other types */ + if (SUCCEEDED(hr)) + { + apartment_release(apt); + return hr; + } + } + + /* Next try in-process handler */ + if (clscontext & CLSCTX_INPROC_HANDLER) + { + HKEY hkey; + + hr = open_key_for_clsid(rclsid, L"InprocHandler32", KEY_READ, &hkey); + if (FAILED(hr)) + { + if (hr == REGDB_E_CLASSNOTREG) + ERR("class %s not registered\n", debugstr_guid(rclsid)); + else if (hr == REGDB_E_KEYMISSING) + { + WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid)); + hr = REGDB_E_CLASSNOTREG; + } + } + + if (SUCCEEDED(hr)) + { + clsreg.u.hkey = hkey; + clsreg.origin = CLASS_REG_REGISTRY; + + hr = apartment_get_inproc_class_object(apt, &clsreg, rclsid, riid, !(clscontext & WINE_CLSCTX_DONT_HOST), obj); + RegCloseKey(hkey); + } + + /* return if we got a class, otherwise fall through to one of the + * other types */ + if (SUCCEEDED(hr)) + { + apartment_release(apt); + return hr; + } + } + apartment_release(apt); + + /* Next try out of process */ + if (clscontext & CLSCTX_LOCAL_SERVER) + { + hr = rpc_get_local_class_object(rclsid, riid, obj); + if (SUCCEEDED(hr)) + return hr; + } + + /* Finally try remote: this requires networked DCOM (a lot of work) */ + if (clscontext & CLSCTX_REMOTE_SERVER) + { + FIXME ("CLSCTX_REMOTE_SERVER not supported\n"); + hr = REGDB_E_CLASSNOTREG; + } + + if (FAILED(hr)) + ERR("no class object %s could be created for context %#x\n", debugstr_guid(rclsid), clscontext); + + return hr; +} + /*********************************************************************** * CoFreeUnusedLibraries (combase.@) */ diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 143de28d7d6..f2f4506ae50 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -101,7 +101,7 @@ @ stdcall CoGetCallState(long ptr) @ stdcall CoGetCallerTID(ptr) ole32.CoGetCallerTID @ stub CoGetCancelObject -@ stdcall CoGetClassObject(ptr long ptr ptr ptr) ole32.CoGetClassObject +@ stdcall CoGetClassObject(ptr long ptr ptr ptr) @ stub CoGetClassVersion @ stdcall CoGetContextToken(ptr) @ stdcall CoGetCurrentLogicalThreadId(ptr) @@ -355,7 +355,6 @@ @ stdcall apartment_release(ptr) @ stdcall enter_apartment(ptr long) @ stdcall leave_apartment(ptr) -@ stdcall apartment_get_inproc_class_object(ptr ptr ptr ptr long ptr) @ stdcall apartment_findfromoxid(int64) @ stdcall apartment_getwindow(ptr) @ stdcall apartment_global_cleanup() diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 1f80f1a12be..c6d090707a7 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -54,10 +54,19 @@ struct apartment struct list usage_cookies; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */ };
+extern HRESULT WINAPI InternalGetRegisteredClassObject(struct apartment *apt, REFGUID guid, + DWORD clscontext, IUnknown **obj); + +HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN; +HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN; + /* DCOM messages used by the apartment window (not compatible with native) */ #define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */ #define DM_HOSTOBJECT (WM_USER + 1) /* WPARAM = 0, LPARAM = (struct host_object_params *) */
+#define WINE_CLSCTX_DONT_HOST 0x80000000 +#define CHARS_IN_GUID 39 + /* this is what is stored in TEB->ReservedForOle */ struct tlsdata { @@ -102,6 +111,7 @@ void apartment_freeunusedlibraries(struct apartment *apt, DWORD unload_delay) DE
/* RpcSs interface */ HRESULT rpcss_get_next_seqid(DWORD *id) DECLSPEC_HIDDEN; +HRESULT rpc_get_local_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
/* stub managers hold refs on the object and each interface stub */ struct stub_manager @@ -131,12 +141,36 @@ struct stub_manager BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */ };
+enum class_reg_data_origin +{ + CLASS_REG_ACTCTX, + CLASS_REG_REGISTRY, +}; + +struct class_reg_data +{ + enum class_reg_data_origin origin; + union + { + struct + { + const WCHAR *module_name; + DWORD threading_model; + HANDLE hactctx; + } actctx; + HKEY hkey; + } u; +}; + HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model); void WINAPI leave_apartment(struct tlsdata *data); void WINAPI apartment_release(struct apartment *apt); +struct apartment * WINAPI apartment_get_current_or_mta(void); HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) DECLSPEC_HIDDEN; void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) DECLSPEC_HIDDEN; struct apartment * apartment_get_mta(void) DECLSPEC_HIDDEN; +HRESULT apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, + REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) DECLSPEC_HIDDEN;
/* Stub Manager */
diff --git a/dlls/combase/rpc.c b/dlls/combase/rpc.c index 3b531661726..2b655da8bad 100644 --- a/dlls/combase/rpc.c +++ b/dlls/combase/rpc.c @@ -16,14 +16,19 @@
#include <stdarg.h>
+#define COBJMACROS + #include "windef.h" #include "winbase.h" #include "winsvc.h" +#include "servprov.h"
#include "wine/debug.h" #include "wine/exception.h" #include "wine/heap.h"
+#include "combase_private.h" + #include "irpcss.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -221,3 +226,236 @@ HRESULT WINAPI InternalIrotRevoke(IrotCookie cookie, IrotContextHandle *ctxt_han hr = IrotRevoke(get_irot_handle(), cookie, ctxt_handle, object, moniker); RPCSS_CALL_END } + +static void get_localserver_pipe_name(WCHAR *pipefn, REFCLSID rclsid) +{ + static const WCHAR wszPipeRef[] = {'\','\','.','\','p','i','p','e','\',0}; + lstrcpyW(pipefn, wszPipeRef); + StringFromGUID2(rclsid, pipefn + ARRAY_SIZE(wszPipeRef) - 1, CHARS_IN_GUID); +} + +static DWORD start_local_service(const WCHAR *name, DWORD num, LPCWSTR *params) +{ + SC_HANDLE handle, hsvc; + DWORD r = ERROR_FUNCTION_FAILED; + + TRACE("Starting service %s %d params\n", debugstr_w(name), num); + + handle = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); + if (!handle) + return r; + hsvc = OpenServiceW(handle, name, SERVICE_START); + if (hsvc) + { + if(StartServiceW(hsvc, num, params)) + r = ERROR_SUCCESS; + else + r = GetLastError(); + if (r == ERROR_SERVICE_ALREADY_RUNNING) + r = ERROR_SUCCESS; + CloseServiceHandle(hsvc); + } + else + r = GetLastError(); + CloseServiceHandle(handle); + + TRACE("StartService returned error %u (%s)\n", r, (r == ERROR_SUCCESS) ? "ok":"failed"); + + return r; +} + +/* + * create_local_service() - start a COM server in a service + * + * To start a Local Service, we read the AppID value under + * the class's CLSID key, then open the HKCR\AppId key specified + * there and check for a LocalService value. + * + * Note: Local Services are not supported under Windows 9x + */ +static HRESULT create_local_service(REFCLSID rclsid) +{ + HRESULT hr; + WCHAR buf[CHARS_IN_GUID]; + HKEY hkey; + LONG r; + DWORD type, sz; + + TRACE("Attempting to start Local service for %s\n", debugstr_guid(rclsid)); + + hr = open_appidkey_from_clsid(rclsid, KEY_READ, &hkey); + if (FAILED(hr)) + return hr; + + /* read the LocalService and ServiceParameters values from the AppID key */ + sz = sizeof buf; + r = RegQueryValueExW(hkey, L"LocalService", NULL, &type, (LPBYTE)buf, &sz); + if (r == ERROR_SUCCESS && type == REG_SZ) + { + DWORD num_args = 0; + LPWSTR args[1] = { NULL }; + + /* + * FIXME: I'm not really sure how to deal with the service parameters. + * I suspect that the string returned from RegQueryValueExW + * should be split into a number of arguments by spaces. + * It would make more sense if ServiceParams contained a + * REG_MULTI_SZ here, but it's a REG_SZ for the services + * that I'm interested in for the moment. + */ + r = RegQueryValueExW(hkey, L"ServiceParams", NULL, &type, NULL, &sz); + if (r == ERROR_SUCCESS && type == REG_SZ && sz) + { + args[0] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz); + num_args++; + RegQueryValueExW(hkey, L"ServiceParams", NULL, &type, (LPBYTE)args[0], &sz); + } + r = start_local_service(buf, num_args, (LPCWSTR *)args); + if (r != ERROR_SUCCESS) + hr = REGDB_E_CLASSNOTREG; /* FIXME: check retval */ + HeapFree(GetProcessHeap(),0,args[0]); + } + else + { + WARN("No LocalService value\n"); + hr = REGDB_E_CLASSNOTREG; /* FIXME: check retval */ + } + RegCloseKey(hkey); + + return hr; +} + +static HRESULT create_server(REFCLSID rclsid, HANDLE *process) +{ + static const WCHAR embeddingW[] = L" -Embedding"; + HKEY key; + HRESULT hr; + WCHAR command[MAX_PATH + ARRAY_SIZE(embeddingW)]; + DWORD size = (MAX_PATH+1) * sizeof(WCHAR); + STARTUPINFOW sinfo; + PROCESS_INFORMATION pinfo; + LONG ret; + + hr = open_key_for_clsid(rclsid, L"LocalServer32", KEY_READ, &key); + if (FAILED(hr)) + { + ERR("class %s not registered\n", debugstr_guid(rclsid)); + return hr; + } + + ret = RegQueryValueExW(key, NULL, NULL, NULL, (LPBYTE)command, &size); + RegCloseKey(key); + if (ret) + { + WARN("No default value for LocalServer32 key\n"); + return REGDB_E_CLASSNOTREG; /* FIXME: check retval */ + } + + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.cb = sizeof(sinfo); + + /* EXE servers are started with the -Embedding switch. */ + + lstrcatW(command, embeddingW); + + TRACE("activating local server %s for %s\n", debugstr_w(command), debugstr_guid(rclsid)); + + /* FIXME: Win2003 supports a ServerExecutable value that is passed into + * CreateProcess */ + if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) + { + WARN("failed to run local server %s\n", debugstr_w(command)); + return HRESULT_FROM_WIN32(GetLastError()); + } + *process = pinfo.hProcess; + CloseHandle(pinfo.hThread); + + return S_OK; +} + +/* FIXME: should call to rpcss instead */ +HRESULT rpc_get_local_class_object(REFCLSID rclsid, REFIID riid, void **obj) +{ + HRESULT hr; + HANDLE hPipe; + WCHAR pipefn[100]; + DWORD res, bufferlen; + char marshalbuffer[200]; + IStream *pStm; + LARGE_INTEGER seekto; + ULARGE_INTEGER newpos; + int tries = 0; + IServiceProvider *local_server; + + static const int MAXTRIES = 30; /* 30 seconds */ + + TRACE("rclsid %s, riid %s\n", debugstr_guid(rclsid), debugstr_guid(riid)); + + get_localserver_pipe_name(pipefn, rclsid); + + while (tries++ < MAXTRIES) + { + TRACE("waiting for %s\n", debugstr_w(pipefn)); + + WaitNamedPipeW(pipefn, NMPWAIT_WAIT_FOREVER); + hPipe = CreateFileW(pipefn, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); + if (hPipe == INVALID_HANDLE_VALUE) + { + DWORD index; + DWORD start_ticks; + HANDLE process = 0; + if (tries == 1) + { + if ((hr = create_local_service(rclsid)) && (hr = create_server(rclsid, &process))) + return hr; + } + else + { + WARN("Connecting to %s, no response yet, retrying: le is %u\n", debugstr_w(pipefn), GetLastError()); + } + /* wait for one second, even if messages arrive */ + start_ticks = GetTickCount(); + do + { + if (SUCCEEDED(CoWaitForMultipleHandles(0, 1000, (process != 0), &process, &index)) && process && !index) + { + WARN("server for %s failed to start\n", debugstr_guid(rclsid)); + CloseHandle( hPipe ); + CloseHandle( process ); + return E_NOINTERFACE; + } + } while (GetTickCount() - start_ticks < 1000); + if (process) CloseHandle(process); + continue; + } + bufferlen = 0; + if (!ReadFile(hPipe, marshalbuffer, sizeof(marshalbuffer), &bufferlen, NULL)) + { + FIXME("Failed to read marshal id from classfactory of %s.\n", debugstr_guid(rclsid)); + CloseHandle(hPipe); + Sleep(1000); + continue; + } + TRACE("read marshal id from pipe\n"); + CloseHandle(hPipe); + break; + } + + if (tries >= MAXTRIES) + return E_NOINTERFACE; + + hr = CreateStreamOnHGlobal(0, TRUE, &pStm); + if (hr != S_OK) return hr; + hr = IStream_Write(pStm, marshalbuffer, bufferlen, &res); + if (hr != S_OK) goto out; + seekto.u.LowPart = 0;seekto.u.HighPart = 0; + hr = IStream_Seek(pStm, seekto, STREAM_SEEK_SET, &newpos); + TRACE("unmarshalling local server\n"); + hr = CoUnmarshalInterface(pStm, &IID_IServiceProvider, (void **)&local_server); + if(SUCCEEDED(hr)) + hr = IServiceProvider_QueryService(local_server, rclsid, riid, obj); + IServiceProvider_Release(local_server); +out: + IStream_Release(pStm); + return hr; +} diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 975af46f854..45187fc8113 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -985,209 +985,6 @@ HRESULT WINAPI CoRegisterClassObject( return S_OK; }
-/*********************************************************************** - * CoGetClassObject [OLE32.@] - * - * Creates an object of the specified class. - * - * PARAMS - * rclsid [I] Class ID to create an instance of. - * dwClsContext [I] Flags to restrict the location of the created instance. - * pServerInfo [I] Optional. Details for connecting to a remote server. - * iid [I] The ID of the interface of the instance to return. - * ppv [O] On returns, contains a pointer to the specified interface of the object. - * - * RETURNS - * Success: S_OK - * Failure: HRESULT code. - * - * NOTES - * The dwClsContext parameter can be one or more of the following: - *| CLSCTX_INPROC_SERVER - Use an in-process server, such as from a DLL. - *| CLSCTX_INPROC_HANDLER - Use an in-process object which handles certain functions for an object running in another process. - *| CLSCTX_LOCAL_SERVER - Connect to an object running in another process. - *| CLSCTX_REMOTE_SERVER - Connect to an object running on another machine. - * - * SEE ALSO - * CoCreateInstance() - */ -HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( - REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, - REFIID iid, LPVOID *ppv) -{ - struct class_reg_data clsreg = { 0 }; - IUnknown *regClassObject; - HRESULT hres = E_UNEXPECTED; - struct apartment *apt; - - TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid)); - - if (!ppv) - return E_INVALIDARG; - - *ppv = NULL; - - if (!(apt = apartment_get_current_or_mta())) - { - ERR("apartment not initialised\n"); - return CO_E_NOTINITIALIZED; - } - - if (pServerInfo) { - FIXME("pServerInfo->name=%s pAuthInfo=%p\n", - debugstr_w(pServerInfo->pwszName), pServerInfo->pAuthInfo); - } - - if (CLSCTX_INPROC_SERVER & dwClsContext) - { - if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler) || - IsEqualCLSID(rclsid, &CLSID_GlobalOptions) || - IsEqualCLSID(rclsid, &CLSID_ManualResetEvent) || - IsEqualCLSID(rclsid, &CLSID_StdGlobalInterfaceTable)) - { - apartment_release(apt); - return Ole32DllGetClassObject(rclsid, iid, ppv); - } - } - - if (CLSCTX_INPROC & dwClsContext) - { - ACTCTX_SECTION_KEYED_DATA data; - - data.cbSize = sizeof(data); - /* search activation context first */ - if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, - ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, - rclsid, &data)) - { - struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData; - - clsreg.u.actctx.module_name = (WCHAR *)((BYTE *)data.lpSectionBase + comclass->name_offset); - clsreg.u.actctx.hactctx = data.hActCtx; - clsreg.u.actctx.threading_model = comclass->model; - clsreg.origin = CLASS_REG_ACTCTX; - - hres = apartment_get_inproc_class_object(apt, &clsreg, &comclass->clsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv); - ReleaseActCtx(data.hActCtx); - apartment_release(apt); - return hres; - } - } - - /* - * First, try and see if we can't match the class ID with one of the - * registered classes. - */ - if (S_OK == InternalGetRegisteredClassObject(apt, rclsid, dwClsContext, - ®ClassObject)) - { - /* Get the required interface from the retrieved pointer. */ - hres = IUnknown_QueryInterface(regClassObject, iid, ppv); - - /* - * Since QI got another reference on the pointer, we want to release the - * one we already have. If QI was unsuccessful, this will release the object. This - * is good since we are not returning it in the "out" parameter. - */ - IUnknown_Release(regClassObject); - apartment_release(apt); - return hres; - } - - /* First try in-process server */ - if (CLSCTX_INPROC_SERVER & dwClsContext) - { - static const WCHAR wszInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; - HKEY hkey; - - hres = COM_OpenKeyForCLSID(rclsid, wszInprocServer32, KEY_READ, &hkey); - if (FAILED(hres)) - { - if (hres == REGDB_E_CLASSNOTREG) - ERR("class %s not registered\n", debugstr_guid(rclsid)); - else if (hres == REGDB_E_KEYMISSING) - { - WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid)); - hres = REGDB_E_CLASSNOTREG; - } - } - - if (SUCCEEDED(hres)) - { - clsreg.u.hkey = hkey; - clsreg.origin = CLASS_REG_REGISTRY; - - hres = apartment_get_inproc_class_object(apt, &clsreg, rclsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv); - RegCloseKey(hkey); - } - - /* return if we got a class, otherwise fall through to one of the - * other types */ - if (SUCCEEDED(hres)) - { - apartment_release(apt); - return hres; - } - } - - /* Next try in-process handler */ - if (CLSCTX_INPROC_HANDLER & dwClsContext) - { - static const WCHAR wszInprocHandler32[] = {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0}; - HKEY hkey; - - hres = COM_OpenKeyForCLSID(rclsid, wszInprocHandler32, KEY_READ, &hkey); - if (FAILED(hres)) - { - if (hres == REGDB_E_CLASSNOTREG) - ERR("class %s not registered\n", debugstr_guid(rclsid)); - else if (hres == REGDB_E_KEYMISSING) - { - WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid)); - hres = REGDB_E_CLASSNOTREG; - } - } - - if (SUCCEEDED(hres)) - { - clsreg.u.hkey = hkey; - clsreg.origin = CLASS_REG_REGISTRY; - - hres = apartment_get_inproc_class_object(apt, &clsreg, rclsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv); - RegCloseKey(hkey); - } - - /* return if we got a class, otherwise fall through to one of the - * other types */ - if (SUCCEEDED(hres)) - { - apartment_release(apt); - return hres; - } - } - apartment_release(apt); - - /* Next try out of process */ - if (CLSCTX_LOCAL_SERVER & dwClsContext) - { - hres = RPC_GetLocalClassObject(rclsid,iid,ppv); - if (SUCCEEDED(hres)) - return hres; - } - - /* Finally try remote: this requires networked DCOM (a lot of work) */ - if (CLSCTX_REMOTE_SERVER & dwClsContext) - { - FIXME ("CLSCTX_REMOTE_SERVER not supported\n"); - hres = REGDB_E_CLASSNOTREG; - } - - if (FAILED(hres)) - ERR("no class object %s could be created for context 0x%x\n", - debugstr_guid(rclsid), dwClsContext); - return hres; -} - /*********************************************************************** * CoResumeClassObjects (OLE32.@) * diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 9d6a1d1b794..5fc100e8163 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -252,11 +252,6 @@ extern HWND WINAPI apartment_getwindow(const struct apartment *apt) DECLSPEC_HID extern HRESULT WINAPI enter_apartment(struct oletls *info, DWORD model) DECLSPEC_HIDDEN; void WINAPI leave_apartment(struct oletls *info) DECLSPEC_HIDDEN; extern struct apartment * WINAPI apartment_get_current_or_mta(void) DECLSPEC_HIDDEN; - -struct class_reg_data; -extern HRESULT WINAPI apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, - REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) DECLSPEC_HIDDEN; - extern HRESULT WINAPI apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN; extern void WINAPI apartment_global_cleanup(void) DECLSPEC_HIDDEN;
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 0b38e74388a..9c6b9396e17 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -30,7 +30,7 @@ @ stdcall CoGetCallContext(ptr ptr) combase.CoGetCallContext @ stdcall CoGetCallState(long ptr) combase.CoGetCallState @ stdcall CoGetCallerTID(ptr) -@ stdcall CoGetClassObject(ptr long ptr ptr ptr) +@ stdcall CoGetClassObject(ptr long ptr ptr ptr) combase.CoGetClassObject @ stdcall CoGetContextToken(ptr) combase.CoGetContextToken @ stdcall CoGetCurrentLogicalThreadId(ptr) combase.CoGetCurrentLogicalThreadId @ stdcall CoGetCurrentProcess() combase.CoGetCurrentProcess diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index 1c88ae21543..eb76d9cb668 100644 --- a/dlls/ole32/rpc.c +++ b/dlls/ole32/rpc.c @@ -1649,150 +1649,6 @@ void RPC_StartRemoting(struct apartment *apt) start_apartment_remote_unknown(apt); }
- -static HRESULT create_server(REFCLSID rclsid, HANDLE *process) -{ - static const WCHAR wszLocalServer32[] = { 'L','o','c','a','l','S','e','r','v','e','r','3','2',0 }; - static const WCHAR embedding[] = { ' ', '-','E','m','b','e','d','d','i','n','g',0 }; - HKEY key; - HRESULT hres; - WCHAR command[MAX_PATH+ARRAY_SIZE(embedding)]; - DWORD size = (MAX_PATH+1) * sizeof(WCHAR); - STARTUPINFOW sinfo; - PROCESS_INFORMATION pinfo; - LONG ret; - - hres = COM_OpenKeyForCLSID(rclsid, wszLocalServer32, KEY_READ, &key); - if (FAILED(hres)) { - ERR("class %s not registered\n", debugstr_guid(rclsid)); - return hres; - } - - ret = RegQueryValueExW(key, NULL, NULL, NULL, (LPBYTE)command, &size); - RegCloseKey(key); - if (ret) { - WARN("No default value for LocalServer32 key\n"); - return REGDB_E_CLASSNOTREG; /* FIXME: check retval */ - } - - memset(&sinfo,0,sizeof(sinfo)); - sinfo.cb = sizeof(sinfo); - - /* EXE servers are started with the -Embedding switch. */ - - lstrcatW(command, embedding); - - TRACE("activating local server %s for %s\n", debugstr_w(command), debugstr_guid(rclsid)); - - /* FIXME: Win2003 supports a ServerExecutable value that is passed into - * CreateProcess */ - if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) { - WARN("failed to run local server %s\n", debugstr_w(command)); - return HRESULT_FROM_WIN32(GetLastError()); - } - *process = pinfo.hProcess; - CloseHandle(pinfo.hThread); - - return S_OK; -} - -/* - * start_local_service() - start a service given its name and parameters - */ -static DWORD start_local_service(LPCWSTR name, DWORD num, LPCWSTR *params) -{ - SC_HANDLE handle, hsvc; - DWORD r = ERROR_FUNCTION_FAILED; - - TRACE("Starting service %s %d params\n", debugstr_w(name), num); - - handle = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); - if (!handle) - return r; - hsvc = OpenServiceW(handle, name, SERVICE_START); - if (hsvc) - { - if(StartServiceW(hsvc, num, params)) - r = ERROR_SUCCESS; - else - r = GetLastError(); - if (r == ERROR_SERVICE_ALREADY_RUNNING) - r = ERROR_SUCCESS; - CloseServiceHandle(hsvc); - } - else - r = GetLastError(); - CloseServiceHandle(handle); - - TRACE("StartService returned error %u (%s)\n", r, (r == ERROR_SUCCESS) ? "ok":"failed"); - - return r; -} - -/* - * create_local_service() - start a COM server in a service - * - * To start a Local Service, we read the AppID value under - * the class's CLSID key, then open the HKCR\AppId key specified - * there and check for a LocalService value. - * - * Note: Local Services are not supported under Windows 9x - */ -static HRESULT create_local_service(REFCLSID rclsid) -{ - HRESULT hres; - WCHAR buf[CHARS_IN_GUID]; - static const WCHAR szLocalService[] = { 'L','o','c','a','l','S','e','r','v','i','c','e',0 }; - static const WCHAR szServiceParams[] = {'S','e','r','v','i','c','e','P','a','r','a','m','s',0}; - HKEY hkey; - LONG r; - DWORD type, sz; - - TRACE("Attempting to start Local service for %s\n", debugstr_guid(rclsid)); - - hres = COM_OpenKeyForAppIdFromCLSID(rclsid, KEY_READ, &hkey); - if (FAILED(hres)) - return hres; - - /* read the LocalService and ServiceParameters values from the AppID key */ - sz = sizeof buf; - r = RegQueryValueExW(hkey, szLocalService, NULL, &type, (LPBYTE)buf, &sz); - if (r==ERROR_SUCCESS && type==REG_SZ) - { - DWORD num_args = 0; - LPWSTR args[1] = { NULL }; - - /* - * FIXME: I'm not really sure how to deal with the service parameters. - * I suspect that the string returned from RegQueryValueExW - * should be split into a number of arguments by spaces. - * It would make more sense if ServiceParams contained a - * REG_MULTI_SZ here, but it's a REG_SZ for the services - * that I'm interested in for the moment. - */ - r = RegQueryValueExW(hkey, szServiceParams, NULL, &type, NULL, &sz); - if (r == ERROR_SUCCESS && type == REG_SZ && sz) - { - args[0] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz); - num_args++; - RegQueryValueExW(hkey, szServiceParams, NULL, &type, (LPBYTE)args[0], &sz); - } - r = start_local_service(buf, num_args, (LPCWSTR *)args); - if (r != ERROR_SUCCESS) - hres = REGDB_E_CLASSNOTREG; /* FIXME: check retval */ - HeapFree(GetProcessHeap(),0,args[0]); - } - else - { - WARN("No LocalService value\n"); - hres = REGDB_E_CLASSNOTREG; /* FIXME: check retval */ - } - RegCloseKey(hkey); - - return hres; -} - - static void get_localserver_pipe_name(WCHAR *pipefn, REFCLSID rclsid) { static const WCHAR wszPipeRef[] = {'\','\','.','\','p','i','p','e','\',0}; @@ -1800,90 +1656,6 @@ static void get_localserver_pipe_name(WCHAR *pipefn, REFCLSID rclsid) StringFromGUID2(rclsid, pipefn + ARRAY_SIZE(wszPipeRef) - 1, CHARS_IN_GUID); }
-/* FIXME: should call to rpcss instead */ -HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) -{ - HRESULT hres; - HANDLE hPipe; - WCHAR pipefn[100]; - DWORD res, bufferlen; - char marshalbuffer[200]; - IStream *pStm; - LARGE_INTEGER seekto; - ULARGE_INTEGER newpos; - int tries = 0; - IServiceProvider *local_server; - - static const int MAXTRIES = 30; /* 30 seconds */ - - TRACE("rclsid=%s, iid=%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); - - get_localserver_pipe_name(pipefn, rclsid); - - while (tries++ < MAXTRIES) { - TRACE("waiting for %s\n", debugstr_w(pipefn)); - - WaitNamedPipeW( pipefn, NMPWAIT_WAIT_FOREVER ); - hPipe = CreateFileW(pipefn, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); - if (hPipe == INVALID_HANDLE_VALUE) { - DWORD index; - DWORD start_ticks; - HANDLE process = 0; - if (tries == 1) { - if ( (hres = create_local_service(rclsid)) && - (hres = create_server(rclsid, &process)) ) - return hres; - } else { - WARN("Connecting to %s, no response yet, retrying: le is %u\n", debugstr_w(pipefn), GetLastError()); - } - /* wait for one second, even if messages arrive */ - start_ticks = GetTickCount(); - do { - if (SUCCEEDED(CoWaitForMultipleHandles(0, 1000, (process != 0), - &process, &index)) && process && !index) - { - WARN( "server for %s failed to start\n", debugstr_guid(rclsid) ); - CloseHandle( hPipe ); - CloseHandle( process ); - return E_NOINTERFACE; - } - } while (GetTickCount() - start_ticks < 1000); - if (process) CloseHandle( process ); - continue; - } - bufferlen = 0; - if (!ReadFile(hPipe,marshalbuffer,sizeof(marshalbuffer),&bufferlen,NULL)) { - FIXME("Failed to read marshal id from classfactory of %s.\n",debugstr_guid(rclsid)); - CloseHandle(hPipe); - Sleep(1000); - continue; - } - TRACE("read marshal id from pipe\n"); - CloseHandle(hPipe); - break; - } - - if (tries >= MAXTRIES) - return E_NOINTERFACE; - - hres = CreateStreamOnHGlobal(0,TRUE,&pStm); - if (hres != S_OK) return hres; - hres = IStream_Write(pStm,marshalbuffer,bufferlen,&res); - if (hres != S_OK) goto out; - seekto.u.LowPart = 0;seekto.u.HighPart = 0; - hres = IStream_Seek(pStm,seekto,STREAM_SEEK_SET,&newpos); - - TRACE("unmarshalling local server\n"); - hres = CoUnmarshalInterface(pStm, &IID_IServiceProvider, (void**)&local_server); - if(SUCCEEDED(hres)) - hres = IServiceProvider_QueryService(local_server, rclsid, iid, ppv); - IServiceProvider_Release(local_server); -out: - IStream_Release(pStm); - return hres; -} - - struct local_server_params { CLSID clsid;
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 22 +++++++++++++++++----- dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 11 ----------- dlls/ole32/compobj_private.h | 3 --- dlls/ole32/moniker.c | 5 +++-- dlls/ole32/ole32.spec | 1 - 6 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 228260ba214..28a63c6c7f4 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -113,8 +113,6 @@ static CRITICAL_SECTION_DEBUG psclsid_cs_debug = }; static CRITICAL_SECTION cs_registered_ps = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
-extern BOOL WINAPI InternalIsInitialized(void); - static struct init_spy *get_spy_entry(struct tlsdata *tlsdata, unsigned int id) { struct init_spy *spy; @@ -324,6 +322,20 @@ HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey) return S_OK; }
+/*********************************************************************** + * InternalIsProcessInitialized (combase.@) + */ +BOOL WINAPI InternalIsProcessInitialized(void) +{ + struct apartment *apt; + + if (!(apt = apartment_get_current_or_mta())) + return FALSE; + apartment_release(apt); + + return TRUE; +} + /*********************************************************************** * InternalTlsAllocData (combase.@) */ @@ -2020,7 +2032,7 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
TRACE("%s, %p\n", debugstr_guid(riid), pclsid);
- if (!InternalIsInitialized()) + if (!InternalIsProcessInitialized()) { ERR("apartment not initialised\n"); return CO_E_NOTINITIALIZED; @@ -2078,7 +2090,7 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
TRACE("%s, %s\n", debugstr_guid(riid), debugstr_guid(rclsid));
- if (!InternalIsInitialized()) + if (!InternalIsProcessInitialized()) { ERR("apartment not initialised\n"); return CO_E_NOTINITIALIZED; @@ -2388,7 +2400,7 @@ HRESULT WINAPI CoGetContextToken(ULONG_PTR *token)
TRACE("%p\n", token);
- if (!InternalIsInitialized()) + if (!InternalIsProcessInitialized()) { ERR("apartment not initialised\n"); return CO_E_NOTINITIALIZED; diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index f2f4506ae50..ea2177ca7ba 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -263,7 +263,7 @@ @ stdcall InternalIrotRegister(ptr ptr ptr ptr long ptr ptr) @ stdcall InternalIrotRevoke(long ptr ptr ptr) @ stub InternalIsApartmentInitialized -@ stub InternalIsProcessInitialized +@ stdcall InternalIsProcessInitialized() @ stub InternalMarshalObjRef @ stub InternalNotifyDDStartOrStop @ stub InternalOleModalLoopBlockFn diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 45187fc8113..dfd81a8d0f5 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1608,17 +1608,6 @@ HRESULT WINAPI CoRegisterSurrogateEx(REFGUID guid, void *reserved) return E_NOTIMPL; }
-BOOL WINAPI InternalIsInitialized(void) -{ - struct apartment *apt; - - if (!(apt = apartment_get_current_or_mta())) - return FALSE; - apartment_release(apt); - - return TRUE; -} - typedef struct { IGlobalOptions IGlobalOptions_iface; LONG ref; diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 5fc100e8163..6e14d69e424 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -351,7 +351,4 @@ static inline HRESULT copy_formatetc(FORMATETC *dst, const FORMATETC *src) extern HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, BOOL copy, IEnumSTATDATA **ppenum) DECLSPEC_HIDDEN;
-extern BOOL WINAPI InternalIsInitialized(void); -extern void WINAPI DestroyRunningObjectTable(void); - #endif /* __WINE_OLE_COMPOBJ_H */ diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index 874b58f99e7..251c3c47849 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -35,7 +35,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
- +/* Combase exports */ +BOOL WINAPI InternalIsProcessInitialized(void); HRESULT WINAPI InternalIrotRegister(const MonikerComparisonData *moniker_data, const InterfaceData *object, const InterfaceData *moniker, const FILETIME *time, DWORD flags, IrotCookie *cookie, IrotContextHandle *ctxt_handle); @@ -720,7 +721,7 @@ HRESULT WINAPI GetRunningObjectTable(DWORD reserved, IRunningObjectTable **ret) if (reserved!=0) return E_UNEXPECTED;
- if (!InternalIsInitialized()) + if (!InternalIsProcessInitialized()) return CO_E_NOTINITIALIZED;
*ret = &rot.IRunningObjectTable_iface; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 9c6b9396e17..c4e7b594fb2 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -298,7 +298,6 @@ @ stdcall WriteFmtUserTypeStg(ptr long ptr) @ stub WriteOleStg @ stub WriteStringStream -@ stdcall InternalIsInitialized() @ stdcall InternalGetRegisteredClassObject(ptr ptr long ptr) @ stdcall InternalRevokeAllClasses(ptr) @ stdcall Internal_apartment_disconnectproxies(ptr)
Signed-off-by: Huw Davies huw@codeweavers.com