[1/2] ole32: Reorder some compobj functions to avoid forward declarations.
Francois Gouget
fgouget at free.fr
Mon Jun 22 03:47:17 CDT 2009
---
dlls/ole32/compobj.c | 681 ++++++++++++++++++++++++--------------------------
1 files changed, 333 insertions(+), 348 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 586a930..276fa50 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -71,11 +71,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
* This section defines variables internal to the COM module.
*/
-static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid,
- DWORD dwClsContext, LPUNKNOWN* ppUnk);
-static void COM_RevokeAllClasses(const struct apartment *apt);
-static HRESULT get_inproc_class_object(APARTMENT *apt, HKEY hkeydll, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv);
-
static APARTMENT *MTA; /* protected by csApartment */
static APARTMENT *MainApartment; /* the first STA apartment */
static struct list apts = LIST_INIT( apts ); /* protected by csApartment */
@@ -172,71 +167,154 @@ static CRITICAL_SECTION_DEBUG dll_cs_debug =
};
static CRITICAL_SECTION csOpenDllList = { &dll_cs_debug, -1, 0, 0, 0, 0 };
-struct apartment_loaded_dll
+/*****************************************************************************
+ * This section contains OpenDllList implementation
+ */
+
+static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name)
{
- struct list entry;
- OpenDll *dll;
- DWORD unload_time;
- BOOL multi_threaded;
-};
+ OpenDll *ptr;
+ OpenDll *ret = NULL;
+ EnterCriticalSection(&csOpenDllList);
+ LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry)
+ {
+ if (!strcmpiW(library_name, ptr->library_name) &&
+ (InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */)
+ {
+ ret = ptr;
+ break;
+ }
+ }
+ LeaveCriticalSection(&csOpenDllList);
+ return ret;
+}
-static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ',
- '0','x','#','#','#','#','#','#','#','#',' ',0};
-static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
- BOOL apartment_threaded,
- REFCLSID rclsid, REFIID riid, void **ppv);
-static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay);
+/* caller must ensure that library_name is not already in the open dll list */
+static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
+{
+ OpenDll *entry;
+ int len;
+ HRESULT hr = S_OK;
+ HANDLE hLibrary;
+ DllCanUnloadNowFunc DllCanUnloadNow;
+ DllGetClassObjectFunc DllGetClassObject;
+
+ TRACE("\n");
-static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret);
-static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name);
-static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry);
+ *ret = COMPOBJ_DllList_Get(library_name);
+ if (*ret) return S_OK;
-static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen);
+ /* do this outside the csOpenDllList to avoid creating a lock dependency on
+ * the loader lock */
+ hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (!hLibrary)
+ {
+ ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
+ /* failure: DLL could not be loaded */
+ return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
+ }
-static void COMPOBJ_InitProcess( void )
-{
- WNDCLASSW wclass;
+ DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow");
+ /* Note: failing to find DllCanUnloadNow is not a failure */
+ DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject");
+ if (!DllGetClassObject)
+ {
+ /* failure: the dll did not export DllGetClassObject */
+ ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name));
+ FreeLibrary(hLibrary);
+ return CO_E_DLLNOTFOUND;
+ }
- /* Dispatching to the correct thread in an apartment is done through
- * window messages rather than RPC transports. When an interface is
- * marshalled into another apartment in the same process, a window of the
- * following class is created. The *caller* of CoMarshalInterface (i.e., the
- * application) is responsible for pumping the message loop in that thread.
- * The WM_USER messages which point to the RPCs are then dispatched to
- * apartment_wndproc by the user's code from the apartment in which the
- * interface was unmarshalled.
- */
- memset(&wclass, 0, sizeof(wclass));
- wclass.lpfnWndProc = apartment_wndproc;
- wclass.hInstance = hProxyDll;
- wclass.lpszClassName = wszAptWinClass;
- RegisterClassW(&wclass);
+ EnterCriticalSection( &csOpenDllList );
+
+ *ret = COMPOBJ_DllList_Get(library_name);
+ if (*ret)
+ {
+ /* another caller to this function already added the dll while we
+ * weren't in the critical section */
+ FreeLibrary(hLibrary);
+ }
+ else
+ {
+ len = strlenW(library_name);
+ entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
+ if (entry)
+ entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
+ if (entry && entry->library_name)
+ {
+ memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
+ entry->library = hLibrary;
+ entry->refs = 1;
+ entry->DllCanUnloadNow = DllCanUnloadNow;
+ entry->DllGetClassObject = DllGetClassObject;
+ list_add_tail(&openDllList, &entry->entry);
+ }
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ hr = E_OUTOFMEMORY;
+ FreeLibrary(hLibrary);
+ }
+ *ret = entry;
+ }
+
+ LeaveCriticalSection( &csOpenDllList );
+
+ return hr;
}
-static void COMPOBJ_UninitProcess( void )
+/* pass FALSE for free_entry to release a reference without destroying the
+ * entry if it reaches zero or TRUE otherwise */
+static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry)
{
- UnregisterClassW(wszAptWinClass, hProxyDll);
+ if (!InterlockedDecrement(&entry->refs) && free_entry)
+ {
+ EnterCriticalSection(&csOpenDllList);
+ list_remove(&entry->entry);
+ LeaveCriticalSection(&csOpenDllList);
+
+ TRACE("freeing %p\n", entry->library);
+ FreeLibrary(entry->library);
+
+ HeapFree(GetProcessHeap(), 0, entry->library_name);
+ HeapFree(GetProcessHeap(), 0, entry);
+ }
}
-static void COM_TlsDestroy(void)
+/* frees memory associated with active dll list */
+static void COMPOBJ_DllList_Free(void)
{
- struct oletls *info = NtCurrentTeb()->ReservedForOle;
- if (info)
+ OpenDll *entry, *cursor2;
+ EnterCriticalSection(&csOpenDllList);
+ LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &openDllList, OpenDll, entry)
{
- if (info->apt) apartment_release(info->apt);
- if (info->errorinfo) IErrorInfo_Release(info->errorinfo);
- if (info->state) IUnknown_Release(info->state);
- if (info->spy) IUnknown_Release(info->spy);
- HeapFree(GetProcessHeap(), 0, info);
- NtCurrentTeb()->ReservedForOle = NULL;
+ list_remove(&entry->entry);
+
+ HeapFree(GetProcessHeap(), 0, entry->library_name);
+ HeapFree(GetProcessHeap(), 0, entry);
}
+ LeaveCriticalSection(&csOpenDllList);
}
/******************************************************************************
* Manage apartments.
*/
+struct apartment_loaded_dll
+{
+ struct list entry;
+ OpenDll *dll;
+ DWORD unload_time;
+ BOOL multi_threaded;
+};
+
+DWORD apartment_addref(struct apartment *apt)
+{
+ DWORD refs = InterlockedIncrement(&apt->refs);
+ TRACE("%s: before = %d\n", wine_dbgstr_longlong(apt->oxid), refs - 1);
+ return refs;
+}
+
/* allocates memory and fills in the necessary fields for a new apartment
* object. must be called inside apartment cs */
static APARTMENT *apartment_construct(DWORD model)
@@ -335,11 +413,82 @@ static inline BOOL apartment_is_model(const APARTMENT *apt, DWORD model)
return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED));
}
-DWORD apartment_addref(struct apartment *apt)
+static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
{
- DWORD refs = InterlockedIncrement(&apt->refs);
- TRACE("%s: before = %d\n", wine_dbgstr_longlong(apt->oxid), refs - 1);
- return refs;
+ list_remove(&curClass->entry);
+
+ if (curClass->runContext & CLSCTX_LOCAL_SERVER)
+ RPC_StopLocalServer(curClass->RpcRegistration);
+
+ /*
+ * Release the reference to the class object.
+ */
+ IUnknown_Release(curClass->classObject);
+
+ if (curClass->pMarshaledData)
+ {
+ LARGE_INTEGER zero;
+ memset(&zero, 0, sizeof(zero));
+ IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL);
+ CoReleaseMarshalData(curClass->pMarshaledData);
+ IStream_Release(curClass->pMarshaledData);
+ }
+
+ HeapFree(GetProcessHeap(), 0, curClass);
+}
+
+static void COM_RevokeAllClasses(const struct apartment *apt)
+{
+ RegisteredClass *curClass, *cursor;
+
+ EnterCriticalSection( &csRegisteredClassList );
+
+ LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry)
+ {
+ if (curClass->apartment_id == apt->oxid)
+ COM_RevokeRegisteredClassObject(curClass);
+ }
+
+ LeaveCriticalSection( &csRegisteredClassList );
+}
+
+/* frees unused libraries loaded by apartment_getclassobject by calling the
+ * DLL's DllCanUnloadNow entry point */
+static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
+{
+ struct apartment_loaded_dll *entry, *next;
+ EnterCriticalSection(&apt->cs);
+ LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry)
+ {
+ if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
+ {
+ DWORD real_delay = delay;
+
+ if (real_delay == INFINITE)
+ {
+ /* DLLs that return multi-threaded objects aren't unloaded
+ * straight away to cope for programs that have races between
+ * last object destruction and threads in the DLLs that haven't
+ * finished, despite DllCanUnloadNow returning S_OK */
+ if (entry->multi_threaded)
+ real_delay = 10 * 60 * 1000; /* 10 minutes */
+ else
+ real_delay = 0;
+ }
+
+ if (!real_delay || (entry->unload_time && (entry->unload_time < GetTickCount())))
+ {
+ list_remove(&entry->entry);
+ COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE);
+ HeapFree(GetProcessHeap(), 0, entry);
+ }
+ else
+ entry->unload_time = GetTickCount() + real_delay;
+ }
+ else if (entry->unload_time)
+ entry->unload_time = 0;
+ }
+ LeaveCriticalSection(&apt->cs);
}
DWORD apartment_release(struct apartment *apt)
@@ -530,6 +679,106 @@ struct host_object_params
BOOL apartment_threaded; /* is the component purely apartment-threaded? */
};
+/* gets the specified class object by loading the appropriate DLL, if
+ * necessary and calls the DllGetClassObject function for the DLL */
+static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
+ BOOL apartment_threaded,
+ REFCLSID rclsid, REFIID riid, void **ppv)
+{
+ static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0};
+ HRESULT hr = S_OK;
+ BOOL found = FALSE;
+ struct apartment_loaded_dll *apartment_loaded_dll;
+
+ if (!strcmpiW(dllpath, wszOle32))
+ {
+ /* we don't need to control the lifetime of this dll, so use the local
+ * implementation of DllGetClassObject directly */
+ TRACE("calling ole32!DllGetClassObject\n");
+ hr = DllGetClassObject(rclsid, riid, ppv);
+
+ if (hr != S_OK)
+ ERR("DllGetClassObject returned error 0x%08x\n", hr);
+
+ return hr;
+ }
+
+ EnterCriticalSection(&apt->cs);
+
+ LIST_FOR_EACH_ENTRY(apartment_loaded_dll, &apt->loaded_dlls, struct apartment_loaded_dll, entry)
+ if (!strcmpiW(dllpath, apartment_loaded_dll->dll->library_name))
+ {
+ TRACE("found %s already loaded\n", debugstr_w(dllpath));
+ found = TRUE;
+ break;
+ }
+
+ if (!found)
+ {
+ apartment_loaded_dll = HeapAlloc(GetProcessHeap(), 0, sizeof(*apartment_loaded_dll));
+ if (!apartment_loaded_dll)
+ hr = E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ apartment_loaded_dll->unload_time = 0;
+ apartment_loaded_dll->multi_threaded = FALSE;
+ hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll );
+ if (FAILED(hr))
+ HeapFree(GetProcessHeap(), 0, apartment_loaded_dll);
+ }
+ if (SUCCEEDED(hr))
+ {
+ TRACE("added new loaded dll %s\n", debugstr_w(dllpath));
+ list_add_tail(&apt->loaded_dlls, &apartment_loaded_dll->entry);
+ }
+ }
+
+ LeaveCriticalSection(&apt->cs);
+
+ if (SUCCEEDED(hr))
+ {
+ /* one component being multi-threaded overrides any number of
+ * apartment-threaded components */
+ if (!apartment_threaded)
+ apartment_loaded_dll->multi_threaded = TRUE;
+
+ TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject);
+ /* OK: get the ClassObject */
+ hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv);
+
+ if (hr != S_OK)
+ ERR("DllGetClassObject returned error 0x%08x\n", hr);
+ }
+
+ return hr;
+}
+
+/***********************************************************************
+ * COM_RegReadPath [internal]
+ *
+ * Reads a registry value and expands it when necessary
+ */
+static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen)
+{
+ DWORD ret;
+ HKEY key;
+ DWORD keytype;
+ WCHAR src[MAX_PATH];
+ DWORD dwLength = dstlen * sizeof(WCHAR);
+
+ if((ret = RegOpenKeyExW(hkeyroot, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) {
+ if( (ret = RegQueryValueExW(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) {
+ if (keytype == REG_EXPAND_SZ) {
+ if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA;
+ } else {
+ lstrcpynW(dst, src, dstlen);
+ }
+ }
+ RegCloseKey (key);
+ }
+ return ret;
+}
+
static HRESULT apartment_hostobject(struct apartment *apt,
const struct host_object_params *params)
{
@@ -743,6 +992,9 @@ static HRESULT apartment_hostobject_in_hostapt(
return hr;
}
+static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ',
+ '0','x','#','#','#','#','#','#','#','#',' ',0};
+
/* create a window for the apartment or return the current one if one has
* already been created */
HRESULT apartment_createwindowifneeded(struct apartment *apt)
@@ -781,246 +1033,44 @@ void apartment_joinmta(void)
COM_CurrentInfo()->apt = MTA;
}
-/* gets the specified class object by loading the appropriate DLL, if
- * necessary and calls the DllGetClassObject function for the DLL */
-static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
- BOOL apartment_threaded,
- REFCLSID rclsid, REFIID riid, void **ppv)
-{
- static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0};
- HRESULT hr = S_OK;
- BOOL found = FALSE;
- struct apartment_loaded_dll *apartment_loaded_dll;
-
- if (!strcmpiW(dllpath, wszOle32))
- {
- /* we don't need to control the lifetime of this dll, so use the local
- * implementation of DllGetClassObject directly */
- TRACE("calling ole32!DllGetClassObject\n");
- hr = DllGetClassObject(rclsid, riid, ppv);
-
- if (hr != S_OK)
- ERR("DllGetClassObject returned error 0x%08x\n", hr);
-
- return hr;
- }
-
- EnterCriticalSection(&apt->cs);
-
- LIST_FOR_EACH_ENTRY(apartment_loaded_dll, &apt->loaded_dlls, struct apartment_loaded_dll, entry)
- if (!strcmpiW(dllpath, apartment_loaded_dll->dll->library_name))
- {
- TRACE("found %s already loaded\n", debugstr_w(dllpath));
- found = TRUE;
- break;
- }
-
- if (!found)
- {
- apartment_loaded_dll = HeapAlloc(GetProcessHeap(), 0, sizeof(*apartment_loaded_dll));
- if (!apartment_loaded_dll)
- hr = E_OUTOFMEMORY;
- if (SUCCEEDED(hr))
- {
- apartment_loaded_dll->unload_time = 0;
- apartment_loaded_dll->multi_threaded = FALSE;
- hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll );
- if (FAILED(hr))
- HeapFree(GetProcessHeap(), 0, apartment_loaded_dll);
- }
- if (SUCCEEDED(hr))
- {
- TRACE("added new loaded dll %s\n", debugstr_w(dllpath));
- list_add_tail(&apt->loaded_dlls, &apartment_loaded_dll->entry);
- }
- }
-
- LeaveCriticalSection(&apt->cs);
-
- if (SUCCEEDED(hr))
- {
- /* one component being multi-threaded overrides any number of
- * apartment-threaded components */
- if (!apartment_threaded)
- apartment_loaded_dll->multi_threaded = TRUE;
-
- TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject);
- /* OK: get the ClassObject */
- hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv);
-
- if (hr != S_OK)
- ERR("DllGetClassObject returned error 0x%08x\n", hr);
- }
-
- return hr;
-}
-
-/* frees unused libraries loaded by apartment_getclassobject by calling the
- * DLL's DllCanUnloadNow entry point */
-static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
-{
- struct apartment_loaded_dll *entry, *next;
- EnterCriticalSection(&apt->cs);
- LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry)
- {
- if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
- {
- DWORD real_delay = delay;
-
- if (real_delay == INFINITE)
- {
- /* DLLs that return multi-threaded objects aren't unloaded
- * straight away to cope for programs that have races between
- * last object destruction and threads in the DLLs that haven't
- * finished, despite DllCanUnloadNow returning S_OK */
- if (entry->multi_threaded)
- real_delay = 10 * 60 * 1000; /* 10 minutes */
- else
- real_delay = 0;
- }
-
- if (!real_delay || (entry->unload_time && (entry->unload_time < GetTickCount())))
- {
- list_remove(&entry->entry);
- COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE);
- HeapFree(GetProcessHeap(), 0, entry);
- }
- else
- entry->unload_time = GetTickCount() + real_delay;
- }
- else if (entry->unload_time)
- entry->unload_time = 0;
- }
- LeaveCriticalSection(&apt->cs);
-}
-
-/*****************************************************************************
- * This section contains OpenDllList implementation
- */
-/* caller must ensure that library_name is not already in the open dll list */
-static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
+static void COMPOBJ_InitProcess( void )
{
- OpenDll *entry;
- int len;
- HRESULT hr = S_OK;
- HANDLE hLibrary;
- DllCanUnloadNowFunc DllCanUnloadNow;
- DllGetClassObjectFunc DllGetClassObject;
-
- TRACE("\n");
-
- *ret = COMPOBJ_DllList_Get(library_name);
- if (*ret) return S_OK;
-
- /* do this outside the csOpenDllList to avoid creating a lock dependency on
- * the loader lock */
- hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (!hLibrary)
- {
- ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
- /* failure: DLL could not be loaded */
- return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
- }
-
- DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow");
- /* Note: failing to find DllCanUnloadNow is not a failure */
- DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject");
- if (!DllGetClassObject)
- {
- /* failure: the dll did not export DllGetClassObject */
- ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name));
- FreeLibrary(hLibrary);
- return CO_E_DLLNOTFOUND;
- }
-
- EnterCriticalSection( &csOpenDllList );
-
- *ret = COMPOBJ_DllList_Get(library_name);
- if (*ret)
- {
- /* another caller to this function already added the dll while we
- * weren't in the critical section */
- FreeLibrary(hLibrary);
- }
- else
- {
- len = strlenW(library_name);
- entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
- if (entry)
- entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
- if (entry && entry->library_name)
- {
- memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
- entry->library = hLibrary;
- entry->refs = 1;
- entry->DllCanUnloadNow = DllCanUnloadNow;
- entry->DllGetClassObject = DllGetClassObject;
- list_add_tail(&openDllList, &entry->entry);
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, entry);
- hr = E_OUTOFMEMORY;
- FreeLibrary(hLibrary);
- }
- *ret = entry;
- }
-
- LeaveCriticalSection( &csOpenDllList );
-
- return hr;
-}
+ WNDCLASSW wclass;
-static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name)
-{
- OpenDll *ptr;
- OpenDll *ret = NULL;
- EnterCriticalSection(&csOpenDllList);
- LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry)
- {
- if (!strcmpiW(library_name, ptr->library_name) &&
- (InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */)
- {
- ret = ptr;
- break;
- }
- }
- LeaveCriticalSection(&csOpenDllList);
- return ret;
+ /* Dispatching to the correct thread in an apartment is done through
+ * window messages rather than RPC transports. When an interface is
+ * marshalled into another apartment in the same process, a window of the
+ * following class is created. The *caller* of CoMarshalInterface (i.e., the
+ * application) is responsible for pumping the message loop in that thread.
+ * The WM_USER messages which point to the RPCs are then dispatched to
+ * apartment_wndproc by the user's code from the apartment in which the
+ * interface was unmarshalled.
+ */
+ memset(&wclass, 0, sizeof(wclass));
+ wclass.lpfnWndProc = apartment_wndproc;
+ wclass.hInstance = hProxyDll;
+ wclass.lpszClassName = wszAptWinClass;
+ RegisterClassW(&wclass);
}
-/* pass FALSE for free_entry to release a reference without destroying the
- * entry if it reaches zero or TRUE otherwise */
-static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry)
+static void COMPOBJ_UninitProcess( void )
{
- if (!InterlockedDecrement(&entry->refs) && free_entry)
- {
- EnterCriticalSection(&csOpenDllList);
- list_remove(&entry->entry);
- LeaveCriticalSection(&csOpenDllList);
-
- TRACE("freeing %p\n", entry->library);
- FreeLibrary(entry->library);
-
- HeapFree(GetProcessHeap(), 0, entry->library_name);
- HeapFree(GetProcessHeap(), 0, entry);
- }
+ UnregisterClassW(wszAptWinClass, hProxyDll);
}
-/* frees memory associated with active dll list */
-static void COMPOBJ_DllList_Free(void)
+static void COM_TlsDestroy(void)
{
- OpenDll *entry, *cursor2;
- EnterCriticalSection(&csOpenDllList);
- LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &openDllList, OpenDll, entry)
+ struct oletls *info = NtCurrentTeb()->ReservedForOle;
+ if (info)
{
- list_remove(&entry->entry);
-
- HeapFree(GetProcessHeap(), 0, entry->library_name);
- HeapFree(GetProcessHeap(), 0, entry);
+ if (info->apt) apartment_release(info->apt);
+ if (info->errorinfo) IErrorInfo_Release(info->errorinfo);
+ if (info->state) IUnknown_Release(info->state);
+ if (info->spy) IUnknown_Release(info->spy);
+ HeapFree(GetProcessHeap(), 0, info);
+ NtCurrentTeb()->ReservedForOle = NULL;
}
- LeaveCriticalSection(&csOpenDllList);
}
/******************************************************************************
@@ -2031,45 +2081,6 @@ HRESULT WINAPI CoRegisterClassObject(
return S_OK;
}
-static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
-{
- list_remove(&curClass->entry);
-
- if (curClass->runContext & CLSCTX_LOCAL_SERVER)
- RPC_StopLocalServer(curClass->RpcRegistration);
-
- /*
- * Release the reference to the class object.
- */
- IUnknown_Release(curClass->classObject);
-
- if (curClass->pMarshaledData)
- {
- LARGE_INTEGER zero;
- memset(&zero, 0, sizeof(zero));
- IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL);
- CoReleaseMarshalData(curClass->pMarshaledData);
- IStream_Release(curClass->pMarshaledData);
- }
-
- HeapFree(GetProcessHeap(), 0, curClass);
-}
-
-static void COM_RevokeAllClasses(const struct apartment *apt)
-{
- RegisteredClass *curClass, *cursor;
-
- EnterCriticalSection( &csRegisteredClassList );
-
- LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry)
- {
- if (curClass->apartment_id == apt->oxid)
- COM_RevokeRegisteredClassObject(curClass);
- }
-
- LeaveCriticalSection( &csRegisteredClassList );
-}
-
/***********************************************************************
* CoRevokeClassObject [OLE32.@]
*
@@ -2134,32 +2145,6 @@ HRESULT WINAPI CoRevokeClassObject(
return hr;
}
-/***********************************************************************
- * COM_RegReadPath [internal]
- *
- * Reads a registry value and expands it when necessary
- */
-static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen)
-{
- DWORD ret;
- HKEY key;
- DWORD keytype;
- WCHAR src[MAX_PATH];
- DWORD dwLength = dstlen * sizeof(WCHAR);
-
- if((ret = RegOpenKeyExW(hkeyroot, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) {
- if( (ret = RegQueryValueExW(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) {
- if (keytype == REG_EXPAND_SZ) {
- if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA;
- } else {
- lstrcpynW(dst, src, dstlen);
- }
- }
- RegCloseKey (key);
- }
- return ret;
-}
-
static void get_threading_model(HKEY key, LPWSTR value, DWORD len)
{
static const WCHAR wszThreadingModel[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
--
1.6.3.1
More information about the wine-patches
mailing list