urlmon: Cache the binding notif window.

This commit is contained in:
Jacek Caban 2009-05-11 13:14:45 +02:00 committed by Alexandre Julliard
parent f85e7dc3c2
commit bee36fe831
3 changed files with 140 additions and 10 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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);