*/
#include "urlmon_main.h"
-#include "wine/debug.h"
-WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
+typedef void (*task_proc_t)(BindProtocol*,task_header_t*);
-typedef struct BindProtocol BindProtocol;
-
-struct _task_header_t;
-
-typedef void (*task_proc_t)(BindProtocol*,struct _task_header_t*);
-
-typedef struct _task_header_t {
+struct _task_header_t {
task_proc_t proc;
- struct _task_header_t *next;
-} task_header_t;
-
-struct BindProtocol {
- const IInternetProtocolVtbl *lpIInternetProtocolVtbl;
- const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
- const IInternetPriorityVtbl *lpInternetPriorityVtbl;
- const IServiceProviderVtbl *lpServiceProviderVtbl;
- const IInternetProtocolSinkVtbl *lpIInternetProtocolSinkVtbl;
- const IWinInetHttpInfoVtbl *lpIWinInetHttpInfoVtbl;
-
- const IInternetProtocolVtbl *lpIInternetProtocolHandlerVtbl;
-
- LONG ref;
-
- IInternetProtocol *protocol;
- IInternetProtocol *protocol_handler;
- IInternetBindInfo *bind_info;
- IInternetProtocolSink *protocol_sink;
- IServiceProvider *service_provider;
- IWinInetInfo *wininet_info;
+ task_header_t *next;
+};
- LONG priority;
+#define BUFFER_SIZE 2048
+#define MIME_TEST_SIZE 255
- BOOL reported_result;
- BOOL reported_mime;
- BOOL from_urlmon;
- DWORD pi;
+#define WM_MK_CONTINUE (WM_USER+101)
+#define WM_MK_RELEASE (WM_USER+102)
- DWORD apartment_thread;
- HWND notif_hwnd;
- DWORD continue_call;
+static void process_tasks(BindProtocol *This)
+{
+ task_header_t *task;
- CRITICAL_SECTION section;
- task_header_t *task_queue_head, *task_queue_tail;
+ while(1) {
+ EnterCriticalSection(&This->section);
- BYTE *buf;
- DWORD buf_size;
- LPWSTR mime;
- LPWSTR url;
- ProtocolProxy *filter_proxy;
-};
-
-#define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
-#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
-#define HTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpIWinInetHttpInfoVtbl)
-#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
+ task = This->task_queue_head;
+ if(task) {
+ This->task_queue_head = task->next;
+ if(!This->task_queue_head)
+ This->task_queue_tail = NULL;
+ }
-#define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl)
+ LeaveCriticalSection(&This->section);
-#define BUFFER_SIZE 2048
-#define MIME_TEST_SIZE 255
+ if(!task)
+ break;
-#define WM_MK_CONTINUE (WM_USER+101)
-#define WM_MK_RELEASE (WM_USER+102)
+ This->continue_call++;
+ task->proc(This, task);
+ This->continue_call--;
+ }
+}
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_MK_CONTINUE: {
BindProtocol *This = (BindProtocol*)lParam;
- 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;
- }
+ process_tasks(This);
- LeaveCriticalSection(&This->section);
-
- if(!task)
- break;
-
- This->continue_call++;
- task->proc(This, task);
- This->continue_call--;
- }
-
- IInternetProtocol_Release(PROTOCOL(This));
+ IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
return 0;
}
case WM_MK_RELEASE: {
LeaveCriticalSection(&This->section);
if(do_post) {
- IInternetProtocol_AddRef(PROTOCOL(This));
+ IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
}
}
+static inline BOOL is_apartment_thread(BindProtocol *This)
+{
+ return This->apartment_thread == GetCurrentThreadId();
+}
+
static inline BOOL do_direct_notif(BindProtocol *This)
{
- return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
+ return !(This->pi & PI_APARTMENTTHREADED) || (is_apartment_thread(This) && !This->continue_call);
}
-static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
+static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
{
PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
- IInternetProtocolSink *protocol_sink, *old_sink;
- ProtocolProxy *filter_proxy;
HRESULT hres;
- hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
- if(FAILED(hres))
- return hres;
-
- hres = create_protocol_proxy(PROTOCOLHANDLER(This), This->protocol_sink, &filter_proxy);
+ hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
if(FAILED(hres)) {
- IInternetProtocolSink_Release(protocol_sink);
+ This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
return hres;
}
- old_sink = This->protocol_sink;
- This->protocol_sink = protocol_sink;
- This->filter_proxy = filter_proxy;
-
IInternetProtocol_AddRef(mime_filter);
This->protocol_handler = mime_filter;
- filter_data.pProtocol = PROTOCOL(filter_proxy);
- hres = IInternetProtocol_Start(mime_filter, mime, PROTSINK(filter_proxy), BINDINFO(This),
- PI_FILTER_MODE|PI_FORCE_ASYNC, (HANDLE_PTR)&filter_data);
+ filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
+ hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
+ &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
+ (HANDLE_PTR)&filter_data);
if(FAILED(hres)) {
- IInternetProtocolSink_Release(old_sink);
+ IInternetProtocolSink_Release(This->protocol_sink_handler);
+ IInternetProtocol_Release(This->protocol_handler);
+ This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
+ This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
return hres;
}
- IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
- IInternetProtocolSink_Release(old_sink);
+ /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense so it seems to be a bug there. */
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
- This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
return S_OK;
}
HRESULT hres;
heap_free(This->mime);
- This->mime = NULL;
+ This->mime = heap_strdupW(mime);
- mime_filter = get_mime_filter(mime);
- if(mime_filter) {
+ if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
+ && (mime_filter = get_mime_filter(mime))) {
TRACE("Got mime filter for %s\n", debugstr_w(mime));
- hres = handle_mime_filter(This, mime_filter, mime);
+ hres = handle_mime_filter(This, mime_filter);
IInternetProtocol_Release(mime_filter);
if(FAILED(hres))
FIXME("MIME filter failed: %08x\n", hres);
- }else {
- This->mime = heap_strdupW(mime);
-
- if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
- This->reported_mime = TRUE;
+ }
- if(This->protocol_sink)
- IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
- }
+ if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
+ This->reported_mime = TRUE;
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
}
}
-#define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocol, iface)
+static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
+}
-static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
- *ppv = PROTOCOL(This);
+ *ppv = &This->IInternetProtocolEx_iface;
}else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
- *ppv = PROTOCOL(This);
+ *ppv = &This->IInternetProtocolEx_iface;
}else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
- *ppv = PROTOCOL(This);
+ *ppv = &This->IInternetProtocolEx_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
+ *ppv = &This->IInternetProtocolEx_iface;
}else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
- *ppv = BINDINFO(This);
+ *ppv = &This->IInternetBindInfo_iface;
}else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
- *ppv = PRIORITY(This);
+ *ppv = &This->IInternetPriority_iface;
}else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
}else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
- *ppv = SERVPROV(This);
+ *ppv = &This->IServiceProvider_iface;
}else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
- *ppv = PROTSINK(This);
+ *ppv = &This->IInternetProtocolSink_iface;
}else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
if(SUCCEEDED(hres)) {
- *ppv = HTTPINFO(This);
+ *ppv = &This->IWinInetHttpInfo_iface;
IWinInetInfo_Release(inet_info);
}
}
hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
if(SUCCEEDED(hres)) {
- *ppv = HTTPINFO(This);
+ *ppv = &This->IWinInetHttpInfo_iface;
IWinInetHttpInfo_Release(http_info);
}
}
return S_OK;
}
-static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface)
+static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
-static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
+static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
if(This->wininet_info)
IWinInetInfo_Release(This->wininet_info);
+ if(This->wininet_http_info)
+ IWinInetHttpInfo_Release(This->wininet_http_info);
if(This->protocol)
IInternetProtocol_Release(This->protocol);
if(This->bind_info)
IInternetBindInfo_Release(This->bind_info);
- if(This->protocol_handler && This->protocol_handler != PROTOCOLHANDLER(This))
+ if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
IInternetProtocol_Release(This->protocol_handler);
- if(This->filter_proxy)
- IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
+ if(This->protocol_sink_handler &&
+ This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
+ IInternetProtocolSink_Release(This->protocol_sink_handler);
+ if(This->uri)
+ IUri_Release(This->uri);
+ SysFreeString(This->display_uri);
- set_binding_sink(PROTOCOL(This), NULL, NULL);
+ set_binding_sink(This, NULL, NULL);
if(This->notif_hwnd)
release_notif_hwnd(This->notif_hwnd);
+ This->section.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->section);
heap_free(This->mime);
- heap_free(This->url);
heap_free(This);
URLMON_UnlockModule();
return ref;
}
-static HRESULT WINAPI BindProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
+static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
DWORD grfPI, HANDLE_PTR dwReserved)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
+ IUri *uri;
+ HRESULT hres;
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
pOIBindInfo, grfPI, dwReserved);
- return IInternetProtocol_Start(This->protocol_handler, szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
+ hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
+ if(FAILED(hres))
+ return hres;
+
+ hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
+ pOIBindInfo, grfPI, (HANDLE*)dwReserved);
+
+ IUri_Release(uri);
+ return hres;
}
-static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
+static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
TRACE("(%p)->(%p)\n", This, pProtocolData);
return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
}
-static HRESULT WINAPI BindProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
+static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
DWORD dwOptions)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
- FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
- return E_NOTIMPL;
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
+
+ TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
+
+ return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
}
-static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
+static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
TRACE("(%p)->(%08x)\n", This, dwOptions);
return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
}
-static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocol *iface)
+static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
-static HRESULT WINAPI BindProtocol_Resume(IInternetProtocol *iface)
+static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
-static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv,
+static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
ULONG cb, ULONG *pcbRead)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
}
-static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
+static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
return E_NOTIMPL;
}
-static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
+static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
TRACE("(%p)->(%08x)\n", This, dwOptions);
return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
}
-static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
+static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
{
- BindProtocol *This = PROTOCOL_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
TRACE("(%p)\n", This);
return IInternetProtocol_UnlockRequest(This->protocol_handler);
}
-void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
-{
- BindProtocol *This = PROTOCOL_THIS(bind_protocol);
- IInternetProtocolSink *prev_sink;
- IServiceProvider *service_provider = NULL;
-
- if(sink)
- IInternetProtocolSink_AddRef(sink);
- prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
- if(prev_sink)
- IInternetProtocolSink_Release(prev_sink);
-
- if(sink)
- IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
- service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
- if(service_provider)
- IServiceProvider_Release(service_provider);
-
- if(bind_info)
- IInternetBindInfo_AddRef(bind_info);
- bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
- if(bind_info)
- IInternetBindInfo_Release(bind_info);
-}
-
-IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
-{
- BindProtocol *This = PROTOCOL_THIS(bind_protocol);
-
- return This->wininet_info;
-}
-
-#undef PROTOCOL_THIS
-
-static const IInternetProtocolVtbl BindProtocolVtbl = {
- BindProtocol_QueryInterface,
- BindProtocol_AddRef,
- BindProtocol_Release,
- BindProtocol_Start,
- BindProtocol_Continue,
- BindProtocol_Abort,
- BindProtocol_Terminate,
- BindProtocol_Suspend,
- BindProtocol_Resume,
- BindProtocol_Read,
- BindProtocol_Seek,
- BindProtocol_LockRequest,
- BindProtocol_UnlockRequest
-};
-
-#define PROTOCOLHANDLER_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolHandler, iface)
-
-static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
-{
- ERR("should not be called\n");
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
-{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
- return IInternetProtocol_AddRef(PROTOCOL(This));
-}
-
-static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
-{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
- return IInternetProtocol_Release(PROTOCOL(This));
-}
-
-static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
+static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
- DWORD grfPI, HANDLE_PTR dwReserved)
+ DWORD grfPI, HANDLE *dwReserved)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolEx(iface);
IInternetProtocol *protocol = NULL;
+ IInternetProtocolEx *protocolex;
IInternetPriority *priority;
IServiceProvider *service_provider;
BOOL urlmon_protocol = FALSE;
LPOLESTR clsid_str;
HRESULT hres;
- TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
- pOIBindInfo, grfPI, dwReserved);
+ TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
- if(!szUrl || !pOIProtSink || !pOIBindInfo)
+ if(!pUri || !pOIProtSink || !pOIBindInfo)
return E_INVALIDARG;
This->pi = grfPI;
- This->url = heap_strdupW(szUrl);
+
+ IUri_AddRef(pUri);
+ This->uri = pUri;
hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
(void**)&service_provider);
if(SUCCEEDED(hres)) {
/* FIXME: What's protocol CLSID here? */
IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
- &IID_IInternetProtocol, (void**)&protocol);
+ &IID_IInternetProtocol, (void**)&protocol);
IServiceProvider_Release(service_provider);
}
IClassFactory *cf;
IUnknown *unk;
- hres = get_protocol_handler(szUrl, &clsid, &urlmon_protocol, &cf);
+ hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
if(FAILED(hres))
return hres;
if(FAILED(hres))
return hres;
}else {
- hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
+ hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
&IID_IUnknown, (void**)&unk);
IClassFactory_Release(cf);
if(FAILED(hres))
This->protocol = protocol;
- if(urlmon_protocol)
+ if(urlmon_protocol) {
IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
+ IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
+ }
- set_binding_sink(PROTOCOL(This), pOIProtSink, pOIBindInfo);
+ set_binding_sink(This, pOIProtSink, pOIBindInfo);
hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
if(SUCCEEDED(hres)) {
IInternetPriority_Release(priority);
}
- return IInternetProtocol_Start(protocol, szUrl, PROTSINK(This), BINDINFO(This), 0, 0);
+ hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
+ if(SUCCEEDED(hres)) {
+ hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
+ &This->IInternetBindInfo_iface, 0, NULL);
+ IInternetProtocolEx_Release(protocolex);
+ }else {
+ hres = IUri_GetDisplayUri(pUri, &This->display_uri);
+ if(FAILED(hres))
+ return hres;
+
+ hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
+ &This->IInternetBindInfo_iface, 0, 0);
+ }
+
+ if(SUCCEEDED(hres))
+ process_tasks(This);
+ return hres;
+}
+
+void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
+{
+ IInternetProtocolSink *prev_sink;
+ IServiceProvider *service_provider = NULL;
+
+ if(sink)
+ IInternetProtocolSink_AddRef(sink);
+ prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
+ if(prev_sink)
+ IInternetProtocolSink_Release(prev_sink);
+
+ if(sink)
+ IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
+ service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
+ if(service_provider)
+ IServiceProvider_Release(service_provider);
+
+ if(bind_info)
+ IInternetBindInfo_AddRef(bind_info);
+ bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
+ if(bind_info)
+ IInternetBindInfo_Release(bind_info);
+}
+
+static const IInternetProtocolExVtbl BindProtocolVtbl = {
+ BindProtocol_QueryInterface,
+ BindProtocol_AddRef,
+ BindProtocol_Release,
+ BindProtocol_Start,
+ BindProtocol_Continue,
+ BindProtocol_Abort,
+ BindProtocol_Terminate,
+ BindProtocol_Suspend,
+ BindProtocol_Resume,
+ BindProtocol_Read,
+ BindProtocol_Seek,
+ BindProtocol_LockRequest,
+ BindProtocol_UnlockRequest,
+ BindProtocol_StartEx
+};
+
+static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
+}
+
+static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+{
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
+
+ *ppv = NULL;
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
+ *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
+ *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
+ *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
+ }
+
+ if(*ppv) {
+ IInternetProtocol_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("not supported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
+{
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
+}
+
+static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
+{
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
+}
+
+static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
+ IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
+ DWORD grfPI, HANDLE_PTR dwReserved)
+{
+ ERR("Should not be called\n");
+ return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
HRESULT hres;
TRACE("(%p)->(%p)\n", This, pProtocolData);
static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
DWORD dwOptions)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
- FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
- return E_NOTIMPL;
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
+
+ TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
+
+ if(This->protocol && !This->reported_result)
+ return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
+
+ return S_OK;
}
static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
TRACE("(%p)->(%08x)\n", This, dwOptions);
IInternetProtocol_Terminate(This->protocol, 0);
- if(This->filter_proxy) {
- IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
- This->filter_proxy = NULL;
- }
-
- set_binding_sink(PROTOCOL(This), NULL, NULL);
+ set_binding_sink(This, NULL, NULL);
if(This->bind_info) {
IInternetBindInfo_Release(This->bind_info);
static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
ULONG cb, ULONG *pcbRead)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
ULONG read = 0;
HRESULT hres = S_OK;
if(read < cb) {
ULONG cread = 0;
+ if(is_apartment_thread(This))
+ This->continue_call++;
hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
+ if(is_apartment_thread(This))
+ This->continue_call--;
read += cread;
}
static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
TRACE("(%p)->(%08x)\n", This, dwOptions);
static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
{
- BindProtocol *This = PROTOCOLHANDLER_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocol(iface);
TRACE("(%p)\n", This);
return IInternetProtocol_UnlockRequest(This->protocol);
}
-#undef PROTOCOL_THIS
-
static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
ProtocolHandler_QueryInterface,
ProtocolHandler_AddRef,
ProtocolHandler_UnlockRequest
};
-#define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
+static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
+ REFIID riid, void **ppvObject)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+ return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
+ riid, ppvObject);
+}
+
+static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
+}
+
+static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
+ PROTOCOLDATA *pProtocolData)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+ TRACE("(%p)->(%p)\n", This, pProtocolData);
+
+ if(!This->protocol_sink) {
+ IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
+ return S_OK;
+ }
+
+ return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
+ ULONG status_code, LPCWSTR status_text)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+ TRACE("(%p)->(%s %s)\n", This, debugstr_bindstatus(status_code), debugstr_w(status_text));
+
+ if(!This->protocol_sink)
+ return S_OK;
+
+ switch(status_code) {
+ case BINDSTATUS_FINDINGRESOURCE:
+ case BINDSTATUS_CONNECTING:
+ case BINDSTATUS_REDIRECTING:
+ case BINDSTATUS_SENDINGREQUEST:
+ case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+ case BINDSTATUS_DIRECTBIND:
+ case BINDSTATUS_ACCEPTRANGES:
+ case BINDSTATUS_DECODING:
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
+ break;
+
+ case BINDSTATUS_BEGINDOWNLOADDATA:
+ IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
+ break;
+
+ case BINDSTATUS_MIMETYPEAVAILABLE:
+ mime_available(This, status_text, FALSE);
+ break;
+
+ case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
+ mime_available(This, status_text, TRUE);
+ break;
+
+ default:
+ FIXME("unsupported ulStatusCode %u\n", status_code);
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
+ DWORD bscf, ULONG progress, ULONG progress_max)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+ TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
+
+ This->bscf = bscf;
+ This->progress = progress;
+ This->progress_max = progress_max;
+
+ if(!This->protocol_sink)
+ return S_OK;
+
+ if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
+ BYTE buf[BUFFER_SIZE];
+ DWORD read = 0;
+ LPWSTR mime;
+ HRESULT hres;
+
+ do {
+ read = 0;
+ if(is_apartment_thread(This))
+ This->continue_call++;
+ hres = IInternetProtocol_Read(This->protocol, buf,
+ sizeof(buf)-This->buf_size, &read);
+ if(is_apartment_thread(This))
+ This->continue_call--;
+ if(FAILED(hres) && hres != E_PENDING)
+ return hres;
+
+ if(!This->buf) {
+ This->buf = heap_alloc(BUFFER_SIZE);
+ if(!This->buf)
+ return E_OUTOFMEMORY;
+ }else if(read + This->buf_size > BUFFER_SIZE) {
+ BYTE *tmp;
+
+ tmp = heap_realloc(This->buf, read+This->buf_size);
+ if(!tmp)
+ return E_OUTOFMEMORY;
+ This->buf = tmp;
+ }
+
+ memcpy(This->buf+This->buf_size, buf, read);
+ This->buf_size += read;
+ }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
+
+ if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
+ return S_OK;
+
+ bscf = BSCF_FIRSTDATANOTIFICATION;
+ if(hres == S_FALSE)
+ bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
+
+ if(!This->reported_mime) {
+ BSTR raw_uri;
+
+ hres = IUri_GetRawUri(This->uri, &raw_uri);
+ if(FAILED(hres))
+ return hres;
+
+ hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
+ This->mime, 0, &mime, 0);
+ SysFreeString(raw_uri);
+ if(FAILED(hres))
+ return hres;
+
+ heap_free(This->mime);
+ This->mime = heap_strdupW(mime);
+ CoTaskMemFree(mime);
+ This->reported_mime = TRUE;
+ if(This->protocol_sink)
+ IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
+ }
+ }
+
+ if(!This->protocol_sink)
+ return S_OK;
+
+ return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
+ HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
+{
+ BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+ TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
+
+ if(This->protocol_sink)
+ return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
+ return S_OK;
+}
+
+static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
+ ProtocolSinkHandler_QueryInterface,
+ ProtocolSinkHandler_AddRef,
+ ProtocolSinkHandler_Release,
+ ProtocolSinkHandler_Switch,
+ ProtocolSinkHandler_ReportProgress,
+ ProtocolSinkHandler_ReportData,
+ ProtocolSinkHandler_ReportResult
+};
+
+static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
+}
static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
REFIID riid, void **ppv)
{
- BindProtocol *This = BINDINFO_THIS(iface);
- return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+ BindProtocol *This = impl_from_IInternetBindInfo(iface);
+ return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
}
static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
{
- BindProtocol *This = BINDINFO_THIS(iface);
- return IBinding_AddRef(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetBindInfo(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
{
- BindProtocol *This = BINDINFO_THIS(iface);
- return IBinding_Release(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetBindInfo(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
DWORD *grfBINDF, BINDINFO *pbindinfo)
{
- BindProtocol *This = BINDINFO_THIS(iface);
+ BindProtocol *This = impl_from_IInternetBindInfo(iface);
HRESULT hres;
TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
{
- BindProtocol *This = BINDINFO_THIS(iface);
+ BindProtocol *This = impl_from_IInternetBindInfo(iface);
TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
}
-#undef BINDFO_THIS
-
static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
BindInfo_QueryInterface,
BindInfo_AddRef,
BindInfo_GetBindString
};
-#define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
+static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
+}
static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
REFIID riid, void **ppv)
{
- BindProtocol *This = PRIORITY_THIS(iface);
- return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+ BindProtocol *This = impl_from_IInternetPriority(iface);
+ return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
}
static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
{
- BindProtocol *This = PRIORITY_THIS(iface);
- return IInternetProtocol_AddRef(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetPriority(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
{
- BindProtocol *This = PRIORITY_THIS(iface);
- return IInternetProtocol_Release(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetPriority(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
{
- BindProtocol *This = PRIORITY_THIS(iface);
+ BindProtocol *This = impl_from_IInternetPriority(iface);
TRACE("(%p)->(%d)\n", This, nPriority);
static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
{
- BindProtocol *This = PRIORITY_THIS(iface);
+ BindProtocol *This = impl_from_IInternetPriority(iface);
TRACE("(%p)->(%p)\n", This, pnPriority);
return S_OK;
}
-#undef PRIORITY_THIS
-
static const IInternetPriorityVtbl InternetPriorityVtbl = {
InternetPriority_QueryInterface,
InternetPriority_AddRef,
};
-#define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
+static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
+}
static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
REFIID riid, void **ppv)
{
- BindProtocol *This = PROTSINK_THIS(iface);
- return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+ return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
}
static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
{
- BindProtocol *This = PROTSINK_THIS(iface);
- return IInternetProtocol_AddRef(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
{
- BindProtocol *This = PROTSINK_THIS(iface);
- return IInternetProtocol_Release(PROTOCOL(This));
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
typedef struct {
static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
PROTOCOLDATA *pProtocolData)
{
- BindProtocol *This = PROTSINK_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
PROTOCOLDATA *data;
TRACE("(%p)->(%p)\n", This, pProtocolData);
return E_OUTOFMEMORY;
memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
- if(!do_direct_notif(This)) {
+ if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
+ || !do_direct_notif(This)) {
switch_task_t *task;
task = heap_alloc(sizeof(switch_task_t));
if(!task)
+ {
+ heap_free(data);
return E_OUTOFMEMORY;
+ }
task->data = data;
return S_OK;
}
- if(!This->protocol_sink) {
- IInternetProtocol_Continue(This->protocol_handler, data);
- return S_OK;
- }
-
- return IInternetProtocolSink_Switch(This->protocol_sink, data);
-}
-
-static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
-{
- switch(status_code) {
- case BINDSTATUS_FINDINGRESOURCE:
- case BINDSTATUS_CONNECTING:
- case BINDSTATUS_REDIRECTING:
- 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:
- mime_available(This, status_text, FALSE);
- break;
-
- case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
- mime_available(This, status_text, TRUE);
- break;
-
- default:
- FIXME("unsupported ulStatusCode %u\n", status_code);
- }
+ return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
}
typedef struct {
{
on_progress_task_t *task = (on_progress_task_t*)t;
- report_progress(This, task->status_code, task->status_text);
+ IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
heap_free(task->status_text);
heap_free(task);
static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
ULONG ulStatusCode, LPCWSTR szStatusText)
{
- BindProtocol *This = PROTSINK_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
if(do_direct_notif(This)) {
- report_progress(This, ulStatusCode, szStatusText);
+ IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
}else {
on_progress_task_t *task;
return S_OK;
}
-static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
-{
- if(!This->protocol_sink)
- return S_OK;
-
- if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
- BYTE buf[BUFFER_SIZE];
- DWORD read = 0;
- LPWSTR mime;
- HRESULT hres;
-
- do {
- read = 0;
- hres = IInternetProtocol_Read(This->protocol, buf,
- sizeof(buf)-This->buf_size, &read);
- if(FAILED(hres) && hres != E_PENDING)
- return hres;
-
- if(!This->buf) {
- This->buf = heap_alloc(BUFFER_SIZE);
- if(!This->buf)
- return E_OUTOFMEMORY;
- }else if(read + This->buf_size > BUFFER_SIZE) {
- BYTE *tmp;
-
- tmp = heap_realloc(This->buf, read+This->buf_size);
- if(!tmp)
- return E_OUTOFMEMORY;
- This->buf = tmp;
- }
-
- memcpy(This->buf+This->buf_size, buf, read);
- This->buf_size += read;
- }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
-
- if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
- return S_OK;
-
- bscf = BSCF_FIRSTDATANOTIFICATION;
- if(hres == S_FALSE)
- bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
-
- if(!This->reported_mime) {
- hres = FindMimeFromData(NULL, This->url, This->buf, min(This->buf_size, MIME_TEST_SIZE),
- This->mime, 0, &mime, 0);
- if(FAILED(hres))
- return hres;
-
- mime_available(This, mime, TRUE);
- CoTaskMemFree(mime);
- }
- }
-
- if(!This->protocol_sink)
- return S_OK;
-
- return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
-}
-
typedef struct {
task_header_t header;
DWORD bscf;
{
report_data_task_t *task = (report_data_task_t*)t;
- report_data(This, task->bscf, task->progress, task->progress_max);
+ IInternetProtocolSink_ReportData(This->protocol_sink_handler,
+ task->bscf, task->progress, task->progress_max);
+
heap_free(task);
}
static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
{
- BindProtocol *This = PROTSINK_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
- TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
+ TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
if(!This->protocol_sink)
return S_OK;
return S_OK;
}
- return report_data(This, grfBSCF, ulProgress, ulProgressMax);
+ return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
+ grfBSCF, ulProgress, ulProgressMax);
}
typedef struct {
{
report_result_task_t *task = (report_result_task_t*)t;
- if(This->protocol_sink)
- IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
+ IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
heap_free(task->str);
heap_free(task);
static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
{
- BindProtocol *This = PROTSINK_THIS(iface);
+ BindProtocol *This = impl_from_IInternetProtocolSink(iface);
TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
if(!This->protocol_sink)
return E_FAIL;
-
This->reported_result = TRUE;
if(!do_direct_notif(This)) {
return S_OK;
}
- return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
+ return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
}
-#undef PROTSINK_THIS
-
static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
BPInternetProtocolSink_QueryInterface,
BPInternetProtocolSink_AddRef,
BPInternetProtocolSink_ReportResult
};
-#define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
+static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
+}
static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
{
- BindProtocol *This = INETINFO_THIS(iface);
- return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+ BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+ return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
}
static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
{
- BindProtocol *This = INETINFO_THIS(iface);
- return IInternetProtocol_AddRef(PROTOCOL(This));
+ BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
{
- BindProtocol *This = INETINFO_THIS(iface);
- return IInternetProtocol_Release(PROTOCOL(This));
+ BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
void *pBuffer, DWORD *pcbBuffer)
{
- BindProtocol *This = INETINFO_THIS(iface);
+ BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
return E_NOTIMPL;
}
static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
{
- BindProtocol *This = INETINFO_THIS(iface);
+ BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
return E_NOTIMPL;
}
-#undef INETINFO_THIS
-
static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
WinInetHttpInfo_QueryInterface,
WinInetHttpInfo_AddRef,
WinInetHttpInfo_QueryInfo
};
-#define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
+static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+ return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
+}
static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
REFIID riid, void **ppv)
{
- BindProtocol *This = SERVPROV_THIS(iface);
- return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+ BindProtocol *This = impl_from_IServiceProvider(iface);
+ return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
}
static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
{
- BindProtocol *This = SERVPROV_THIS(iface);
- return IInternetProtocol_AddRef(PROTOCOL(This));
+ BindProtocol *This = impl_from_IServiceProvider(iface);
+ return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
{
- BindProtocol *This = SERVPROV_THIS(iface);
- return IInternetProtocol_Release(PROTOCOL(This));
+ BindProtocol *This = impl_from_IServiceProvider(iface);
+ return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
REFGUID guidService, REFIID riid, void **ppv)
{
- BindProtocol *This = SERVPROV_THIS(iface);
+ BindProtocol *This = impl_from_IServiceProvider(iface);
TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
}
-#undef SERVPROV_THIS
-
static const IServiceProviderVtbl ServiceProviderVtbl = {
BPServiceProvider_QueryInterface,
BPServiceProvider_AddRef,
BPServiceProvider_QueryService
};
-HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol)
+HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
{
BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
- ret->lpIInternetProtocolVtbl = &BindProtocolVtbl;
- ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
- ret->lpInternetPriorityVtbl = &InternetPriorityVtbl;
- ret->lpServiceProviderVtbl = &ServiceProviderVtbl;
- ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
- ret->lpIInternetProtocolHandlerVtbl = &InternetProtocolHandlerVtbl;
- ret->lpIWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl;
+ ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
+ ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
+ ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
+ ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
+ ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
+ ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
+
+ ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
+ ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
ret->ref = 1;
ret->from_urlmon = from_urlmon;
ret->apartment_thread = GetCurrentThreadId();
ret->notif_hwnd = get_notif_hwnd();
- ret->protocol_handler = PROTOCOLHANDLER(ret);
+ ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
+ ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
InitializeCriticalSection(&ret->section);
+ ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
URLMON_LockModule();
- *protocol = PROTOCOL(ret);
+ *protocol = ret;
return S_OK;
}