diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c index 28d0802174b..f8ad73a6336 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 8561937643a..3203753f923 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 1ee2eec313e..aa2f276257d 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);