Jacek Caban : urlmon: Cache the binding notif window.
Alexandre Julliard
julliard at winehq.org
Mon May 11 09:10:49 CDT 2009
Module: wine
Branch: master
Commit: bee36fe8315cdacf2d71a903ab524c929e645122
URL: http://source.winehq.org/git/wine.git/?a=commit;h=bee36fe8315cdacf2d71a903ab524c929e645122
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon May 11 13:14:45 2009 +0200
urlmon: Cache the binding notif window.
---
dlls/urlmon/binding.c | 55 ++++++++++++++++++++++++-----
dlls/urlmon/urlmon_main.c | 85 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/urlmon/urlmon_main.h | 10 +++++
3 files changed, 140 insertions(+), 10 deletions(-)
diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c
index 28d0802..f8ad73a 100644
--- a/dlls/urlmon/binding.c
+++ b/dlls/urlmon/binding.c
@@ -125,6 +125,7 @@ struct Binding {
#define HTTPNEG2(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
#define WM_MK_CONTINUE (WM_USER+101)
+#define WM_MK_RELEASE (WM_USER+102)
static void push_task(Binding *binding, task_header_t *task, task_proc_t proc)
{
@@ -177,7 +178,8 @@ static void fill_stgmed_buffer(stgmed_buf_t *buf)
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- if(msg == WM_MK_CONTINUE) {
+ switch(msg) {
+ case WM_MK_CONTINUE: {
Binding *binding = (Binding*)lParam;
task_header_t *task;
@@ -190,6 +192,15 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
IBinding_Release(BINDING(binding));
return 0;
}
+ case WM_MK_RELEASE: {
+ tls_data_t *data = get_tls_data();
+
+ if(!--data->notif_hwnd_cnt) {
+ DestroyWindow(hwnd);
+ data->notif_hwnd = NULL;
+ }
+ }
+ }
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
@@ -197,12 +208,21 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
static HWND get_notif_hwnd(void)
{
static ATOM wnd_class = 0;
- HWND hwnd;
+ tls_data_t *tls_data;
static const WCHAR wszURLMonikerNotificationWindow[] =
{'U','R','L',' ','M','o','n','i','k','e','r',' ',
'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
+ tls_data = get_tls_data();
+ if(!tls_data)
+ return NULL;
+
+ if(tls_data->notif_hwnd_cnt) {
+ tls_data->notif_hwnd_cnt++;
+ return tls_data->notif_hwnd;
+ }
+
if(!wnd_class) {
static WNDCLASSEXW wndclass = {
sizeof(wndclass), 0,
@@ -219,13 +239,30 @@ static HWND get_notif_hwnd(void)
wnd_class = 1;
}
- hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
- wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
- NULL, URLMON_hInstance, NULL);
+ tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
+ wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
+ NULL, URLMON_hInstance, NULL);
+ if(tls_data->notif_hwnd)
+ tls_data->notif_hwnd_cnt++;
- TRACE("hwnd = %p\n", hwnd);
+ TRACE("hwnd = %p\n", tls_data->notif_hwnd);
- return hwnd;
+ return tls_data->notif_hwnd;
+}
+
+static void release_notif_hwnd(HWND hwnd)
+{
+ tls_data_t *data = get_tls_data();
+
+ if(!data || data->notif_hwnd != hwnd) {
+ PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
+ return;
+ }
+
+ if(!--data->notif_hwnd_cnt) {
+ DestroyWindow(data->notif_hwnd);
+ data->notif_hwnd = NULL;
+ }
}
static void dump_BINDINFO(BINDINFO *bi)
@@ -957,8 +994,8 @@ static ULONG WINAPI Binding_Release(IBinding *iface)
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
- if (This->notif_hwnd)
- DestroyWindow( This->notif_hwnd );
+ if(This->notif_hwnd)
+ release_notif_hwnd(This->notif_hwnd);
if(This->mon)
IMoniker_Release(This->mon);
if(This->callback)
diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c
index 8561937..3203753 100644
--- a/dlls/urlmon/urlmon_main.c
+++ b/dlls/urlmon/urlmon_main.c
@@ -36,9 +36,88 @@ LONG URLMON_refCount = 0;
HINSTANCE URLMON_hInstance = 0;
static HMODULE hCabinet = NULL;
+static DWORD urlmon_tls;
static void init_session(BOOL);
+static struct list tls_list = LIST_INIT(tls_list);
+
+static CRITICAL_SECTION tls_cs;
+static CRITICAL_SECTION_DEBUG tls_cs_dbg =
+{
+ 0, 0, &tls_cs,
+ { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
+};
+
+static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
+
+tls_data_t *get_tls_data(void)
+{
+ tls_data_t *data;
+
+ if(!urlmon_tls) {
+ DWORD tls = TlsAlloc();
+ tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, 0);
+ if(tls != urlmon_tls)
+ TlsFree(tls);
+ }
+
+ data = TlsGetValue(urlmon_tls);
+ if(!data) {
+ data = heap_alloc_zero(sizeof(tls_data_t));
+ if(!data)
+ return NULL;
+
+ EnterCriticalSection(&tls_cs);
+ list_add_tail(&tls_list, &data->entry);
+ LeaveCriticalSection(&tls_cs);
+
+ TlsSetValue(urlmon_tls, data);
+ }
+
+ return data;
+}
+
+static void free_tls_list(void)
+{
+ tls_data_t *data;
+
+ if(!urlmon_tls)
+ return;
+
+ while(!list_empty(&tls_list)) {
+ data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
+ list_remove(&data->entry);
+ heap_free(data);
+ }
+
+ TlsFree(urlmon_tls);
+}
+
+static void detach_thread(void)
+{
+ tls_data_t *data;
+
+ if(!urlmon_tls)
+ return;
+
+ data = TlsGetValue(urlmon_tls);
+ if(!data)
+ return;
+
+ EnterCriticalSection(&tls_cs);
+ list_remove(&data->entry);
+ LeaveCriticalSection(&tls_cs);
+
+ if(data->notif_hwnd) {
+ WARN("notif_hwnd not destroyed\n");
+ DestroyWindow(data->notif_hwnd);
+ }
+
+ heap_free(data);
+}
+
/***********************************************************************
* DllMain (URLMON.init)
*/
@@ -48,7 +127,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hinstDLL);
URLMON_hInstance = hinstDLL;
init_session(TRUE);
break;
@@ -58,8 +136,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
FreeLibrary(hCabinet);
hCabinet = NULL;
init_session(FALSE);
+ free_tls_list();
URLMON_hInstance = 0;
break;
+
+ case DLL_THREAD_DETACH:
+ detach_thread();
+ break;
}
return TRUE;
}
diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h
index 1ee2eec..aa2f276 100644
--- a/dlls/urlmon/urlmon_main.h
+++ b/dlls/urlmon/urlmon_main.h
@@ -34,6 +34,7 @@
#include "wininet.h"
#include "wine/unicode.h"
+#include "wine/list.h"
extern HINSTANCE URLMON_hInstance;
extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
@@ -106,6 +107,15 @@ HRESULT protocol_lock_request(Protocol*);
HRESULT protocol_unlock_request(Protocol*);
void protocol_close_connection(Protocol*);
+typedef struct {
+ HWND notif_hwnd;
+ DWORD notif_hwnd_cnt;
+
+ struct list entry;
+} tls_data_t;
+
+tls_data_t *get_tls_data(void);
+
static inline void *heap_alloc(size_t len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
More information about the wine-cvs
mailing list