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