diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c index 8f1ed4f1ac6..92d4fa2826d 100644 --- a/dlls/urlmon/binding.c +++ b/dlls/urlmon/binding.c @@ -80,6 +80,7 @@ struct Binding { BINDINFO bindinfo; DWORD bindf; LPWSTR mime; + UINT clipboard_format; LPWSTR url; BOOL report_mime; DWORD continue_call; @@ -251,6 +252,75 @@ static void dump_BINDINFO(BINDINFO *bi) ); } +static void set_binding_mime(Binding *binding, LPCWSTR mime) +{ + EnterCriticalSection(&binding->section); + + if(binding->report_mime) { + heap_free(binding->mime); + binding->mime = heap_strdupW(mime); + } + + LeaveCriticalSection(&binding->section); +} + +static void handle_mime_available(Binding *binding, BOOL verify) +{ + BOOL report_mime; + + EnterCriticalSection(&binding->section); + report_mime = binding->report_mime; + binding->report_mime = FALSE; + LeaveCriticalSection(&binding->section); + + if(!report_mime) + return; + + if(verify) { + LPWSTR mime = NULL; + + fill_stream_buffer(binding->stream); + FindMimeFromData(NULL, binding->url, binding->stream->buf, + min(binding->stream->buf_size, 255), binding->mime, 0, &mime, 0); + + heap_free(binding->mime); + binding->mime = heap_strdupW(mime); + CoTaskMemFree(mime); + } + + IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, binding->mime); + + binding->clipboard_format = RegisterClipboardFormatW(binding->mime); +} + +typedef struct { + task_header_t header; + BOOL verify; +} mime_available_task_t; + +static void mime_available_proc(Binding *binding, task_header_t *t) +{ + mime_available_task_t *task = (mime_available_task_t*)t; + + handle_mime_available(binding, task->verify); + + heap_free(task); +} + +static void mime_available(Binding *This, LPCWSTR mime, BOOL verify) +{ + if(mime) + set_binding_mime(This, mime); + + if(GetCurrentThreadId() == This->apartment_thread) { + handle_mime_available(This, verify); + }else { + mime_available_task_t *task = heap_alloc(sizeof(task_header_t)); + task->verify = verify; + push_task(This, &task->header, mime_available_proc); + } +} + #define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface) static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface, @@ -725,18 +795,14 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink case BINDSTATUS_BEGINDOWNLOADDATA: fill_stream_buffer(This->stream); break; - case BINDSTATUS_MIMETYPEAVAILABLE: { - int len = strlenW(szStatusText)+1; - This->mime = heap_alloc(len*sizeof(WCHAR)); - memcpy(This->mime, szStatusText, len*sizeof(WCHAR)); + case BINDSTATUS_MIMETYPEAVAILABLE: + set_binding_mime(This, szStatusText); break; - } case BINDSTATUS_SENDINGREQUEST: on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText); break; case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: - This->report_mime = FALSE; - on_progress(This, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, szStatusText); + mime_available(This, szStatusText, FALSE); break; case BINDSTATUS_CACHEFILENAMEAVAILABLE: break; @@ -764,19 +830,8 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres if(GetCurrentThreadId() != This->apartment_thread) FIXME("called from worked hread\n"); - if(This->report_mime) { - LPWSTR mime; - - This->report_mime = FALSE; - - fill_stream_buffer(This->stream); - - FindMimeFromData(NULL, This->url, This->stream->buf, - min(This->stream->buf_size, 255), This->mime, 0, &mime, 0); - - IBindStatusCallback_OnProgress(This->callback, progress, progress_max, - BINDSTATUS_MIMETYPEAVAILABLE, mime); - } + if(This->report_mime) + mime_available(This, NULL, TRUE); if(This->download_state == BEFORE_DOWNLOAD) { fill_stream_buffer(This->stream); @@ -801,6 +856,7 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres This->request_locked = SUCCEEDED(hres); } + formatetc.cfFormat = This->clipboard_format; IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress, &formatetc, &This->stgmed); @@ -1137,6 +1193,7 @@ static HRESULT Binding_Create(LPCWSTR url, IBindCtx *pbc, REFIID riid, Binding * ret->service_provider = NULL; ret->stream = NULL; ret->mime = NULL; + ret->clipboard_format = 0; ret->url = NULL; ret->apartment_thread = GetCurrentThreadId(); ret->notif_hwnd = get_notif_hwnd(); diff --git a/dlls/urlmon/tests/url.c b/dlls/urlmon/tests/url.c index 935e92bfd66..91c705df69a 100644 --- a/dlls/urlmon/tests/url.c +++ b/dlls/urlmon/tests/url.c @@ -1080,7 +1080,7 @@ static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWOR ok(pformatetc != NULL, "pformatetx == NULL\n"); if(pformatetc) { - if (mime_type[0]) todo_wine { + if (mime_type[0]) { clipfmt[0] = 0; ok(GetClipboardFormatName(pformatetc->cfFormat, clipfmt, sizeof(clipfmt)-1), "GetClipboardFormatName failed, error %d\n", GetLastError()); diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h index 9f31fb9ca3b..8803ffc80be 100644 --- a/dlls/urlmon/urlmon_main.h +++ b/dlls/urlmon/urlmon_main.h @@ -24,6 +24,8 @@ #include "windef.h" #include "winbase.h" +#include "wine/unicode.h" + extern HINSTANCE URLMON_hInstance; extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); @@ -83,4 +85,19 @@ static inline BOOL heap_free(void *mem) return HeapFree(GetProcessHeap(), 0, mem); } +static inline LPWSTR heap_strdupW(LPCWSTR str) +{ + LPWSTR ret = NULL; + + if(str) { + DWORD size; + + size = (strlenW(str)+1)*sizeof(WCHAR); + ret = heap_alloc(size); + memcpy(ret, str, size); + } + + return ret; +} + #endif /* __WINE_URLMON_MAIN_H */