urlmon: Added support for PI_APARTMENTTHREADED to BindProtocol::Switch.
This commit is contained in:
parent
0d446053da
commit
e487196dc2
|
@ -192,6 +192,9 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||||
IBinding_Release(BINDING(binding));
|
IBinding_Release(BINDING(binding));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case WM_MK_CONTINUE2:
|
||||||
|
handle_bindprot_task((void*)lParam);
|
||||||
|
return 0;
|
||||||
case WM_MK_RELEASE: {
|
case WM_MK_RELEASE: {
|
||||||
tls_data_t *data = get_tls_data();
|
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);
|
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HWND get_notif_hwnd(void)
|
HWND get_notif_hwnd(void)
|
||||||
{
|
{
|
||||||
static ATOM wnd_class = 0;
|
static ATOM wnd_class = 0;
|
||||||
tls_data_t *tls_data;
|
tls_data_t *tls_data;
|
||||||
|
@ -250,7 +253,7 @@ static HWND get_notif_hwnd(void)
|
||||||
return tls_data->notif_hwnd;
|
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();
|
tls_data_t *data = get_tls_data();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,18 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
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 IInternetProtocolVtbl *lpInternetProtocolVtbl;
|
||||||
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
|
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
|
||||||
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
||||||
|
@ -40,7 +51,15 @@ typedef struct {
|
||||||
|
|
||||||
BOOL reported_result;
|
BOOL reported_result;
|
||||||
BOOL from_urlmon;
|
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 PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
|
||||||
#define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
|
#define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
|
||||||
|
@ -48,6 +67,64 @@ typedef struct {
|
||||||
#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
|
#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
|
||||||
#define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
|
#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)
|
#define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, InternetProtocol, iface)
|
||||||
|
|
||||||
static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
|
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);
|
IInternetBindInfo_Release(This->bind_info);
|
||||||
|
|
||||||
set_binding_sink(PROTOCOL(This), NULL);
|
set_binding_sink(PROTOCOL(This), NULL);
|
||||||
|
|
||||||
|
if(This->notif_hwnd)
|
||||||
|
release_notif_hwnd(This->notif_hwnd);
|
||||||
|
DeleteCriticalSection(&This->section);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
|
|
||||||
URLMON_UnlockModule();
|
URLMON_UnlockModule();
|
||||||
|
@ -140,6 +221,8 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
||||||
if(!szUrl || !pOIProtSink || !pOIBindInfo)
|
if(!szUrl || !pOIProtSink || !pOIBindInfo)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
This->pi = grfPI;
|
||||||
|
|
||||||
hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
|
hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
|
||||||
(void**)&service_provider);
|
(void**)&service_provider);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
|
@ -468,6 +551,20 @@ static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
|
||||||
return IInternetProtocol_Release(PROTOCOL(This));
|
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,
|
static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
|
||||||
PROTOCOLDATA *pProtocolData)
|
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,
|
TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
|
||||||
pProtocolData->pData, pProtocolData->cbData);
|
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) {
|
if(!This->protocol_sink) {
|
||||||
IInternetProtocol_Continue(This->protocol, pProtocolData);
|
IInternetProtocol_Continue(This->protocol, pProtocolData);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -615,6 +725,9 @@ HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol
|
||||||
|
|
||||||
ret->ref = 1;
|
ret->ref = 1;
|
||||||
ret->from_urlmon = from_urlmon;
|
ret->from_urlmon = from_urlmon;
|
||||||
|
ret->apartment_thread = GetCurrentThreadId();
|
||||||
|
ret->notif_hwnd = get_notif_hwnd();
|
||||||
|
InitializeCriticalSection(&ret->section);
|
||||||
|
|
||||||
URLMON_LockModule();
|
URLMON_LockModule();
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,12 @@ typedef struct {
|
||||||
|
|
||||||
tls_data_t *get_tls_data(void);
|
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)
|
static inline void *heap_alloc(size_t len)
|
||||||
{
|
{
|
||||||
return HeapAlloc(GetProcessHeap(), 0, len);
|
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||||
|
|
Loading…
Reference in New Issue