Jacek Caban : urlmon: Call OnProgress in apartment thread.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu May 25 14:18:26 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 10acd23b2cc89dc353677ef7abd11265dfe98a0e
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=10acd23b2cc89dc353677ef7abd11265dfe98a0e
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu May 25 18:35:35 2006 +0200
urlmon: Call OnProgress in apartment thread.
---
dlls/urlmon/binding.c | 115 +++++++++++++++++++++++++++++++++++++++++++--
dlls/urlmon/urlmon_main.c | 4 ++
dlls/urlmon/urlmon_main.h | 2 +
3 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c
index 2a59b80..7de0847 100644
--- a/dlls/urlmon/binding.c
+++ b/dlls/urlmon/binding.c
@@ -53,6 +53,9 @@ typedef struct {
DWORD bindf;
LPWSTR mime;
LPWSTR url;
+
+ DWORD apartment_thread;
+ HWND notif_hwnd;
} Binding;
struct ProtocolStream {
@@ -74,6 +77,110 @@ #define SERVPROV(x) ((IServiceProvider*
#define STREAM(x) ((IStream*) &(x)->lpStreamVtbl)
+#define WM_MK_ONPROGRESS (WM_USER+100)
+
+typedef struct {
+ Binding *binding;
+ ULONG progress;
+ ULONG progress_max;
+ ULONG status_code;
+ LPWSTR status_text;
+} on_progress_data;
+
+static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_MK_ONPROGRESS: {
+ on_progress_data *data = (on_progress_data*)lParam;
+
+ TRACE("WM_MK_PROGRESS %p\n", data);
+
+ IBindStatusCallback_OnProgress(data->binding->callback, data->progress,
+ data->progress_max, data->status_code, data->status_text);
+
+ IBinding_Release(BINDING(data->binding));
+ HeapFree(GetProcessHeap(), 0, data->status_text);
+ HeapFree(GetProcessHeap(), 0, data);
+
+ return 0;
+ }
+ }
+
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
+}
+
+static HWND get_notif_hwnd(void)
+{
+ static ATOM wnd_class = 0;
+ HWND hwnd;
+
+ 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};
+
+ if(!wnd_class) {
+ static WNDCLASSEXW wndclass = {
+ sizeof(wndclass), 0,
+ notif_wnd_proc, 0, 0,
+ NULL, NULL, NULL, NULL, NULL,
+ wszURLMonikerNotificationWindow,
+ NULL
+ };
+
+ wndclass.hInstance = URLMON_hInstance;
+
+ wnd_class = RegisterClassExW(&wndclass);
+ }
+
+ if(!urlmon_tls)
+ urlmon_tls = TlsAlloc();
+
+ hwnd = TlsGetValue(urlmon_tls);
+ if(hwnd)
+ return hwnd;
+
+ hwnd = CreateWindowExW(0, MAKEINTATOMW(wnd_class),
+ wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
+ NULL, URLMON_hInstance, NULL);
+ TlsSetValue(urlmon_tls, hwnd);
+
+ TRACE("hwnd = %p\n", hwnd);
+
+ return hwnd;
+}
+
+static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
+ ULONG status_code, LPCWSTR status_text)
+{
+ on_progress_data *data;
+
+ if(GetCurrentThreadId() == This->apartment_thread) {
+ IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
+ status_code, status_text);
+ return;
+ }
+
+ data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
+
+ IBinding_AddRef(BINDING(This));
+
+ data->binding = This;
+ data->progress = progress;
+ data->progress_max = progress_max;
+ data->status_code = status_code;
+
+ if(status_text) {
+ DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
+
+ data->status_text = HeapAlloc(GetProcessHeap(), 0, size);
+ memcpy(data->status_text, status_text, size);
+ }else {
+ data->status_text = NULL;
+ }
+
+ PostMessageW(This->notif_hwnd, WM_MK_ONPROGRESS, 0, (LPARAM)data);
+}
+
static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
REFIID riid, void **ppv)
{
@@ -543,12 +650,10 @@ static HRESULT WINAPI InternetProtocolSi
break;
}
case BINDSTATUS_SENDINGREQUEST:
- IBindStatusCallback_OnProgress(This->callback, 0, 0, BINDSTATUS_SENDINGREQUEST,
- szStatusText);
+ on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText);
break;
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
- IBindStatusCallback_OnProgress(This->callback, 0, 0,
- BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
+ on_progress(This, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
break;
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
break;
@@ -847,6 +952,8 @@ static HRESULT Binding_Create(LPCWSTR ur
ret->stream = NULL;
ret->mime = NULL;
ret->url = NULL;
+ ret->apartment_thread = GetCurrentThreadId();
+ ret->notif_hwnd = get_notif_hwnd();
memset(&ret->bindinfo, 0, sizeof(BINDINFO));
ret->bindinfo.cbSize = sizeof(BINDINFO);
diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c
index fa62409..edec353 100644
--- a/dlls/urlmon/urlmon_main.c
+++ b/dlls/urlmon/urlmon_main.c
@@ -42,6 +42,8 @@ LONG URLMON_refCount = 0;
HINSTANCE URLMON_hInstance = 0;
+DWORD urlmon_tls = 0;
+
/***********************************************************************
* DllMain (URLMON.init)
*/
@@ -56,6 +58,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
break;
case DLL_PROCESS_DETACH:
+ if(urlmon_tls)
+ TlsFree(urlmon_tls);
URLMON_hInstance = 0;
break;
}
diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h
index 0eb7db6..9b9f149 100644
--- a/dlls/urlmon/urlmon_main.h
+++ b/dlls/urlmon/urlmon_main.h
@@ -59,4 +59,6 @@ HRESULT get_protocol_handler(LPCWSTR url
HRESULT start_binding(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
+extern DWORD urlmon_tls;
+
#endif /* __WINE_URLMON_MAIN_H */
More information about the wine-cvs
mailing list