Jacek Caban : urlmon: Added support for PI_APARTMENTTHREADED to BindProtocol::Switch.
Alexandre Julliard
julliard at winehq.org
Tue May 12 09:08:46 CDT 2009
Module: wine
Branch: master
Commit: e487196dc2ec499ac11a0e99d9919db799a03f0f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e487196dc2ec499ac11a0e99d9919db799a03f0f
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon May 11 21:59:31 2009 +0200
urlmon: Added support for PI_APARTMENTTHREADED to BindProtocol::Switch.
---
dlls/urlmon/binding.c | 7 ++-
dlls/urlmon/bindprot.c | 117 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/urlmon/urlmon_main.h | 6 ++
3 files changed, 126 insertions(+), 4 deletions(-)
diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c
index f8ad73a..4b8651c 100644
--- a/dlls/urlmon/binding.c
+++ b/dlls/urlmon/binding.c
@@ -192,6 +192,9 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
IBinding_Release(BINDING(binding));
return 0;
}
+ case WM_MK_CONTINUE2:
+ handle_bindprot_task((void*)lParam);
+ return 0;
case WM_MK_RELEASE: {
tls_data_t *data = get_tls_data();
@@ -205,7 +208,7 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
-static HWND get_notif_hwnd(void)
+HWND get_notif_hwnd(void)
{
static ATOM wnd_class = 0;
tls_data_t *tls_data;
@@ -250,7 +253,7 @@ static HWND get_notif_hwnd(void)
return tls_data->notif_hwnd;
}
-static void release_notif_hwnd(HWND hwnd)
+void release_notif_hwnd(HWND hwnd)
{
tls_data_t *data = get_tls_data();
diff --git a/dlls/urlmon/bindprot.c b/dlls/urlmon/bindprot.c
index 1f24594..eaee9b6 100644
--- a/dlls/urlmon/bindprot.c
+++ b/dlls/urlmon/bindprot.c
@@ -21,7 +21,18 @@
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-typedef struct {
+typedef struct BindProtocol BindProtocol;
+
+struct _task_header_t;
+
+typedef void (*task_proc_t)(BindProtocol*,struct _task_header_t*);
+
+typedef struct _task_header_t {
+ task_proc_t proc;
+ struct _task_header_t *next;
+} task_header_t;
+
+struct BindProtocol {
const IInternetProtocolVtbl *lpInternetProtocolVtbl;
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
@@ -40,7 +51,15 @@ typedef struct {
BOOL reported_result;
BOOL from_urlmon;
-} BindProtocol;
+ DWORD pi;
+
+ DWORD apartment_thread;
+ HWND notif_hwnd;
+ DWORD continue_call;
+
+ CRITICAL_SECTION section;
+ task_header_t *task_queue_head, *task_queue_tail;
+};
#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
#define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
@@ -48,6 +67,64 @@ typedef struct {
#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
#define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
+void handle_bindprot_task(void *v)
+{
+ BindProtocol *This = v;
+ task_header_t *task;
+
+ while(1) {
+ EnterCriticalSection(&This->section);
+
+ task = This->task_queue_head;
+ if(task) {
+ This->task_queue_head = task->next;
+ if(!This->task_queue_head)
+ This->task_queue_tail = NULL;
+ }
+
+ LeaveCriticalSection(&This->section);
+
+ if(!task)
+ break;
+
+ This->continue_call++;
+ task->proc(This, task);
+ This->continue_call--;
+ }
+
+ IInternetProtocol_Release(PROTOCOL(This));
+}
+
+static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
+{
+ BOOL do_post = FALSE;
+
+ task->proc = proc;
+ task->next = NULL;
+
+ EnterCriticalSection(&This->section);
+
+ if(This->task_queue_tail) {
+ This->task_queue_tail->next = task;
+ This->task_queue_tail = task;
+ }else {
+ This->task_queue_tail = This->task_queue_head = task;
+ do_post = TRUE;
+ }
+
+ LeaveCriticalSection(&This->section);
+
+ if(do_post) {
+ IInternetProtocol_AddRef(PROTOCOL(This));
+ PostMessageW(This->notif_hwnd, WM_MK_CONTINUE2, 0, (LPARAM)This);
+ }
+}
+
+static BOOL inline do_direct_notif(BindProtocol *This)
+{
+ return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
+}
+
#define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
@@ -113,6 +190,10 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
IInternetBindInfo_Release(This->bind_info);
set_binding_sink(PROTOCOL(This), NULL);
+
+ if(This->notif_hwnd)
+ release_notif_hwnd(This->notif_hwnd);
+ DeleteCriticalSection(&This->section);
heap_free(This);
URLMON_UnlockModule();
@@ -140,6 +221,8 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
if(!szUrl || !pOIProtSink || !pOIBindInfo)
return E_INVALIDARG;
+ This->pi = grfPI;
+
hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
(void**)&service_provider);
if(SUCCEEDED(hres)) {
@@ -468,6 +551,20 @@ static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
return IInternetProtocol_Release(PROTOCOL(This));
}
+typedef struct {
+ task_header_t header;
+ PROTOCOLDATA data;
+} switch_task_t;
+
+static void switch_proc(BindProtocol *bind, task_header_t *t)
+{
+ switch_task_t *task = (switch_task_t*)t;
+
+ IInternetProtocol_Continue(bind->protocol, &task->data);
+
+ heap_free(task);
+}
+
static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
PROTOCOLDATA *pProtocolData)
{
@@ -478,6 +575,19 @@ static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface
TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
pProtocolData->pData, pProtocolData->cbData);
+ if(!do_direct_notif(This)) {
+ switch_task_t *task;
+
+ task = heap_alloc(sizeof(switch_task_t));
+ if(!task)
+ return E_OUTOFMEMORY;
+
+ task->data = *pProtocolData;
+
+ push_task(This, &task->header, switch_proc);
+ return S_OK;
+ }
+
if(!This->protocol_sink) {
IInternetProtocol_Continue(This->protocol, pProtocolData);
return S_OK;
@@ -615,6 +725,9 @@ HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol
ret->ref = 1;
ret->from_urlmon = from_urlmon;
+ ret->apartment_thread = GetCurrentThreadId();
+ ret->notif_hwnd = get_notif_hwnd();
+ InitializeCriticalSection(&ret->section);
URLMON_LockModule();
diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h
index aa2f276..13eb4f3 100644
--- a/dlls/urlmon/urlmon_main.h
+++ b/dlls/urlmon/urlmon_main.h
@@ -116,6 +116,12 @@ typedef struct {
tls_data_t *get_tls_data(void);
+HWND get_notif_hwnd(void);
+void release_notif_hwnd(HWND);
+
+#define WM_MK_CONTINUE2 (WM_USER+103)
+void handle_bindprot_task(void*);
+
static inline void *heap_alloc(size_t len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
More information about the wine-cvs
mailing list