Jacek Caban : urlmon: Added PI_MIMEVERIFICATION support.
Alexandre Julliard
julliard at winehq.org
Thu May 14 11:07:41 CDT 2009
Module: wine
Branch: master
Commit: 299ce6c18eb7dfaf8f339658b2f5e606936fb8bc
URL: http://source.winehq.org/git/wine.git/?a=commit;h=299ce6c18eb7dfaf8f339658b2f5e606936fb8bc
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu May 14 00:49:01 2009 +0200
urlmon: Added PI_MIMEVERIFICATION support.
---
dlls/urlmon/bindprot.c | 163 ++++++++++++++++++++++++++++++++++++-----------
1 files changed, 125 insertions(+), 38 deletions(-)
diff --git a/dlls/urlmon/bindprot.c b/dlls/urlmon/bindprot.c
index 7235b63..d431095 100644
--- a/dlls/urlmon/bindprot.c
+++ b/dlls/urlmon/bindprot.c
@@ -50,6 +50,7 @@ struct BindProtocol {
LONG priority;
BOOL reported_result;
+ BOOL reported_mime;
BOOL from_urlmon;
DWORD pi;
@@ -59,6 +60,11 @@ struct BindProtocol {
CRITICAL_SECTION section;
task_header_t *task_queue_head, *task_queue_tail;
+
+ BYTE *buf;
+ DWORD buf_size;
+ LPWSTR mime;
+ LPWSTR url;
};
#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
@@ -67,6 +73,9 @@ struct BindProtocol {
#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
#define PROTSINK(x) ((IInternetProtocolSink*) &(x)->lpInternetProtocolSinkVtbl)
+#define BUFFER_SIZE 2048
+#define MIME_TEST_SIZE 255
+
#define WM_MK_CONTINUE (WM_USER+101)
#define WM_MK_RELEASE (WM_USER+102)
@@ -272,6 +281,9 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
if(This->notif_hwnd)
release_notif_hwnd(This->notif_hwnd);
DeleteCriticalSection(&This->section);
+
+ heap_free(This->mime);
+ heap_free(This->url);
heap_free(This);
URLMON_UnlockModule();
@@ -300,6 +312,7 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
return E_INVALIDARG;
This->pi = grfPI;
+ This->url = heap_strdupW(szUrl);
hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
(void**)&service_provider);
@@ -417,11 +430,30 @@ static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
{
BindProtocol *This = PROTOCOL_THIS(iface);
ULONG read = 0;
- HRESULT hres;
+ HRESULT hres = S_OK;
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
- hres = IInternetProtocol_Read(This->protocol, pv, cb, &read);
+ if(This->buf) {
+ read = min(cb, This->buf_size);
+ memcpy(pv, This->buf, read);
+
+ if(read == This->buf_size) {
+ heap_free(This->buf);
+ This->buf = NULL;
+ }else {
+ memmove(This->buf, This->buf+cb, This->buf_size-cb);
+ }
+
+ This->buf_size -= read;
+ }
+
+ if(read < cb) {
+ ULONG cread = 0;
+
+ hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb, &cread);
+ read += cread;
+ }
*pcbRead = read;
return hres;
@@ -674,6 +706,47 @@ static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface
return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
}
+static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
+{
+ switch(status_code) {
+ case BINDSTATUS_FINDINGRESOURCE:
+ case BINDSTATUS_CONNECTING:
+ case BINDSTATUS_BEGINDOWNLOADDATA:
+ case BINDSTATUS_SENDINGREQUEST:
+ case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+ case BINDSTATUS_DIRECTBIND:
+ case BINDSTATUS_ACCEPTRANGES:
+ if(This->protocol_sink)
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
+ break;
+
+ case BINDSTATUS_MIMETYPEAVAILABLE:
+ if(!This->reported_mime) {
+ heap_free(This->mime);
+ This->mime = heap_strdupW(status_text);
+ }
+
+ if(This->protocol_sink && !(This->pi & PI_MIMEVERIFICATION))
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
+ break;
+
+ case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
+ if(!This->reported_mime) {
+ heap_free(This->mime);
+ This->mime = heap_strdupW(status_text);
+ }
+
+ if(This->protocol_sink) {
+ This->reported_mime = TRUE;
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, status_text);
+ }
+ break;
+
+ default:
+ FIXME("unsupported ulStatusCode %u\n", status_code);
+ }
+}
+
typedef struct {
task_header_t header;
@@ -685,63 +758,79 @@ static void on_progress_proc(BindProtocol *This, task_header_t *t)
{
on_progress_task_t *task = (on_progress_task_t*)t;
- IInternetProtocolSink_ReportProgress(This->protocol_sink, task->status_code, task->status_text);
+ report_progress(This, task->status_code, task->status_text);
heap_free(task->status_text);
heap_free(task);
}
-static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
+static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
+ ULONG ulStatusCode, LPCWSTR szStatusText)
{
+ BindProtocol *This = PROTSINK_THIS(iface);
+
+ TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
+
if(do_direct_notif(This)) {
- IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
+ report_progress(This, ulStatusCode, szStatusText);
}else {
on_progress_task_t *task;
task = heap_alloc(sizeof(on_progress_task_t));
- task->status_code = status_code;
- task->status_text = heap_strdupW(status_text);
+ task->status_code = ulStatusCode;
+ task->status_text = heap_strdupW(szStatusText);
push_task(This, &task->header, on_progress_proc);
}
+
+ return S_OK;
}
-static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
- ULONG ulStatusCode, LPCWSTR szStatusText)
+static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
{
- BindProtocol *This = PROTSINK_THIS(iface);
+ if(!This->protocol_sink)
+ return S_OK;
- TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
+ if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
+ DWORD read = 0;
+ LPWSTR mime;
+ HRESULT hres;
- switch(ulStatusCode) {
- case BINDSTATUS_FINDINGRESOURCE:
- case BINDSTATUS_CONNECTING:
- case BINDSTATUS_BEGINDOWNLOADDATA:
- case BINDSTATUS_SENDINGREQUEST:
- case BINDSTATUS_CACHEFILENAMEAVAILABLE:
- case BINDSTATUS_DIRECTBIND:
- case BINDSTATUS_ACCEPTRANGES:
- case BINDSTATUS_MIMETYPEAVAILABLE:
- if(!This->protocol_sink)
- return S_OK;
- report_progress(This, ulStatusCode, szStatusText);
- break;
+ if(!This->buf) {
+ This->buf = heap_alloc(BUFFER_SIZE);
+ if(!This->buf)
+ return E_OUTOFMEMORY;
+ }
- case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
- if(!This->protocol_sink)
+ do {
+ read = 0;
+ hres = IInternetProtocol_Read(This->protocol, This->buf+This->buf_size, BUFFER_SIZE-This->buf_size, &read);
+ if(hres != S_OK)
+ break;
+ This->buf_size += read;
+ }while(This->buf_size < MIME_TEST_SIZE);
+ if(FAILED(hres) && hres != E_PENDING)
+ return hres;
+
+ This->buf_size += read;
+ if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
return S_OK;
- report_progress(This,
- This->from_urlmon ? BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
- szStatusText);
- break;
- default:
- FIXME("unsupported ulStatusCode %u\n", ulStatusCode);
- return E_NOTIMPL;
+
+ hres = FindMimeFromData(NULL, This->url, This->buf, min(This->buf_size, MIME_TEST_SIZE), This->mime, 0, &mime, 0);
+ if(FAILED(hres))
+ return hres;
+
+ heap_free(This->mime);
+ This->mime = heap_strdupW(mime);
+ CoTaskMemFree(mime);
+
+ This->reported_mime = TRUE;
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
}
- return S_OK;
+ return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
}
typedef struct {
@@ -755,9 +844,7 @@ static void report_data_proc(BindProtocol *This, task_header_t *t)
{
report_data_task_t *task = (report_data_task_t*)t;
- if(This->protocol_sink)
- IInternetProtocolSink_ReportData(This->protocol_sink, task->bscf, task->progress, task->progress_max);
-
+ report_data(This, task->bscf, task->progress, task->progress_max);
heap_free(task);
}
@@ -786,7 +873,7 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *i
return S_OK;
}
- return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
+ return report_data(This, grfBSCF, ulProgress, ulProgressMax);
}
typedef struct {
More information about the wine-cvs
mailing list