urlmon: Added task queue architecture and use it for OnProgress calls from Continue call.
This commit is contained in:
parent
89d9287af6
commit
99cb95394a
|
@ -34,9 +34,47 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
||||||
|
|
||||||
typedef struct ProtocolStream ProtocolStream;
|
typedef struct Binding Binding;
|
||||||
|
|
||||||
|
enum task_enum {
|
||||||
|
TASK_ON_PROGRESS
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Binding *binding;
|
||||||
|
ULONG progress;
|
||||||
|
ULONG progress_max;
|
||||||
|
ULONG status_code;
|
||||||
|
LPWSTR status_text;
|
||||||
|
} on_progress_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Binding *binding;
|
||||||
|
PROTOCOLDATA *data;
|
||||||
|
} switch_data;
|
||||||
|
|
||||||
|
typedef struct _task_t {
|
||||||
|
enum task_enum task;
|
||||||
|
Binding *binding;
|
||||||
|
struct _task_t *next;
|
||||||
|
union {
|
||||||
|
on_progress_data on_progress;
|
||||||
|
} data;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const IStreamVtbl *lpStreamVtbl;
|
||||||
|
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
IInternetProtocol *protocol;
|
||||||
|
|
||||||
|
BYTE buf[1024*8];
|
||||||
|
DWORD buf_size;
|
||||||
|
BOOL init_buf;
|
||||||
|
} ProtocolStream;
|
||||||
|
|
||||||
|
struct Binding {
|
||||||
const IBindingVtbl *lpBindingVtbl;
|
const IBindingVtbl *lpBindingVtbl;
|
||||||
const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
|
const IInternetProtocolSinkVtbl *lpInternetProtocolSinkVtbl;
|
||||||
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
|
const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
|
||||||
|
@ -54,23 +92,15 @@ typedef struct {
|
||||||
LPWSTR mime;
|
LPWSTR mime;
|
||||||
LPWSTR url;
|
LPWSTR url;
|
||||||
BOOL verified_mime;
|
BOOL verified_mime;
|
||||||
|
DWORD continue_call;
|
||||||
|
|
||||||
DWORD apartment_thread;
|
DWORD apartment_thread;
|
||||||
HWND notif_hwnd;
|
HWND notif_hwnd;
|
||||||
|
|
||||||
STGMEDIUM stgmed;
|
STGMEDIUM stgmed;
|
||||||
} Binding;
|
|
||||||
|
|
||||||
struct ProtocolStream {
|
task_t *task_queue_head, *task_queue_tail;
|
||||||
const IStreamVtbl *lpStreamVtbl;
|
CRITICAL_SECTION section;
|
||||||
|
|
||||||
LONG ref;
|
|
||||||
|
|
||||||
IInternetProtocol *protocol;
|
|
||||||
|
|
||||||
BYTE buf[1024*8];
|
|
||||||
DWORD buf_size;
|
|
||||||
BOOL init_buf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BINDING(x) ((IBinding*) &(x)->lpBindingVtbl)
|
#define BINDING(x) ((IBinding*) &(x)->lpBindingVtbl)
|
||||||
|
@ -83,18 +113,62 @@ struct ProtocolStream {
|
||||||
#define WM_MK_ONPROGRESS (WM_USER+100)
|
#define WM_MK_ONPROGRESS (WM_USER+100)
|
||||||
#define WM_MK_CONTINUE (WM_USER+101)
|
#define WM_MK_CONTINUE (WM_USER+101)
|
||||||
|
|
||||||
typedef struct {
|
static void push_task(task_t *task)
|
||||||
Binding *binding;
|
{
|
||||||
ULONG progress;
|
task->next = NULL;
|
||||||
ULONG progress_max;
|
|
||||||
ULONG status_code;
|
|
||||||
LPWSTR status_text;
|
|
||||||
} on_progress_data;
|
|
||||||
|
|
||||||
typedef struct {
|
EnterCriticalSection(&task->binding->section);
|
||||||
Binding *binding;
|
|
||||||
PROTOCOLDATA *data;
|
if(task->binding->task_queue_tail)
|
||||||
} switch_data;
|
task->binding->task_queue_tail->next = task;
|
||||||
|
else
|
||||||
|
task->binding->task_queue_tail = task->binding->task_queue_head = task;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&task->binding->section);
|
||||||
|
}
|
||||||
|
|
||||||
|
static task_t *pop_task(Binding *binding)
|
||||||
|
{
|
||||||
|
task_t *ret;
|
||||||
|
|
||||||
|
EnterCriticalSection(&binding->section);
|
||||||
|
|
||||||
|
ret = binding->task_queue_head;
|
||||||
|
if(ret) {
|
||||||
|
binding->task_queue_head = ret->next;
|
||||||
|
if(!binding->task_queue_head)
|
||||||
|
binding->task_queue_tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&binding->section);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_task(task_t *task)
|
||||||
|
{
|
||||||
|
switch(task->task) {
|
||||||
|
case TASK_ON_PROGRESS: {
|
||||||
|
on_progress_data *data = &task->data.on_progress;
|
||||||
|
|
||||||
|
IBindStatusCallback_OnProgress(task->binding->callback, data->progress,
|
||||||
|
data->progress_max, data->status_code, data->status_text);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, data->status_text);
|
||||||
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_tasks(Binding *This)
|
||||||
|
{
|
||||||
|
task_t *task;
|
||||||
|
|
||||||
|
while((task = pop_task(This))) {
|
||||||
|
do_task(task);
|
||||||
|
IBinding_Release(BINDING(task->binding));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -116,7 +190,11 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||||
case WM_MK_CONTINUE: {
|
case WM_MK_CONTINUE: {
|
||||||
switch_data *data = (switch_data*)lParam;
|
switch_data *data = (switch_data*)lParam;
|
||||||
|
|
||||||
|
data->binding->continue_call++;
|
||||||
IInternetProtocol_Continue(data->binding->protocol, data->data);
|
IInternetProtocol_Continue(data->binding->protocol, data->data);
|
||||||
|
data->binding->continue_call--;
|
||||||
|
|
||||||
|
do_tasks(data->binding);
|
||||||
|
|
||||||
IBinding_Release(BINDING(data->binding));
|
IBinding_Release(BINDING(data->binding));
|
||||||
HeapFree(GetProcessHeap(), 0, data);
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
@ -170,33 +248,61 @@ static HWND get_notif_hwnd(void)
|
||||||
static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
|
static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
|
||||||
ULONG status_code, LPCWSTR status_text)
|
ULONG status_code, LPCWSTR status_text)
|
||||||
{
|
{
|
||||||
on_progress_data *data;
|
task_t *task;
|
||||||
|
|
||||||
if(GetCurrentThreadId() == This->apartment_thread) {
|
if(GetCurrentThreadId() != This->apartment_thread) {
|
||||||
|
on_progress_data *data;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!This->continue_call) {
|
||||||
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
|
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
|
||||||
status_code, status_text);
|
status_code, status_text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
|
task = HeapAlloc(GetProcessHeap(), 0, sizeof(task_t));
|
||||||
|
|
||||||
|
task->task = TASK_ON_PROGRESS;
|
||||||
|
|
||||||
IBinding_AddRef(BINDING(This));
|
IBinding_AddRef(BINDING(This));
|
||||||
|
task->binding = This;
|
||||||
|
|
||||||
data->binding = This;
|
task->data.on_progress.progress = progress;
|
||||||
data->progress = progress;
|
task->data.on_progress.progress_max = progress_max;
|
||||||
data->progress_max = progress_max;
|
task->data.on_progress.status_code = status_code;
|
||||||
data->status_code = status_code;
|
|
||||||
|
|
||||||
if(status_text) {
|
if(status_text) {
|
||||||
DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
|
DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
|
||||||
|
|
||||||
data->status_text = HeapAlloc(GetProcessHeap(), 0, size);
|
task->data.on_progress.status_text = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
memcpy(data->status_text, status_text, size);
|
memcpy(task->data.on_progress.status_text, status_text, size);
|
||||||
}else {
|
}else {
|
||||||
data->status_text = NULL;
|
task->data.on_progress.status_text = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostMessageW(This->notif_hwnd, WM_MK_ONPROGRESS, 0, (LPARAM)data);
|
push_task(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_BINDINFO(BINDINFO *bi)
|
static void dump_BINDINFO(BINDINFO *bi)
|
||||||
|
@ -606,6 +712,7 @@ static ULONG WINAPI Binding_Release(IBinding *iface)
|
||||||
IStream_Release(STREAM(This->stream));
|
IStream_Release(STREAM(This->stream));
|
||||||
|
|
||||||
ReleaseBindInfo(&This->bindinfo);
|
ReleaseBindInfo(&This->bindinfo);
|
||||||
|
DeleteCriticalSection(&This->section);
|
||||||
HeapFree(GetProcessHeap(), 0, This->mime);
|
HeapFree(GetProcessHeap(), 0, This->mime);
|
||||||
HeapFree(GetProcessHeap(), 0, This->url);
|
HeapFree(GetProcessHeap(), 0, This->url);
|
||||||
|
|
||||||
|
@ -1041,11 +1148,15 @@ static HRESULT Binding_Create(LPCWSTR url, IBindCtx *pbc, REFIID riid, Binding *
|
||||||
ret->apartment_thread = GetCurrentThreadId();
|
ret->apartment_thread = GetCurrentThreadId();
|
||||||
ret->notif_hwnd = get_notif_hwnd();
|
ret->notif_hwnd = get_notif_hwnd();
|
||||||
ret->verified_mime = FALSE;
|
ret->verified_mime = FALSE;
|
||||||
|
ret->continue_call = 0;
|
||||||
|
ret->task_queue_head = ret->task_queue_tail = NULL;
|
||||||
|
|
||||||
memset(&ret->bindinfo, 0, sizeof(BINDINFO));
|
memset(&ret->bindinfo, 0, sizeof(BINDINFO));
|
||||||
ret->bindinfo.cbSize = sizeof(BINDINFO);
|
ret->bindinfo.cbSize = sizeof(BINDINFO);
|
||||||
ret->bindf = 0;
|
ret->bindf = 0;
|
||||||
|
|
||||||
|
InitializeCriticalSection(&ret->section);
|
||||||
|
|
||||||
hres = get_callback(pbc, &ret->callback);
|
hres = get_callback(pbc, &ret->callback);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
WARN("Could not get IBindStatusCallback\n");
|
WARN("Could not get IBindStatusCallback\n");
|
||||||
|
|
Loading…
Reference in New Issue