From 6c76be5e63aaf7b18edd57f847a52d9a8a3236be Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 20 Dec 2010 21:29:55 +0000 Subject: [PATCH] [URLMON] - Sync to Wine 1.3.9 svn path=/trunk/; revision=50074 --- reactos/dll/win32/urlmon/bindctx.c | 54 +- reactos/dll/win32/urlmon/binding.c | 147 +- reactos/dll/win32/urlmon/bindprot.c | 353 +++-- reactos/dll/win32/urlmon/download.c | 107 +- reactos/dll/win32/urlmon/file.c | 85 +- reactos/dll/win32/urlmon/format.c | 27 +- reactos/dll/win32/urlmon/ftp.c | 191 +-- reactos/dll/win32/urlmon/gopher.c | 12 +- reactos/dll/win32/urlmon/http.c | 241 ++-- reactos/dll/win32/urlmon/protocol.c | 58 + reactos/dll/win32/urlmon/sec_mgr.c | 54 +- reactos/dll/win32/urlmon/session.c | 46 +- reactos/dll/win32/urlmon/umon.c | 21 +- reactos/dll/win32/urlmon/uri.c | 1786 ++++++++++++++++++++---- reactos/dll/win32/urlmon/urlmon.spec | 3 + reactos/dll/win32/urlmon/urlmon_main.c | 245 ++-- reactos/dll/win32/urlmon/urlmon_main.h | 18 +- 17 files changed, 2546 insertions(+), 902 deletions(-) diff --git a/reactos/dll/win32/urlmon/bindctx.c b/reactos/dll/win32/urlmon/bindctx.c index 0b3efa6c874..b08eb80e7a5 100644 --- a/reactos/dll/win32/urlmon/bindctx.c +++ b/reactos/dll/win32/urlmon/bindctx.c @@ -460,9 +460,30 @@ static const IAuthenticateVtbl BSCAuthenticateVtbl = { BSCAuthenticate_Authenticate }; -static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc) +static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc) { - BindStatusCallback *ret = heap_alloc_zero(sizeof(BindStatusCallback)); + IServiceProvider *serv_prov; + HRESULT hres; + + if(This->callback) + IBindStatusCallback_Release(This->callback); + if(This->serv_prov) + IServiceProvider_Release(This->serv_prov); + + IBindStatusCallback_AddRef(bsc); + This->callback = bsc; + + hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov); + This->serv_prov = hres == S_OK ? serv_prov : NULL; +} + +HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface) +{ + BindStatusCallback *ret; + + ret = heap_alloc_zero(sizeof(BindStatusCallback)); + if(!ret) + return E_OUTOFMEMORY; ret->lpBindStatusCallbackExVtbl = &BindStatusCallbackExVtbl; ret->lpServiceProviderVtbl = &BSCServiceProviderVtbl; @@ -470,13 +491,10 @@ static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc) ret->lpAuthenticateVtbl = &BSCAuthenticateVtbl; ret->ref = 1; + set_callback(ret, bsc); - IBindStatusCallback_AddRef(bsc); - ret->callback = bsc; - - IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&ret->serv_prov); - - return STATUSCLB(ret); + *ret_iface = STATUSCLB(ret); + return S_OK; } /*********************************************************************** @@ -511,25 +529,33 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk); if(SUCCEEDED(hres)) { hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc); + IUnknown_Release(unk); if(SUCCEEDED(hres)) { hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder); if(SUCCEEDED(hres)) { - prev = holder->callback; - IBindStatusCallback_AddRef(prev); + if(ppbscPrevious) { + IBindStatusCallback_AddRef(holder->callback); + *ppbscPrevious = holder->callback; + } + + set_callback(holder, pbsc); + IBindStatusCallback_Release(bsc); IBindStatusCallback_Release(STATUSCLB(holder)); + return S_OK; }else { prev = bsc; } } - IUnknown_Release(unk); IBindCtx_RevokeObjectParam(pbc, BSCBHolder); } - bsc = create_bsc(pbsc); - hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc); - IBindStatusCallback_Release(bsc); + hres = wrap_callback(pbsc, &bsc); + if(SUCCEEDED(hres)) { + hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc); + IBindStatusCallback_Release(bsc); + } if(FAILED(hres)) { if(prev) IBindStatusCallback_Release(prev); diff --git a/reactos/dll/win32/urlmon/binding.c b/reactos/dll/win32/urlmon/binding.c index 02053b0cf39..699bf98a76d 100644 --- a/reactos/dll/win32/urlmon/binding.c +++ b/reactos/dll/win32/urlmon/binding.c @@ -18,6 +18,7 @@ #include "urlmon_main.h" #include "winreg.h" +#include "shlwapi.h" #include "wine/debug.h" @@ -42,7 +43,7 @@ typedef struct { LONG ref; - IInternetProtocol *protocol; + IInternetProtocolEx *protocol; BYTE buf[1024*8]; DWORD size; @@ -76,6 +77,7 @@ typedef enum { #define BINDING_LOCKED 0x0001 #define BINDING_STOPPED 0x0002 #define BINDING_OBJAVAIL 0x0004 +#define BINDING_ABORTED 0x0008 struct Binding { const IBindingVtbl *lpBindingVtbl; @@ -87,7 +89,7 @@ struct Binding { LONG ref; IBindStatusCallback *callback; - IInternetProtocol *protocol; + IInternetProtocolEx *protocol; IServiceProvider *service_provider; stgmed_buf_t *stgmed_buf; @@ -426,7 +428,7 @@ static const IUnknownVtbl StgMedUnkVtbl = { StgMedUnk_Release }; -static stgmed_buf_t *create_stgmed_buf(IInternetProtocol *protocol) +static stgmed_buf_t *create_stgmed_buf(IInternetProtocolEx *protocol) { stgmed_buf_t *ret = heap_alloc(sizeof(*ret)); @@ -631,8 +633,30 @@ static HRESULT WINAPI ProtocolStream_Stat(IStream *iface, STATSTG *pstatstg, DWORD dwStatFlag) { ProtocolStream *This = STREAM_THIS(iface); - FIXME("(%p)->(%p %08x)\n", This, pstatstg, dwStatFlag); - return E_NOTIMPL; + TRACE("(%p)->(%p %08x)\n", This, pstatstg, dwStatFlag); + + if(!pstatstg) + return E_FAIL; + + memset(pstatstg, 0, sizeof(STATSTG)); + + if(!(dwStatFlag&STATFLAG_NONAME) && This->buf->cache_file) { + pstatstg->pwcsName = CoTaskMemAlloc((lstrlenW(This->buf->cache_file)+1)*sizeof(WCHAR)); + if(!pstatstg->pwcsName) + return STG_E_INSUFFICIENTMEMORY; + + lstrcpyW(pstatstg->pwcsName, This->buf->cache_file); + } + + pstatstg->type = STGTY_STREAM; + if(This->buf->file != INVALID_HANDLE_VALUE) { + GetFileSizeEx(This->buf->file, (PLARGE_INTEGER)&pstatstg->cbSize); + GetFileTime(This->buf->file, &pstatstg->ctime, &pstatstg->atime, &pstatstg->mtime); + if(pstatstg->cbSize.QuadPart) + pstatstg->grfMode = GENERIC_READ; + } + + return S_OK; } static HRESULT WINAPI ProtocolStream_Clone(IStream *iface, IStream **ppstm) @@ -682,6 +706,10 @@ static HRESULT stgmed_stream_get_result(stgmed_obj_t *obj, DWORD bindf, void **r { ProtocolStream *stream = (ProtocolStream*)obj; + if(!(bindf & BINDF_ASYNCHRONOUS) && stream->buf->file == INVALID_HANDLE_VALUE + && (stream->buf->hres != S_FALSE || stream->buf->size)) + return INET_E_DATA_NOT_AVAILABLE; + IStream_AddRef(STREAM(stream)); *result = STREAM(stream); return S_OK; @@ -862,10 +890,9 @@ static ULONG WINAPI Binding_Release(IBinding *iface) ReleaseBindInfo(&This->bindinfo); This->section.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->section); + SysFreeString(This->url); heap_free(This->mime); heap_free(This->redirect_url); - heap_free(This->url); - heap_free(This); URLMON_UnlockModule(); @@ -877,8 +904,19 @@ static ULONG WINAPI Binding_Release(IBinding *iface) static HRESULT WINAPI Binding_Abort(IBinding *iface) { Binding *This = BINDING_THIS(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + HRESULT hres; + + TRACE("(%p)\n", This); + + if(This->state & BINDING_ABORTED) + return E_FAIL; + + hres = IInternetProtocol_Abort(This->protocol, E_ABORT, ERROR_SUCCESS); + if(FAILED(hres)) + return hres; + + This->state |= BINDING_ABORTED; + return S_OK; } static HRESULT WINAPI Binding_Suspend(IBinding *iface) @@ -1048,7 +1086,7 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres TRACE("(%p)->(%d %u %u)\n", This, bscf, progress, progress_max); - if(This->download_state == END_DOWNLOAD || (This->state & BINDING_STOPPED)) + if(This->download_state == END_DOWNLOAD || (This->state & (BINDING_STOPPED|BINDING_ABORTED))) return; if(This->stgmed_buf->file != INVALID_HANDLE_VALUE) @@ -1076,6 +1114,9 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres BINDSTATUS_DOWNLOADINGDATA, This->url); } + if(This->state & (BINDING_STOPPED|BINDING_ABORTED)) + return; + if(This->to_object) { if(!(This->state & BINDING_OBJAVAIL)) { IBinding_AddRef(BINDING(This)); @@ -1223,7 +1264,7 @@ static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface, return hres; } case BINDSTRING_URL: { - DWORD size = (strlenW(This->url)+1) * sizeof(WCHAR); + DWORD size = (SysStringLen(This->url)+1) * sizeof(WCHAR); if(!ppwzStr || !pcElFetched) return E_INVALIDARG; @@ -1350,50 +1391,37 @@ static HRESULT get_callback(IBindCtx *pbc, IBindStatusCallback **callback) HRESULT hres; hres = IBindCtx_GetObjectParam(pbc, bscb_holderW, &unk); - if(SUCCEEDED(hres)) { - hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)callback); - IUnknown_Release(unk); - } + if(FAILED(hres)) + return create_default_callback(callback); - return SUCCEEDED(hres) ? S_OK : INET_E_DATA_NOT_AVAILABLE; + hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)callback); + IUnknown_Release(unk); + return hres; } -static BOOL is_urlmon_protocol(LPCWSTR url) +static BOOL is_urlmon_protocol(IUri *uri) { - static const WCHAR wszCdl[] = {'c','d','l'}; - static const WCHAR wszFile[] = {'f','i','l','e'}; - static const WCHAR wszFtp[] = {'f','t','p'}; - static const WCHAR wszGopher[] = {'g','o','p','h','e','r'}; - static const WCHAR wszHttp[] = {'h','t','t','p'}; - static const WCHAR wszHttps[] = {'h','t','t','p','s'}; - static const WCHAR wszMk[] = {'m','k'}; + DWORD scheme; + HRESULT hres; - static const struct { - LPCWSTR scheme; - int len; - } protocol_list[] = { - {wszCdl, sizeof(wszCdl) /sizeof(WCHAR)}, - {wszFile, sizeof(wszFile) /sizeof(WCHAR)}, - {wszFtp, sizeof(wszFtp) /sizeof(WCHAR)}, - {wszGopher, sizeof(wszGopher)/sizeof(WCHAR)}, - {wszHttp, sizeof(wszHttp) /sizeof(WCHAR)}, - {wszHttps, sizeof(wszHttps) /sizeof(WCHAR)}, - {wszMk, sizeof(wszMk) /sizeof(WCHAR)} - }; + hres = IUri_GetScheme(uri, &scheme); + if(FAILED(hres)) + return FALSE; - unsigned int i; - int len = lstrlenW(url); - - for(i=0; i < sizeof(protocol_list)/sizeof(protocol_list[0]); i++) { - if(len >= protocol_list[i].len - && !memcmp(url, protocol_list[i].scheme, protocol_list[i].len*sizeof(WCHAR))) - return TRUE; + switch(scheme) { + case URL_SCHEME_FILE: + case URL_SCHEME_FTP: + case URL_SCHEME_GOPHER: + case URL_SCHEME_HTTP: + case URL_SCHEME_HTTPS: + case URL_SCHEME_MK: + return TRUE; } return FALSE; } -static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, IBindCtx *pbc, +static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IBindCtx *pbc, BOOL to_obj, REFIID riid, Binding **binding) { Binding *ret; @@ -1446,7 +1474,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, ret->protocol = binding_ctx->protocol; IInternetProtocol_AddRef(ret->protocol); }else { - hres = create_binding_protocol(url, TRUE, &ret->protocol); + hres = create_binding_protocol(TRUE, &ret->protocol); if(FAILED(hres)) { WARN("Could not get protocol handler\n"); IBinding_Release(BINDING(ret)); @@ -1471,11 +1499,15 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, if(!(ret->bindf & BINDF_ASYNCHRONOUS)) { ret->bindf |= BINDF_NEEDFILE; ret->use_cache_file = TRUE; - }else if(!is_urlmon_protocol(url)) { + }else if(!is_urlmon_protocol(uri)) { ret->bindf |= BINDF_NEEDFILE; } - ret->url = heap_strdupW(url); + hres = IUri_GetDisplayUri(uri, &ret->url); + if(FAILED(hres)) { + IBinding_Release(BINDING(ret)); + return hres; + } if(binding_ctx) { ret->stgmed_buf = binding_ctx->stgmed_buf; @@ -1502,14 +1534,14 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, return S_OK; } -static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, IBindCtx *pbc, +static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, IUri *uri, IBindCtx *pbc, BOOL to_obj, REFIID riid, Binding **ret) { Binding *binding = NULL; HRESULT hres; MSG msg; - hres = Binding_Create(mon, binding_ctx, url, pbc, to_obj, riid, &binding); + hres = Binding_Create(mon, binding_ctx, uri, pbc, to_obj, riid, &binding); if(FAILED(hres)) return hres; @@ -1525,9 +1557,10 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I set_binding_sink(binding->protocol, PROTSINK(binding), BINDINF(binding)); if(binding_ctx->redirect_url) IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url); - report_data(binding, 0, 0, 0); + report_data(binding, BSCF_FIRSTDATANOTIFICATION | (binding_ctx->download_state == END_DOWNLOAD ? BSCF_LASTDATANOTIFICATION : 0), + 0, 0); }else { - hres = IInternetProtocol_Start(binding->protocol, url, PROTSINK(binding), + hres = IInternetProtocolEx_StartEx(binding->protocol, uri, PROTSINK(binding), BINDINF(binding), PI_APARTMENTTHREADED|PI_MIMEVERIFICATION, 0); TRACE("start ret %08x\n", hres); @@ -1553,7 +1586,7 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I return S_OK; } -HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) +HRESULT bind_to_storage(IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv) { Binding *binding = NULL, *binding_ctx; HRESULT hres; @@ -1562,7 +1595,7 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) binding_ctx = get_bctx_binding(pbc); - hres = start_binding(NULL, binding_ctx, url, pbc, FALSE, riid, &binding); + hres = start_binding(NULL, binding_ctx, uri, pbc, FALSE, riid, &binding); if(binding_ctx) IBinding_Release(BINDING(binding_ctx)); if(FAILED(hres)) @@ -1573,8 +1606,10 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) IInternetProtocol_UnlockRequest(binding->protocol); hres = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj, binding->bindf, ppv); - }else { + }else if(binding->bindf & BINDF_ASYNCHRONOUS) { hres = MK_S_ASYNCHRONOUS; + }else { + hres = FAILED(binding->hres) ? binding->hres : S_OK; } IBinding_Release(BINDING(binding)); @@ -1582,14 +1617,14 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) return hres; } -HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) +HRESULT bind_to_object(IMoniker *mon, IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv) { Binding *binding; HRESULT hres; *ppv = NULL; - hres = start_binding(mon, NULL, url, pbc, TRUE, riid, &binding); + hres = start_binding(mon, NULL, uri, pbc, TRUE, riid, &binding); if(FAILED(hres)) return hres; diff --git a/reactos/dll/win32/urlmon/bindprot.c b/reactos/dll/win32/urlmon/bindprot.c index 01443e37856..0549712a048 100644 --- a/reactos/dll/win32/urlmon/bindprot.c +++ b/reactos/dll/win32/urlmon/bindprot.c @@ -33,24 +33,26 @@ typedef struct _task_header_t { } task_header_t; struct BindProtocol { - const IInternetProtocolVtbl *lpIInternetProtocolVtbl; + const IInternetProtocolExVtbl *lpIInternetProtocolExVtbl; 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; + struct { + IInternetProtocol IInternetProtocol_iface; + } default_protocol_handler; + IInternetProtocol *protocol_handler; + LONG priority; BOOL reported_result; @@ -68,7 +70,7 @@ struct BindProtocol { BYTE *buf; DWORD buf_size; LPWSTR mime; - LPWSTR url; + IUri *uri; ProtocolProxy *filter_proxy; }; @@ -76,6 +78,7 @@ struct BindProtocol { #define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) #define HTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpIWinInetHttpInfoVtbl) #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl) +#define PROTOCOLEX(x) ((IInternetProtocolEx*) &(x)->lpIInternetProtocolExVtbl) #define PROTOCOLHANDLER(x) ((IInternetProtocol*) &(x)->lpIInternetProtocolHandlerVtbl) @@ -112,7 +115,7 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM This->continue_call--; } - IInternetProtocol_Release(PROTOCOL(This)); + IInternetProtocolEx_Release(PROTOCOLEX(This)); return 0; } case WM_MK_RELEASE: { @@ -211,7 +214,7 @@ static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc) LeaveCriticalSection(&This->section); if(do_post) { - IInternetProtocol_AddRef(PROTOCOL(This)); + IInternetProtocolEx_AddRef(PROTOCOLEX(This)); PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This); } } @@ -232,7 +235,7 @@ static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_fi if(FAILED(hres)) return hres; - hres = create_protocol_proxy(PROTOCOLHANDLER(This), This->protocol_sink, &filter_proxy); + hres = create_protocol_proxy(&This->default_protocol_handler.IInternetProtocol_iface, This->protocol_sink, &filter_proxy); if(FAILED(hres)) { IInternetProtocolSink_Release(protocol_sink); return hres; @@ -288,22 +291,25 @@ static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified) } } -#define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocol, iface) +#define PROTOCOL_THIS(iface) DEFINE_THIS(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); *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = PROTOCOL(This); + *ppv = PROTOCOLEX(This); }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); - *ppv = PROTOCOL(This); + *ppv = PROTOCOLEX(This); }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); - *ppv = PROTOCOL(This); + *ppv = PROTOCOLEX(This); + }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) { + TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv); + *ppv = PROTOCOLEX(This); }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv); *ppv = BINDINFO(This); @@ -355,7 +361,7 @@ static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocol *iface, REFI return S_OK; } -static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface) +static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface) { BindProtocol *This = PROTOCOL_THIS(iface); LONG ref = InterlockedIncrement(&This->ref); @@ -363,7 +369,7 @@ static ULONG WINAPI BindProtocol_AddRef(IInternetProtocol *iface) return ref; } -static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface) +static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface) { BindProtocol *This = PROTOCOL_THIS(iface); LONG ref = InterlockedDecrement(&This->ref); @@ -377,19 +383,20 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface) 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->uri) + IUri_Release(This->uri); - set_binding_sink(PROTOCOL(This), NULL, NULL); + set_binding_sink(PROTOCOLEX(This), NULL, NULL); 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(); @@ -398,19 +405,29 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface) 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); + 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(PROTOCOLEX(This), 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); @@ -419,15 +436,17 @@ static HRESULT WINAPI BindProtocol_Continue(IInternetProtocol *iface, PROTOCOLDA 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; + + 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); @@ -436,21 +455,21 @@ static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocol *iface, DWORD dwO 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); 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); 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); @@ -462,7 +481,7 @@ static HRESULT WINAPI BindProtocol_Read(IInternetProtocol *iface, void *pv, 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); @@ -470,7 +489,7 @@ static HRESULT WINAPI BindProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER 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); @@ -479,7 +498,7 @@ static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocol *iface, DWORD d 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); @@ -488,82 +507,13 @@ static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface) 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 = PROTOCOL_THIS(iface); IInternetProtocol *protocol = NULL; + IInternetProtocolEx *protocolex; IInternetPriority *priority; IServiceProvider *service_provider; BOOL urlmon_protocol = FALSE; @@ -571,21 +521,22 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz 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); } @@ -593,7 +544,7 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz 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; @@ -625,7 +576,7 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz if(urlmon_protocol) IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info); - set_binding_sink(PROTOCOL(This), pOIProtSink, pOIBindInfo); + set_binding_sink(PROTOCOLEX(This), pOIProtSink, pOIBindInfo); hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority); if(SUCCEEDED(hres)) { @@ -633,12 +584,109 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz 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, PROTSINK(This), BINDINFO(This), 0, NULL); + IInternetProtocolEx_Release(protocolex); + }else { + BSTR display_uri; + + hres = IUri_GetDisplayUri(pUri, &display_uri); + if(FAILED(hres)) + return hres; + + hres = IInternetProtocol_Start(protocol, display_uri, PROTSINK(This), BINDINFO(This), 0, 0); + SysFreeString(display_uri); + } + + return hres; +} + +void set_binding_sink(IInternetProtocolEx *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(IInternetProtocolEx *bind_protocol) +{ + BindProtocol *This = PROTOCOL_THIS(bind_protocol); + + return This->wininet_info; +} + +#undef PROTOCOL_THIS + +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) +{ + ERR("should not be called\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface) +{ + BindProtocol *This = impl_from_IInternetProtocol(iface); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); +} + +static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface) +{ + BindProtocol *This = impl_from_IInternetProtocol(iface); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); +} + +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); @@ -652,14 +700,19 @@ static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCO 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); @@ -673,7 +726,7 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD This->filter_proxy = NULL; } - set_binding_sink(PROTOCOL(This), NULL, NULL); + set_binding_sink(PROTOCOLEX(This), NULL, NULL); if(This->bind_info) { IInternetBindInfo_Release(This->bind_info); @@ -685,14 +738,14 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD 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; } @@ -700,7 +753,7 @@ static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface) 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; @@ -734,14 +787,14 @@ static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv, 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); @@ -750,15 +803,13 @@ static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWOR 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, @@ -781,19 +832,19 @@ static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv) { BindProtocol *This = BINDINFO_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); } static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface) { BindProtocol *This = BINDINFO_THIS(iface); - return IBinding_AddRef(PROTOCOL(This)); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); } static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface) { BindProtocol *This = BINDINFO_THIS(iface); - return IBinding_Release(PROTOCOL(This)); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); } static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, @@ -840,19 +891,19 @@ static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) { BindProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); } static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface) { BindProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); } static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface) { BindProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); } static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority) @@ -892,19 +943,19 @@ static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSin REFIID riid, void **ppv) { BindProtocol *This = PROTSINK_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); } static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface) { BindProtocol *This = PROTSINK_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); } static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface) { BindProtocol *This = PROTSINK_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); } typedef struct { @@ -1069,8 +1120,15 @@ static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE; if(!This->reported_mime) { - hres = FindMimeFromData(NULL, This->url, This->buf, min(This->buf_size, MIME_TEST_SIZE), + 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; @@ -1194,19 +1252,19 @@ static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = { static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv) { BindProtocol *This = INETINFO_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); } static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface) { BindProtocol *This = INETINFO_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); } static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface) { BindProtocol *This = INETINFO_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); } static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption, @@ -1241,19 +1299,19 @@ static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) { BindProtocol *This = SERVPROV_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); } static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface) { BindProtocol *This = SERVPROV_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); } static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface) { BindProtocol *This = SERVPROV_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + return IInternetProtocolEx_Release(PROTOCOLEX(This)); } static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface, @@ -1278,27 +1336,28 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { BPServiceProvider_QueryService }; -HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol) +HRESULT create_binding_protocol(BOOL from_urlmon, IInternetProtocolEx **protocol) { BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol)); - ret->lpIInternetProtocolVtbl = &BindProtocolVtbl; + ret->lpIInternetProtocolExVtbl = &BindProtocolVtbl; ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl; ret->lpInternetPriorityVtbl = &InternetPriorityVtbl; ret->lpServiceProviderVtbl = &ServiceProviderVtbl; ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl; - ret->lpIInternetProtocolHandlerVtbl = &InternetProtocolHandlerVtbl; ret->lpIWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl; + ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl; + 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; InitializeCriticalSection(&ret->section); URLMON_LockModule(); - *protocol = PROTOCOL(ret); + *protocol = PROTOCOLEX(ret); return S_OK; } diff --git a/reactos/dll/win32/urlmon/download.c b/reactos/dll/win32/urlmon/download.c index fee96062ad6..9759e71d18e 100644 --- a/reactos/dll/win32/urlmon/download.c +++ b/reactos/dll/win32/urlmon/download.c @@ -22,8 +22,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { - const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; - const IServiceProviderVtbl *lpServiceProviderVtbl; + IBindStatusCallback IBindStatusCallback_iface; + IServiceProvider IServiceProvider_iface; LONG ref; @@ -32,27 +32,32 @@ typedef struct { LPWSTR cache_file; } DownloadBSC; -#define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl) -#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl) +static inline DownloadBSC *impl_from_IBindStatusCallback(IBindStatusCallback *iface) +{ + return CONTAINING_RECORD(iface, DownloadBSC, IBindStatusCallback_iface); +} -#define STATUSCLB_THIS(iface) DEFINE_THIS(DownloadBSC, BindStatusCallback, iface) +static inline DownloadBSC *impl_from_IServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, DownloadBSC, IServiceProvider_iface); +} static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); - *ppv = STATUSCLB(This); + *ppv = &This->IBindStatusCallback_iface; }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); - *ppv = STATUSCLB(This); + *ppv = &This->IBindStatusCallback_iface; }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv); - *ppv = SERVPROV(This); + *ppv = &This->IServiceProvider_iface; } if(*ppv) { @@ -66,7 +71,7 @@ static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface, static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref = %d\n", This, ref); @@ -76,7 +81,7 @@ static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface) static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref = %d\n", This, ref); @@ -95,7 +100,7 @@ static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface) static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pbind) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); @@ -107,14 +112,14 @@ static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface, static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); FIXME("(%p)->(%p)\n", This, pnPriority); return E_NOTIMPL; } static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD reserved) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); FIXME("(%p)->(%d)\n", This, reserved); return E_NOTIMPL; } @@ -133,7 +138,7 @@ static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); HRESULT hres = S_OK; TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, @@ -167,18 +172,20 @@ static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG u static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); - if(This->cache_file) { - BOOL b; + if(This->file_name) { + if(This->cache_file) { + BOOL b; - b = CopyFileW(This->cache_file, This->file_name, FALSE); - if(!b) - FIXME("CopyFile failed: %u\n", GetLastError()); - }else { - FIXME("No cache file\n"); + b = CopyFileW(This->cache_file, This->file_name, FALSE); + if(!b) + FIXME("CopyFile failed: %u\n", GetLastError()); + }else { + FIXME("No cache file\n"); + } } if(This->callback) @@ -190,7 +197,7 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface, static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); DWORD bindf = 0; TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); @@ -214,7 +221,7 @@ static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface, static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); @@ -224,13 +231,11 @@ static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface, static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk) { - DownloadBSC *This = STATUSCLB_THIS(iface); + DownloadBSC *This = impl_from_IBindStatusCallback(iface); FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); return E_NOTIMPL; } -#undef STATUSCLB_THIS - static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { DownloadBSC_QueryInterface, DownloadBSC_AddRef, @@ -245,31 +250,29 @@ static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { DownloadBSC_OnObjectAvailable }; -#define SERVPROV_THIS(iface) DEFINE_THIS(DownloadBSC, ServiceProvider, iface) - static HRESULT WINAPI DwlServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) { - DownloadBSC *This = SERVPROV_THIS(iface); - return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); + DownloadBSC *This = impl_from_IServiceProvider(iface); + return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv); } static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface) { - DownloadBSC *This = SERVPROV_THIS(iface); - return IBindStatusCallback_AddRef(STATUSCLB(This)); + DownloadBSC *This = impl_from_IServiceProvider(iface); + return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface); } static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface) { - DownloadBSC *This = SERVPROV_THIS(iface); - return IBindStatusCallback_Release(STATUSCLB(This)); + DownloadBSC *This = impl_from_IServiceProvider(iface); + return IBindStatusCallback_Release(&This->IBindStatusCallback_iface); } static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv) { - DownloadBSC *This = SERVPROV_THIS(iface); + DownloadBSC *This = impl_from_IServiceProvider(iface); IServiceProvider *serv_prov; HRESULT hres; @@ -292,8 +295,6 @@ static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface, return E_NOINTERFACE; } -#undef SERVPROV_THIS - static const IServiceProviderVtbl ServiceProviderVtbl = { DwlServiceProvider_QueryInterface, DwlServiceProvider_AddRef, @@ -301,12 +302,12 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { DwlServiceProvider_QueryService }; -static IBindStatusCallback *DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name) +static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name, IBindStatusCallback **ret_callback) { DownloadBSC *ret = heap_alloc(sizeof(*ret)); - ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; - ret->lpServiceProviderVtbl = &ServiceProviderVtbl; + ret->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl; + ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; ret->file_name = heap_strdupW(file_name); ret->cache_file = NULL; @@ -315,7 +316,22 @@ static IBindStatusCallback *DownloadBSC_Create(IBindStatusCallback *callback, LP IBindStatusCallback_AddRef(callback); ret->callback = callback; - return STATUSCLB(ret); + *ret_callback = &ret->IBindStatusCallback_iface; + return S_OK; +} + +HRESULT create_default_callback(IBindStatusCallback **ret) +{ + IBindStatusCallback *callback; + HRESULT hres; + + hres = DownloadBSC_Create(NULL, NULL, &callback); + if(FAILED(hres)) + return hres; + + hres = wrap_callback(callback, ret); + IBindStatusCallback_Release(callback); + return hres; } /*********************************************************************** @@ -348,7 +364,10 @@ HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFi if(pCaller) FIXME("pCaller not supported\n"); - callback = DownloadBSC_Create(lpfnCB, szFileName); + hres = DownloadBSC_Create(lpfnCB, szFileName, &callback); + if(FAILED(hres)) + return hres; + hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx); IBindStatusCallback_Release(callback); if(FAILED(hres)) diff --git a/reactos/dll/win32/urlmon/file.c b/reactos/dll/win32/urlmon/file.c index a1901565336..418b708fe23 100644 --- a/reactos/dll/win32/urlmon/file.c +++ b/reactos/dll/win32/urlmon/file.c @@ -25,8 +25,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { - const IInternetProtocolExVtbl *lpIInternetProtocolExVtbl; - const IInternetPriorityVtbl *lpInternetPriorityVtbl; + IInternetProtocolEx IInternetProtocolEx_iface; + IInternetPriority IInternetPriority_iface; HANDLE file; ULONG size; @@ -35,31 +35,36 @@ typedef struct { LONG ref; } FileProtocol; -#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) -#define PROTOCOLEX(x) ((IInternetProtocolEx*) &(x)->lpIInternetProtocolExVtbl) +static inline FileProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) +{ + return CONTAINING_RECORD(iface, FileProtocol, IInternetProtocolEx_iface); +} -#define PROTOCOL_THIS(iface) DEFINE_THIS(FileProtocol, IInternetProtocolEx, iface) +static inline FileProtocol *impl_from_IInternetPriority(IInternetPriority *iface) +{ + return CONTAINING_RECORD(iface, FileProtocol, IInternetPriority_iface); +} static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = PROTOCOLEX(This); + *ppv = &This->IInternetProtocolEx_iface; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); - *ppv = PROTOCOLEX(This); + *ppv = &This->IInternetProtocolEx_iface; }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); - *ppv = PROTOCOLEX(This); + *ppv = &This->IInternetProtocolEx_iface; }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) { TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv); - *ppv = PROTOCOLEX(This); + *ppv = &This->IInternetProtocolEx_iface; }else if(IsEqualGUID(&IID_IInternetPriority, riid)) { TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); - *ppv = PRIORITY(This); + *ppv = &This->IInternetPriority_iface; } if(*ppv) { @@ -73,7 +78,7 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, RE static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; @@ -81,7 +86,7 @@ static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface) static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -101,7 +106,7 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); IUri *uri; HRESULT hres; @@ -112,8 +117,8 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU if(FAILED(hres)) return hres; - hres = IInternetProtocolEx_StartEx(PROTOCOLEX(This), uri, pOIProtSink, pOIBindInfo, - grfPI, (HANDLE*)dwReserved); + hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink, + pOIBindInfo, grfPI, (HANDLE*)dwReserved); IUri_Release(uri); return hres; @@ -121,7 +126,7 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU static HRESULT WINAPI FileProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)->(%p)\n", This, pProtocolData); return E_NOTIMPL; } @@ -129,14 +134,14 @@ static HRESULT WINAPI FileProtocol_Continue(IInternetProtocolEx *iface, PROTOCOL static HRESULT WINAPI FileProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason, DWORD dwOptions) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); return E_NOTIMPL; } static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); @@ -145,14 +150,14 @@ static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocolEx *iface, DWORD d static HRESULT WINAPI FileProtocol_Suspend(IInternetProtocolEx *iface) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } static HRESULT WINAPI FileProtocol_Resume(IInternetProtocolEx *iface) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } @@ -160,7 +165,7 @@ static HRESULT WINAPI FileProtocol_Resume(IInternetProtocolEx *iface) static HRESULT WINAPI FileProtocol_Read(IInternetProtocolEx *iface, void *pv, ULONG cb, ULONG *pcbRead) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); DWORD read = 0; TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); @@ -183,14 +188,14 @@ static HRESULT WINAPI FileProtocol_Read(IInternetProtocolEx *iface, void *pv, static HRESULT WINAPI FileProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); return E_NOTIMPL; } static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); @@ -199,7 +204,7 @@ static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocolEx *iface, DWORD static HRESULT WINAPI FileProtocol_UnlockRequest(IInternetProtocolEx *iface) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)\n", This); @@ -239,7 +244,7 @@ static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE *dwReserved) { - FileProtocol *This = PROTOCOL_THIS(iface); + FileProtocol *This = impl_from_IInternetProtocolEx(iface); BINDINFO bindinfo; DWORD grfBINDF = 0; DWORD scheme; @@ -314,8 +319,6 @@ static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr return report_result(pOIProtSink, S_OK, 0); } -#undef PROTOCOL_THIS - static const IInternetProtocolExVtbl FileProtocolExVtbl = { FileProtocol_QueryInterface, FileProtocol_AddRef, @@ -333,30 +336,28 @@ static const IInternetProtocolExVtbl FileProtocolExVtbl = { FileProtocol_StartEx }; -#define PRIORITY_THIS(iface) DEFINE_THIS(FileProtocol, InternetPriority, iface) - static HRESULT WINAPI FilePriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) { - FileProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv); + FileProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); } static ULONG WINAPI FilePriority_AddRef(IInternetPriority *iface) { - FileProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocolEx_AddRef(PROTOCOLEX(This)); + FileProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); } static ULONG WINAPI FilePriority_Release(IInternetPriority *iface) { - FileProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocolEx_Release(PROTOCOLEX(This)); + FileProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); } static HRESULT WINAPI FilePriority_SetPriority(IInternetPriority *iface, LONG nPriority) { - FileProtocol *This = PRIORITY_THIS(iface); + FileProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%d)\n", This, nPriority); @@ -366,7 +367,7 @@ static HRESULT WINAPI FilePriority_SetPriority(IInternetPriority *iface, LONG nP static HRESULT WINAPI FilePriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) { - FileProtocol *This = PRIORITY_THIS(iface); + FileProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%p)\n", This, pnPriority); @@ -374,8 +375,6 @@ static HRESULT WINAPI FilePriority_GetPriority(IInternetPriority *iface, LONG *p return S_OK; } -#undef PRIORITY_THIS - static const IInternetPriorityVtbl FilePriorityVtbl = { FilePriority_QueryInterface, FilePriority_AddRef, @@ -394,12 +393,12 @@ HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) ret = heap_alloc(sizeof(FileProtocol)); - ret->lpIInternetProtocolExVtbl = &FileProtocolExVtbl; - ret->lpInternetPriorityVtbl = &FilePriorityVtbl; + ret->IInternetProtocolEx_iface.lpVtbl = &FileProtocolExVtbl; + ret->IInternetPriority_iface.lpVtbl = &FilePriorityVtbl; ret->file = INVALID_HANDLE_VALUE; ret->priority = 0; ret->ref = 1; - *ppobj = PROTOCOLEX(ret); + *ppobj = &ret->IInternetProtocolEx_iface; return S_OK; } diff --git a/reactos/dll/win32/urlmon/format.c b/reactos/dll/win32/urlmon/format.c index bf9dda06034..6967c3b4f39 100644 --- a/reactos/dll/win32/urlmon/format.c +++ b/reactos/dll/win32/urlmon/format.c @@ -24,7 +24,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); static WCHAR wszEnumFORMATETC[] = {'_','E','n','u','m','F','O','R','M','A','T','E','T','C','_',0}; typedef struct { - const IEnumFORMATETCVtbl *lpEnumFORMATETCVtbl; + IEnumFORMATETC IEnumFORMATETC_iface; FORMATETC *fetc; UINT fetc_cnt; @@ -33,13 +33,16 @@ typedef struct { LONG ref; } EnumFORMATETC; -static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmtetc, UINT it); +static inline EnumFORMATETC *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface) +{ + return CONTAINING_RECORD(iface, EnumFORMATETC, IEnumFORMATETC_iface); +} -#define ENUMF_THIS(iface) DEFINE_THIS(EnumFORMATETC, EnumFORMATETC, iface) +static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmtetc, UINT it); static HRESULT WINAPI EnumFORMATETC_QueryInterface(IEnumFORMATETC *iface, REFIID riid, void **ppv) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); @@ -57,7 +60,7 @@ static HRESULT WINAPI EnumFORMATETC_QueryInterface(IEnumFORMATETC *iface, REFIID static ULONG WINAPI EnumFORMATETC_AddRef(IEnumFORMATETC *iface) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; @@ -65,7 +68,7 @@ static ULONG WINAPI EnumFORMATETC_AddRef(IEnumFORMATETC *iface) static ULONG WINAPI EnumFORMATETC_Release(IEnumFORMATETC *iface) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -83,7 +86,7 @@ static ULONG WINAPI EnumFORMATETC_Release(IEnumFORMATETC *iface) static HRESULT WINAPI EnumFORMATETC_Next(IEnumFORMATETC *iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); ULONG cnt; TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); @@ -110,7 +113,7 @@ static HRESULT WINAPI EnumFORMATETC_Next(IEnumFORMATETC *iface, ULONG celt, static HRESULT WINAPI EnumFORMATETC_Skip(IEnumFORMATETC *iface, ULONG celt) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); TRACE("(%p)->(%d)\n", This, celt); @@ -120,7 +123,7 @@ static HRESULT WINAPI EnumFORMATETC_Skip(IEnumFORMATETC *iface, ULONG celt) static HRESULT WINAPI EnumFORMATETC_Reset(IEnumFORMATETC *iface) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); TRACE("(%p)\n", This); @@ -130,7 +133,7 @@ static HRESULT WINAPI EnumFORMATETC_Reset(IEnumFORMATETC *iface) static HRESULT WINAPI EnumFORMATETC_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum) { - EnumFORMATETC *This = ENUMF_THIS(iface); + EnumFORMATETC *This = impl_from_IEnumFORMATETC(iface); TRACE("(%p)->(%p)\n", This, ppenum); @@ -157,7 +160,7 @@ static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmt URLMON_LockModule(); - ret->lpEnumFORMATETCVtbl = &EnumFORMATETCVtbl; + ret->IEnumFORMATETC_iface.lpVtbl = &EnumFORMATETCVtbl; ret->ref = 1; ret->it = it; ret->fetc_cnt = cfmtetc; @@ -165,7 +168,7 @@ static IEnumFORMATETC *EnumFORMATETC_Create(UINT cfmtetc, const FORMATETC *rgfmt ret->fetc = heap_alloc(cfmtetc*sizeof(FORMATETC)); memcpy(ret->fetc, rgfmtetc, cfmtetc*sizeof(FORMATETC)); - return (IEnumFORMATETC*)ret; + return &ret->IEnumFORMATETC_iface; } /********************************************************** diff --git a/reactos/dll/win32/urlmon/ftp.c b/reactos/dll/win32/urlmon/ftp.c index 4fa0924387d..deb611bc901 100644 --- a/reactos/dll/win32/urlmon/ftp.c +++ b/reactos/dll/win32/urlmon/ftp.c @@ -17,6 +17,10 @@ */ #include "urlmon_main.h" + +#define NO_SHLWAPI_REG +#include "shlwapi.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(urlmon); @@ -24,15 +28,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { Protocol base; - const IInternetProtocolVtbl *lpIInternetProtocolVtbl; - const IInternetPriorityVtbl *lpInternetPriorityVtbl; - const IWinInetHttpInfoVtbl *lpWinInetHttpInfoVtbl; + IInternetProtocolEx IInternetProtocolEx_iface; + IInternetPriority IInternetPriority_iface; + IWinInetHttpInfo IWinInetHttpInfo_iface; LONG ref; } FtpProtocol; -#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) -#define INETHTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpWinInetHttpInfoVtbl) +static inline FtpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) +{ + return CONTAINING_RECORD(iface, FtpProtocol, IInternetProtocolEx_iface); +} + +static inline FtpProtocol *impl_from_IInternetPriority(IInternetPriority *iface) +{ + return CONTAINING_RECORD(iface, FtpProtocol, IInternetPriority_iface); +} +static inline FtpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface) + +{ + return CONTAINING_RECORD(iface, FtpProtocol, IWinInetHttpInfo_iface); +} #define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface) @@ -59,6 +75,11 @@ static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request return S_OK; } +static HRESULT FtpProtocol_end_request(Protocol *prot) +{ + return E_NOTIMPL; +} + static HRESULT FtpProtocol_start_downloading(Protocol *prot) { FtpProtocol *This = ASYNCPROTOCOL_THIS(prot); @@ -82,35 +103,37 @@ static void FtpProtocol_close_connection(Protocol *prot) static const ProtocolVtbl AsyncProtocolVtbl = { FtpProtocol_open_request, + FtpProtocol_end_request, FtpProtocol_start_downloading, FtpProtocol_close_connection }; -#define PROTOCOL_THIS(iface) DEFINE_THIS(FtpProtocol, IInternetProtocol, iface) - -static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) +static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *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_IInternetPriority, riid)) { TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); - *ppv = PRIORITY(This); + *ppv = &This->IInternetPriority_iface; }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); - *ppv = INETHTTPINFO(This); + *ppv = &This->IWinInetHttpInfo_iface; }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); - *ppv = INETHTTPINFO(This); + *ppv = &This->IWinInetHttpInfo_iface; } if(*ppv) { @@ -122,17 +145,17 @@ static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocol *iface, REFII return E_NOINTERFACE; } -static ULONG WINAPI FtpProtocol_AddRef(IInternetProtocol *iface) +static ULONG WINAPI FtpProtocol_AddRef(IInternetProtocolEx *iface) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI FtpProtocol_Release(IInternetProtocol *iface) +static ULONG WINAPI FtpProtocol_Release(IInternetProtocolEx *iface) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -147,52 +170,50 @@ static ULONG WINAPI FtpProtocol_Release(IInternetProtocol *iface) return ref; } -static HRESULT WINAPI FtpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, +static HRESULT WINAPI FtpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); IUri *uri; HRESULT hres; - static const WCHAR ftpW[] = {'f','t','p',':'}; - TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); - if(strncmpW(szUrl, ftpW, sizeof(ftpW)/sizeof(WCHAR))) - return MK_E_SYNTAX; - hres = CreateUri(szUrl, 0, 0, &uri); if(FAILED(hres)) return hres; - hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo); + hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink, + pOIBindInfo, grfPI, (HANDLE*)dwReserved); IUri_Release(uri); return hres; } -static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) +static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%p)\n", This, pProtocolData); return protocol_continue(&This->base, pProtocolData); } -static HRESULT WINAPI FtpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, +static HRESULT WINAPI FtpProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason, DWORD dwOptions) { - FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); - return E_NOTIMPL; + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + + TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); + + return protocol_abort(&This->base, hrReason); } -static HRESULT WINAPI FtpProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI FtpProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); @@ -200,59 +221,78 @@ static HRESULT WINAPI FtpProtocol_Terminate(IInternetProtocol *iface, DWORD dwOp return S_OK; } -static HRESULT WINAPI FtpProtocol_Suspend(IInternetProtocol *iface) +static HRESULT WINAPI FtpProtocol_Suspend(IInternetProtocolEx *iface) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } -static HRESULT WINAPI FtpProtocol_Resume(IInternetProtocol *iface) +static HRESULT WINAPI FtpProtocol_Resume(IInternetProtocolEx *iface) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } -static HRESULT WINAPI FtpProtocol_Read(IInternetProtocol *iface, void *pv, +static HRESULT WINAPI FtpProtocol_Read(IInternetProtocolEx *iface, void *pv, ULONG cb, ULONG *pcbRead) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); return protocol_read(&This->base, pv, cb, pcbRead); } -static HRESULT WINAPI FtpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, +static HRESULT WINAPI FtpProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); return E_NOTIMPL; } -static HRESULT WINAPI FtpProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI FtpProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); return protocol_lock_request(&This->base); } -static HRESULT WINAPI FtpProtocol_UnlockRequest(IInternetProtocol *iface) +static HRESULT WINAPI FtpProtocol_UnlockRequest(IInternetProtocolEx *iface) { - FtpProtocol *This = PROTOCOL_THIS(iface); + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)\n", This); return protocol_unlock_request(&This->base); } -#undef PROTOCOL_THIS +static HRESULT WINAPI FtpProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri, + IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, + DWORD grfPI, HANDLE *dwReserved) +{ + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + DWORD scheme = 0; + HRESULT hres; -static const IInternetProtocolVtbl FtpProtocolVtbl = { + TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, + pOIBindInfo, grfPI, dwReserved); + + hres = IUri_GetScheme(pUri, &scheme); + if(FAILED(hres)) + return hres; + if(scheme != URL_SCHEME_FTP) + return MK_E_SYNTAX; + + return protocol_start(&This->base, (IInternetProtocol*)&This->IInternetProtocolEx_iface, pUri, + pOIProtSink, pOIBindInfo); +} + +static const IInternetProtocolExVtbl FtpProtocolVtbl = { FtpProtocol_QueryInterface, FtpProtocol_AddRef, FtpProtocol_Release, @@ -265,32 +305,31 @@ static const IInternetProtocolVtbl FtpProtocolVtbl = { FtpProtocol_Read, FtpProtocol_Seek, FtpProtocol_LockRequest, - FtpProtocol_UnlockRequest + FtpProtocol_UnlockRequest, + FtpProtocol_StartEx }; -#define PRIORITY_THIS(iface) DEFINE_THIS(FtpProtocol, InternetPriority, iface) - static HRESULT WINAPI FtpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) { - FtpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + FtpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); } static ULONG WINAPI FtpPriority_AddRef(IInternetPriority *iface) { - FtpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + FtpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); } static ULONG WINAPI FtpPriority_Release(IInternetPriority *iface) { - FtpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + FtpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); } static HRESULT WINAPI FtpPriority_SetPriority(IInternetPriority *iface, LONG nPriority) { - FtpProtocol *This = PRIORITY_THIS(iface); + FtpProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%d)\n", This, nPriority); @@ -300,7 +339,7 @@ static HRESULT WINAPI FtpPriority_SetPriority(IInternetPriority *iface, LONG nPr static HRESULT WINAPI FtpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) { - FtpProtocol *This = PRIORITY_THIS(iface); + FtpProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%p)\n", This, pnPriority); @@ -308,8 +347,6 @@ static HRESULT WINAPI FtpPriority_GetPriority(IInternetPriority *iface, LONG *pn return S_OK; } -#undef PRIORITY_THIS - static const IInternetPriorityVtbl FtpPriorityVtbl = { FtpPriority_QueryInterface, FtpPriority_AddRef, @@ -318,30 +355,28 @@ static const IInternetPriorityVtbl FtpPriorityVtbl = { FtpPriority_GetPriority }; -#define INETINFO_THIS(iface) DEFINE_THIS(FtpProtocol, WinInetHttpInfo, iface) - static HRESULT WINAPI HttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv) { - FtpProtocol *This = INETINFO_THIS(iface); - return IBinding_QueryInterface(PROTOCOL(This), riid, ppv); + FtpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); } static ULONG WINAPI HttpInfo_AddRef(IWinInetHttpInfo *iface) { - FtpProtocol *This = INETINFO_THIS(iface); - return IBinding_AddRef(PROTOCOL(This)); + FtpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); } static ULONG WINAPI HttpInfo_Release(IWinInetHttpInfo *iface) { - FtpProtocol *This = INETINFO_THIS(iface); - return IBinding_Release(PROTOCOL(This)); + FtpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); } static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer) { - FtpProtocol *This = INETINFO_THIS(iface); + FtpProtocol *This = impl_from_IWinInetHttpInfo(iface); FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); return E_NOTIMPL; } @@ -349,13 +384,11 @@ static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOpti static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) { - FtpProtocol *This = INETINFO_THIS(iface); + FtpProtocol *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 = { HttpInfo_QueryInterface, HttpInfo_AddRef, @@ -375,12 +408,12 @@ HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) ret = heap_alloc_zero(sizeof(FtpProtocol)); ret->base.vtbl = &AsyncProtocolVtbl; - ret->lpIInternetProtocolVtbl = &FtpProtocolVtbl; - ret->lpInternetPriorityVtbl = &FtpPriorityVtbl; - ret->lpWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl; + ret->IInternetProtocolEx_iface.lpVtbl = &FtpProtocolVtbl; + ret->IInternetPriority_iface.lpVtbl = &FtpPriorityVtbl; + ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; ret->ref = 1; - *ppobj = PROTOCOL(ret); - + *ppobj = &ret->IInternetProtocolEx_iface; + return S_OK; } diff --git a/reactos/dll/win32/urlmon/gopher.c b/reactos/dll/win32/urlmon/gopher.c index d8781ce7925..da241e9358e 100644 --- a/reactos/dll/win32/urlmon/gopher.c +++ b/reactos/dll/win32/urlmon/gopher.c @@ -56,6 +56,11 @@ static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD requ return S_OK; } +static HRESULT GopherProtocol_end_request(Protocol *prot) +{ + return E_NOTIMPL; +} + static HRESULT GopherProtocol_start_downloading(Protocol *prot) { return S_OK; @@ -69,6 +74,7 @@ static void GopherProtocol_close_connection(Protocol *prot) static const ProtocolVtbl AsyncProtocolVtbl = { GopherProtocol_open_request, + GopherProtocol_end_request, GopherProtocol_start_downloading, GopherProtocol_close_connection }; @@ -161,8 +167,10 @@ static HRESULT WINAPI GopherProtocol_Abort(IInternetProtocol *iface, HRESULT hrR DWORD dwOptions) { GopherProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); - return E_NOTIMPL; + + TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); + + return protocol_abort(&This->base, hrReason); } static HRESULT WINAPI GopherProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) diff --git a/reactos/dll/win32/urlmon/http.c b/reactos/dll/win32/urlmon/http.c index 722ec501b4d..2aaefb085ec 100644 --- a/reactos/dll/win32/urlmon/http.c +++ b/reactos/dll/win32/urlmon/http.c @@ -20,6 +20,9 @@ #include "urlmon_main.h" #include "wininet.h" +#define NO_SHLWAPI_REG +#include "shlwapi.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(urlmon); @@ -27,9 +30,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { Protocol base; - const IInternetProtocolVtbl *lpIInternetProtocolVtbl; - const IInternetPriorityVtbl *lpInternetPriorityVtbl; - const IWinInetHttpInfoVtbl *lpWinInetHttpInfoVtbl; + IInternetProtocolEx IInternetProtocolEx_iface; + IInternetPriority IInternetPriority_iface; + IWinInetHttpInfo IWinInetHttpInfo_iface; BOOL https; IHttpNegotiate *http_negotiate; @@ -38,8 +41,20 @@ typedef struct { LONG ref; } HttpProtocol; -#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) -#define INETHTTPINFO(x) ((IWinInetHttpInfo*) &(x)->lpWinInetHttpInfoVtbl) +static inline HttpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) +{ + return CONTAINING_RECORD(iface, HttpProtocol, IInternetProtocolEx_iface); +} + +static inline HttpProtocol *impl_from_IInternetPriority(IInternetPriority *iface) +{ + return CONTAINING_RECORD(iface, HttpProtocol, IInternetPriority_iface); +} + +static inline HttpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface) +{ + return CONTAINING_RECORD(iface, HttpProtocol, IWinInetHttpInfo_iface); +} /* Default headers from native */ static const WCHAR wszHeaders[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g', @@ -71,7 +86,8 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques HINTERNET internet_session, IInternetBindInfo *bind_info) { HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); - LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL; + INTERNET_BUFFERSW send_buffer = {sizeof(INTERNET_BUFFERSW)}; + LPWSTR addl_header = NULL, post_cookie = NULL; IServiceProvider *service_provider = NULL; IHttpNegotiate2 *http_negotiate2 = NULL; BSTR url, host, user, pass, path; @@ -162,6 +178,7 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques &IID_IHttpNegotiate, (void **)&This->http_negotiate); if (hres != S_OK) { WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres); + IServiceProvider_Release(service_provider); return hres; } @@ -219,13 +236,30 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques } } + send_buffer.lpcszHeader = This->full_header; + send_buffer.dwHeadersLength = send_buffer.dwHeadersTotal = strlenW(This->full_header); + if(This->base.bind_info.dwBindVerb != BINDVERB_GET) { - /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ - if (This->base.bind_info.stgmedData.tymed != TYMED_HGLOBAL) - WARN("Expected This->base.bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", - This->base.bind_info.stgmedData.tymed); - else - optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal; + switch(This->base.bind_info.stgmedData.tymed) { + case TYMED_HGLOBAL: + /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ + send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal; + send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData; + break; + case TYMED_ISTREAM: { + LARGE_INTEGER offset; + + send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData; + This->base.post_stream = This->base.bind_info.stgmedData.u.pstm; + IStream_AddRef(This->base.post_stream); + + offset.QuadPart = 0; + IStream_Seek(This->base.post_stream, offset, STREAM_SEEK_SET, NULL); + break; + } + default: + FIXME("Unsupported This->base.bind_info.stgmedData.tymed %d\n", This->base.bind_info.stgmedData.tymed); + } } b = TRUE; @@ -233,8 +267,11 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques if(!res) WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError()); - res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header), - optional, optional ? This->base.bind_info.cbstgmedData : 0); + if(This->base.post_stream) + res = HttpSendRequestExW(This->base.request, &send_buffer, NULL, 0, 0); + else + res = HttpSendRequestW(This->base.request, send_buffer.lpcszHeader, send_buffer.dwHeadersLength, + send_buffer.lpvBuffer, send_buffer.dwBufferLength); if(!res && GetLastError() != ERROR_IO_PENDING) { WARN("HttpSendRequest failed: %d\n", GetLastError()); return INET_E_DOWNLOAD_FAILURE; @@ -243,6 +280,19 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques return S_OK; } +static HRESULT HttpProtocol_end_request(Protocol *protocol) +{ + BOOL res; + + res = HttpEndRequestW(protocol->request, NULL, 0, 0); + if(!res && GetLastError() != ERROR_IO_PENDING) { + FIXME("HttpEndRequest failed: %u\n", GetLastError()); + return E_FAIL; + } + + return S_OK; +} + static HRESULT HttpProtocol_start_downloading(Protocol *prot) { HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); @@ -331,35 +381,37 @@ static void HttpProtocol_close_connection(Protocol *prot) static const ProtocolVtbl AsyncProtocolVtbl = { HttpProtocol_open_request, + HttpProtocol_end_request, HttpProtocol_start_downloading, HttpProtocol_close_connection }; -#define PROTOCOL_THIS(iface) DEFINE_THIS(HttpProtocol, IInternetProtocol, iface) - -static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) +static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *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_IInternetPriority, riid)) { TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); - *ppv = PRIORITY(This); + *ppv = &This->IInternetPriority_iface; }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); - *ppv = INETHTTPINFO(This); + *ppv = &This->IWinInetHttpInfo_iface; }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); - *ppv = INETHTTPINFO(This); + *ppv = &This->IWinInetHttpInfo_iface; } if(*ppv) { @@ -371,17 +423,17 @@ static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocol *iface, REFI return E_NOINTERFACE; } -static ULONG WINAPI HttpProtocol_AddRef(IInternetProtocol *iface) +static ULONG WINAPI HttpProtocol_AddRef(IInternetProtocolEx *iface) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI HttpProtocol_Release(IInternetProtocol *iface) +static ULONG WINAPI HttpProtocol_Release(IInternetProtocolEx *iface) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -396,55 +448,50 @@ static ULONG WINAPI HttpProtocol_Release(IInternetProtocol *iface) return ref; } -static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, +static HRESULT WINAPI HttpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); IUri *uri; HRESULT hres; - static const WCHAR httpW[] = {'h','t','t','p',':'}; - static const WCHAR httpsW[] = {'h','t','t','p','s',':'}; - TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); - if(This->https - ? strncmpW(szUrl, httpsW, sizeof(httpsW)/sizeof(WCHAR)) - : strncmpW(szUrl, httpW, sizeof(httpW)/sizeof(WCHAR))) - return MK_E_SYNTAX; - hres = CreateUri(szUrl, 0, 0, &uri); if(FAILED(hres)) return hres; - hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo); + hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink, + pOIBindInfo, grfPI, (HANDLE*)dwReserved); IUri_Release(uri); return hres; } -static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) +static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%p)\n", This, pProtocolData); return protocol_continue(&This->base, pProtocolData); } -static HRESULT WINAPI HttpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, +static HRESULT WINAPI HttpProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason, DWORD dwOptions) { - HttpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); - return E_NOTIMPL; + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + + TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); + + return protocol_abort(&This->base, hrReason); } -static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); @@ -452,59 +499,78 @@ static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocol *iface, DWORD dwO return S_OK; } -static HRESULT WINAPI HttpProtocol_Suspend(IInternetProtocol *iface) +static HRESULT WINAPI HttpProtocol_Suspend(IInternetProtocolEx *iface) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } -static HRESULT WINAPI HttpProtocol_Resume(IInternetProtocol *iface) +static HRESULT WINAPI HttpProtocol_Resume(IInternetProtocolEx *iface) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } -static HRESULT WINAPI HttpProtocol_Read(IInternetProtocol *iface, void *pv, +static HRESULT WINAPI HttpProtocol_Read(IInternetProtocolEx *iface, void *pv, ULONG cb, ULONG *pcbRead) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); return protocol_read(&This->base, pv, cb, pcbRead); } -static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, +static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); return E_NOTIMPL; } -static HRESULT WINAPI HttpProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI HttpProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); return protocol_lock_request(&This->base); } -static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocol *iface) +static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocolEx *iface) { - HttpProtocol *This = PROTOCOL_THIS(iface); + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); TRACE("(%p)\n", This); return protocol_unlock_request(&This->base); } -#undef PROTOCOL_THIS +static HRESULT WINAPI HttpProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri, + IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, + DWORD grfPI, HANDLE *dwReserved) +{ + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + DWORD scheme = 0; + HRESULT hres; -static const IInternetProtocolVtbl HttpProtocolVtbl = { + TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, + pOIBindInfo, grfPI, dwReserved); + + hres = IUri_GetScheme(pUri, &scheme); + if(FAILED(hres)) + return hres; + if(scheme != (This->https ? URL_SCHEME_HTTPS : URL_SCHEME_HTTP)) + return MK_E_SYNTAX; + + return protocol_start(&This->base, (IInternetProtocol*)&This->IInternetProtocolEx_iface, pUri, + pOIProtSink, pOIBindInfo); +} + +static const IInternetProtocolExVtbl HttpProtocolVtbl = { HttpProtocol_QueryInterface, HttpProtocol_AddRef, HttpProtocol_Release, @@ -517,32 +583,31 @@ static const IInternetProtocolVtbl HttpProtocolVtbl = { HttpProtocol_Read, HttpProtocol_Seek, HttpProtocol_LockRequest, - HttpProtocol_UnlockRequest + HttpProtocol_UnlockRequest, + HttpProtocol_StartEx }; -#define PRIORITY_THIS(iface) DEFINE_THIS(HttpProtocol, InternetPriority, iface) - static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) { - HttpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); + HttpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); } static ULONG WINAPI HttpPriority_AddRef(IInternetPriority *iface) { - HttpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_AddRef(PROTOCOL(This)); + HttpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); } static ULONG WINAPI HttpPriority_Release(IInternetPriority *iface) { - HttpProtocol *This = PRIORITY_THIS(iface); - return IInternetProtocol_Release(PROTOCOL(This)); + HttpProtocol *This = impl_from_IInternetPriority(iface); + return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); } static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nPriority) { - HttpProtocol *This = PRIORITY_THIS(iface); + HttpProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%d)\n", This, nPriority); @@ -552,7 +617,7 @@ static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nP static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) { - HttpProtocol *This = PRIORITY_THIS(iface); + HttpProtocol *This = impl_from_IInternetPriority(iface); TRACE("(%p)->(%p)\n", This, pnPriority); @@ -560,8 +625,6 @@ static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *p return S_OK; } -#undef PRIORITY_THIS - static const IInternetPriorityVtbl HttpPriorityVtbl = { HttpPriority_QueryInterface, HttpPriority_AddRef, @@ -570,30 +633,28 @@ static const IInternetPriorityVtbl HttpPriorityVtbl = { HttpPriority_GetPriority }; -#define INETINFO_THIS(iface) DEFINE_THIS(HttpProtocol, WinInetHttpInfo, iface) - static HRESULT WINAPI HttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv) { - HttpProtocol *This = INETINFO_THIS(iface); - return IBinding_QueryInterface(PROTOCOL(This), riid, ppv); + HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); } static ULONG WINAPI HttpInfo_AddRef(IWinInetHttpInfo *iface) { - HttpProtocol *This = INETINFO_THIS(iface); - return IBinding_AddRef(PROTOCOL(This)); + HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); } static ULONG WINAPI HttpInfo_Release(IWinInetHttpInfo *iface) { - HttpProtocol *This = INETINFO_THIS(iface); - return IBinding_Release(PROTOCOL(This)); + HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); + return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface); } static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer) { - HttpProtocol *This = INETINFO_THIS(iface); + HttpProtocol *This = impl_from_IWinInetHttpInfo(iface); FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); return E_NOTIMPL; } @@ -601,13 +662,11 @@ static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOpti static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) { - HttpProtocol *This = INETINFO_THIS(iface); + HttpProtocol *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 = { HttpInfo_QueryInterface, HttpInfo_AddRef, @@ -625,15 +684,15 @@ static HRESULT create_http_protocol(BOOL https, void **ppobj) return E_OUTOFMEMORY; ret->base.vtbl = &AsyncProtocolVtbl; - ret->lpIInternetProtocolVtbl = &HttpProtocolVtbl; - ret->lpInternetPriorityVtbl = &HttpPriorityVtbl; - ret->lpWinInetHttpInfoVtbl = &WinInetHttpInfoVtbl; + ret->IInternetProtocolEx_iface.lpVtbl = &HttpProtocolVtbl; + ret->IInternetPriority_iface.lpVtbl = &HttpPriorityVtbl; + ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; ret->https = https; ret->ref = 1; - *ppobj = PROTOCOL(ret); - + *ppobj = &ret->IInternetProtocolEx_iface; + URLMON_LockModule(); return S_OK; } diff --git a/reactos/dll/win32/urlmon/protocol.c b/reactos/dll/win32/urlmon/protocol.c index b423c67354f..669343b211f 100644 --- a/reactos/dll/win32/urlmon/protocol.c +++ b/reactos/dll/win32/urlmon/protocol.c @@ -104,6 +104,8 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar) { PROTOCOLDATA data; + TRACE("(%p)->(%p)\n", protocol, ar); + if(!ar->dwResult) { WARN("request failed: %d\n", ar->dwError); return; @@ -191,6 +193,42 @@ static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR contex } } +static HRESULT write_post_stream(Protocol *protocol) +{ + BYTE buf[0x20000]; + DWORD written; + ULONG size; + BOOL res; + HRESULT hres; + + protocol->flags &= ~FLAG_REQUEST_COMPLETE; + + while(1) { + size = 0; + hres = IStream_Read(protocol->post_stream, buf, sizeof(buf), &size); + if(FAILED(hres) || !size) + break; + res = InternetWriteFile(protocol->request, buf, size, &written); + if(!res) { + FIXME("InternetWriteFile failed: %u\n", GetLastError()); + hres = E_FAIL; + break; + } + } + + if(SUCCEEDED(hres)) { + IStream_Release(protocol->post_stream); + protocol->post_stream = NULL; + + hres = protocol->vtbl->end_request(protocol); + } + + if(FAILED(hres)) + return report_result(protocol, hres); + + return S_OK; +} + static HINTERNET create_internet_session(IInternetBindInfo *bind_info) { LPWSTR global_user_agent = NULL; @@ -293,6 +331,9 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data) return S_OK; } + if(protocol->post_stream) + return write_post_stream(protocol); + if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) { hres = protocol->vtbl->start_downloading(protocol); if(FAILED(hres)) { @@ -428,6 +469,18 @@ HRESULT protocol_unlock_request(Protocol *protocol) return S_OK; } +HRESULT protocol_abort(Protocol *protocol, HRESULT reason) +{ + if(!protocol->protocol_sink) + return S_OK; + + if(protocol->flags & FLAG_RESULT_REPORTED) + return INET_E_RESULT_DISPATCHED; + + report_result(protocol, reason); + return S_OK; +} + void protocol_close_connection(Protocol *protocol) { protocol->vtbl->close_connection(protocol); @@ -438,5 +491,10 @@ void protocol_close_connection(Protocol *protocol) if(protocol->connection) InternetCloseHandle(protocol->connection); + if(protocol->post_stream) { + IStream_Release(protocol->post_stream); + protocol->post_stream = NULL; + } + protocol->flags = 0; } diff --git a/reactos/dll/win32/urlmon/sec_mgr.c b/reactos/dll/win32/urlmon/sec_mgr.c index f984aa4e907..6b12a9aabaa 100644 --- a/reactos/dll/win32/urlmon/sec_mgr.c +++ b/reactos/dll/win32/urlmon/sec_mgr.c @@ -295,7 +295,7 @@ static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD s * */ typedef struct { - const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl; + IInternetSecurityManager IInternetSecurityManager_iface; LONG ref; @@ -303,11 +303,14 @@ typedef struct { IInternetSecurityManager *custom_manager; } SecManagerImpl; -#define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface) +static inline SecManagerImpl *impl_from_IInternetSecurityManager(IInternetSecurityManager *iface) +{ + return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManager_iface); +} static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject); @@ -337,7 +340,7 @@ static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* if static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); ULONG refCount = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%u\n", This, refCount); @@ -347,7 +350,7 @@ static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface) static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); ULONG refCount = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%u\n", This, refCount); @@ -370,7 +373,7 @@ static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface) static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface, IInternetSecurityMgrSite *pSite) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); TRACE("(%p)->(%p)\n", This, pSite); @@ -405,7 +408,7 @@ static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *i static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface, IInternetSecurityMgrSite **ppSite) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); TRACE("(%p)->(%p)\n", This, ppSite); @@ -423,7 +426,7 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); HRESULT hres; TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags); @@ -449,7 +452,7 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); LPWSTR url, ptr, ptr2; DWORD zone, len; HRESULT hres; @@ -529,7 +532,7 @@ static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager * BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); DWORD zone, policy; HRESULT hres; @@ -584,7 +587,7 @@ static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager BYTE *pContext, DWORD cbContext, DWORD dwReserved) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); HRESULT hres; TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey), @@ -604,7 +607,7 @@ static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface, DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); HRESULT hres; TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags); @@ -623,7 +626,7 @@ static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *if static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface, DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags) { - SecManagerImpl *This = SECMGR_THIS(iface); + SecManagerImpl *This = impl_from_IInternetSecurityManager(iface); HRESULT hres; TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags); @@ -662,7 +665,7 @@ HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) This = heap_alloc(sizeof(*This)); /* Initialize the virtual function table. */ - This->lpInternetSecurityManagerVtbl = &VT_SecManagerImpl; + This->IInternetSecurityManager_iface.lpVtbl = &VT_SecManagerImpl; This->ref = 1; This->mgrsite = NULL; @@ -680,12 +683,17 @@ HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) * */ typedef struct { - const IInternetZoneManagerEx2Vtbl* lpVtbl; + IInternetZoneManagerEx2 IInternetZoneManagerEx2_iface; LONG ref; LPDWORD *zonemaps; DWORD zonemap_count; } ZoneMgrImpl; +static inline ZoneMgrImpl *impl_from_IInternetZoneManagerEx2(IInternetZoneManagerEx2 *iface) +{ + return CONTAINING_RECORD(iface, ZoneMgrImpl, IInternetZoneManagerEx2_iface); +} + /*********************************************************************** * build_zonemap_from_reg [internal] @@ -750,7 +758,7 @@ cleanup: */ static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, REFIID riid, void** ppvObject) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject); @@ -783,7 +791,7 @@ static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, */ static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); ULONG refCount = InterlockedIncrement(&This->ref); TRACE("(%p)->(ref before=%u)\n",This, refCount - 1); @@ -796,7 +804,7 @@ static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface) */ static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManagerEx2* iface) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); ULONG refCount = InterlockedDecrement(&This->ref); TRACE("(%p)->(ref before=%u)\n",This, refCount + 1); @@ -818,7 +826,7 @@ static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManagerEx2* ifa DWORD dwZone, ZONEATTRIBUTES* pZoneAttributes) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); HRESULT hr; HKEY hcu; HKEY hklm = NULL; @@ -957,7 +965,7 @@ static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManagerEx2* DWORD* pdwCount, DWORD dwFlags) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); LPDWORD * new_maps; LPDWORD data; DWORD i; @@ -1012,7 +1020,7 @@ static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface, DWORD dwIndex, DWORD* pdwZone) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); LPDWORD data; TRACE("(%p)->(0x%08x, %d, %p)\n", This, dwEnum, dwIndex, pdwZone); @@ -1035,7 +1043,7 @@ static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface, static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManagerEx2* iface, DWORD dwEnum) { - ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface); LPDWORD data; TRACE("(%p)->(0x%08x)\n", This, dwEnum); @@ -1202,7 +1210,7 @@ HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) ZoneMgrImpl* ret = heap_alloc_zero(sizeof(ZoneMgrImpl)); TRACE("(%p %p)\n", pUnkOuter, ppobj); - ret->lpVtbl = &ZoneMgrImplVtbl; + ret->IInternetZoneManagerEx2_iface.lpVtbl = &ZoneMgrImplVtbl; ret->ref = 1; *ppobj = (IInternetZoneManagerEx*)ret; diff --git a/reactos/dll/win32/urlmon/session.c b/reactos/dll/win32/urlmon/session.c index 163ee081c69..72a3e2a3c56 100644 --- a/reactos/dll/win32/urlmon/session.c +++ b/reactos/dll/win32/urlmon/session.c @@ -92,7 +92,7 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid, heap_free(wszKey); if(res != ERROR_SUCCESS) { TRACE("Could not open protocol handler key\n"); - return E_FAIL; + return MK_E_SYNTAX; } size = sizeof(str_clsid); @@ -100,7 +100,7 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid, RegCloseKey(hkey); if(res != ERROR_SUCCESS || type != REG_SZ) { WARN("Could not get protocol CLSID res=%d\n", res); - return E_FAIL; + return MK_E_SYNTAX; } hres = CLSIDFromString(str_clsid, &clsid); @@ -115,7 +115,8 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid, if(!ret) return S_OK; - return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret); + hres = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret); + return SUCCEEDED(hres) ? S_OK : MK_E_SYNTAX; } static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL urlmon_protocol) @@ -235,23 +236,22 @@ IInternetProtocolInfo *get_protocol_info(LPCWSTR url) return ret; } -HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, BOOL *urlmon_protocol, IClassFactory **ret) +HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, BOOL *urlmon_protocol, IClassFactory **ret) { name_space *ns; - WCHAR schema[64]; - DWORD schema_len; + BSTR scheme; HRESULT hres; *ret = NULL; - hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), - &schema_len, 0); - if(FAILED(hres) || !schema_len) - return schema_len ? hres : E_FAIL; + /* FIXME: Avoid GetSchemeName call for known schemes */ + hres = IUri_GetSchemeName(uri, &scheme); + if(FAILED(hres)) + return hres; EnterCriticalSection(&session_cs); - ns = find_name_space(schema); + ns = find_name_space(scheme); if(ns) { *ret = ns->cf; IClassFactory_AddRef(*ret); @@ -263,12 +263,16 @@ HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, BOOL *urlmon_protocol, I LeaveCriticalSection(&session_cs); - if(*ret) - return S_OK; + if(*ret) { + hres = S_OK; + }else { + if(urlmon_protocol) + *urlmon_protocol = FALSE; + hres = get_protocol_cf(scheme, SysStringLen(scheme), clsid, ret); + } - if(urlmon_protocol) - *urlmon_protocol = FALSE; - return get_protocol_cf(schema, schema_len, clsid, ret); + SysFreeString(scheme); + return hres; } IInternetProtocol *get_mime_filter(LPCWSTR mime) @@ -420,13 +424,21 @@ static HRESULT WINAPI InternetSession_CreateBinding(IInternetSession *iface, LPBC pBC, LPCWSTR szUrl, IUnknown *pUnkOuter, IUnknown **ppUnk, IInternetProtocol **ppOInetProt, DWORD dwOption) { + IInternetProtocolEx *protocol; + HRESULT hres; + TRACE("(%p %s %p %p %p %08x)\n", pBC, debugstr_w(szUrl), pUnkOuter, ppUnk, ppOInetProt, dwOption); if(pBC || pUnkOuter || ppUnk || dwOption) FIXME("Unsupported arguments\n"); - return create_binding_protocol(szUrl, FALSE, ppOInetProt); + hres = create_binding_protocol(FALSE, &protocol); + if(FAILED(hres)) + return hres; + + *ppOInetProt = (IInternetProtocol*)protocol; + return S_OK; } static HRESULT WINAPI InternetSession_SetSessionOption(IInternetSession *iface, diff --git a/reactos/dll/win32/urlmon/umon.c b/reactos/dll/win32/urlmon/umon.c index fea7b21c471..fbb00a44baa 100644 --- a/reactos/dll/win32/urlmon/umon.c +++ b/reactos/dll/win32/urlmon/umon.c @@ -200,6 +200,7 @@ static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IM { URLMoniker *This = MONIKER_THIS(iface); IRunningObjectTable *obj_tbl; + IUri *uri; HRESULT hres; TRACE("(%p)->(%p,%p,%s,%p): stub\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv); @@ -210,20 +211,36 @@ static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IM IRunningObjectTable_Release(obj_tbl); } - return bind_to_object(iface, This->URLName, pbc, riid, ppv); + hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri); + if(FAILED(hres)) + return hres; + + hres = bind_to_object(iface, uri, pbc, riid, ppv); + + IUri_Release(uri); + return hres; } static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, void **ppvObject) { URLMoniker *This = MONIKER_THIS(iface); + IUri *uri; + HRESULT hres; TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject); if(pmkToLeft) FIXME("Unsupported pmkToLeft\n"); - return bind_to_storage(This->URLName, pbc, riid, ppvObject); + hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri); + if(FAILED(hres)) + return hres; + + hres = bind_to_storage(uri, pbc, riid, ppvObject); + + IUri_Release(uri); + return hres; } static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc, diff --git a/reactos/dll/win32/urlmon/uri.c b/reactos/dll/win32/urlmon/uri.c index 2aee38a46ba..681327f6cb8 100644 --- a/reactos/dll/win32/urlmon/uri.c +++ b/reactos/dll/win32/urlmon/uri.c @@ -23,9 +23,14 @@ #define NO_SHLWAPI_REG #include "shlwapi.h" +#include "strsafe.h" + #define UINT_MAX 0xffffffff #define USHORT_MAX 0xffff +#define URI_DISPLAY_NO_ABSOLUTE_URI 0x1 +#define URI_DISPLAY_NO_DEFAULT_PORT_AUTH 0x2 + #define ALLOW_NULL_TERM_SCHEME 0x01 #define ALLOW_NULL_TERM_USER_NAME 0x02 #define ALLOW_NULL_TERM_PASSWORD 0x04 @@ -33,12 +38,19 @@ #define SKIP_IP_FUTURE_CHECK 0x10 #define IGNORE_PORT_DELIMITER 0x20 +#define RAW_URI_FORCE_PORT_DISP 0x1 +#define RAW_URI_CONVERT_TO_DOS_PATH 0x2 + +#define COMBINE_URI_FORCE_FLAG_USE 0x1 + WINE_DEFAULT_DEBUG_CHANNEL(urlmon); static const IID IID_IUriObj = {0x4b364760,0x9f51,0x11df,{0x98,0x1c,0x08,0x00,0x20,0x0c,0x9a,0x66}}; typedef struct { - const IUriVtbl *lpIUriVtbl; + IUri IUri_iface; + IUriBuilderFactory IUriBuilderFactory_iface; + LONG ref; BSTR raw_uri; @@ -47,7 +59,7 @@ typedef struct { WCHAR *canon_uri; DWORD canon_size; DWORD canon_len; - BOOL display_absolute; + BOOL display_modifiers; DWORD create_flags; INT scheme_start; @@ -62,7 +74,8 @@ typedef struct { DWORD host_len; Uri_HOST_TYPE host_type; - USHORT port; + INT port_offset; + DWORD port; BOOL has_port; INT authority_start; @@ -82,7 +95,7 @@ typedef struct { } Uri; typedef struct { - const IUriBuilderVtbl *lpIUriBuilderVtbl; + IUriBuilder IUriBuilder_iface; LONG ref; Uri *uri; @@ -337,6 +350,17 @@ static inline BOOL is_path_delim(WCHAR val) { return (!val || val == '#' || val == '?'); } +static BOOL is_default_port(URL_SCHEME scheme, DWORD port) { + DWORD i; + + for(i = 0; i < sizeof(default_ports)/sizeof(default_ports[0]); ++i) { + if(default_ports[i].scheme == scheme && default_ports[i].port) + return TRUE; + } + + return FALSE; +} + /* List of schemes types Windows seems to expect to be hierarchical. */ static inline BOOL is_hierarchical_scheme(URL_SCHEME type) { return(type == URL_SCHEME_HTTP || type == URL_SCHEME_FTP || @@ -933,6 +957,19 @@ static DWORD ui2ipv4(WCHAR *dest, UINT address) { return ret; } +static DWORD ui2str(WCHAR *dest, UINT value) { + static const WCHAR formatW[] = {'%','u',0}; + DWORD ret = 0; + + if(!dest) { + WCHAR tmp[11]; + ret = sprintfW(tmp, formatW, value); + } else + ret = sprintfW(dest, formatW, value); + + return ret; +} + /* Converts an h16 component (from an IPv6 address) into it's * numerical value. * @@ -1316,19 +1353,13 @@ static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags, DWO } static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) { - const WCHAR *start = *ptr; - - if(**ptr != ':') - return TRUE; - - ++(*ptr); data->password = *ptr; while(**ptr != '@') { if(**ptr == '%') { if(!check_pct_encoded(ptr)) { if(data->scheme_type != URL_SCHEME_UNKNOWN) { - *ptr = start; + *ptr = data->password; data->password = NULL; return FALSE; } @@ -1337,7 +1368,7 @@ static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags, DWO } else if(extras & ALLOW_NULL_TERM_PASSWORD && !**ptr) break; else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) { - *ptr = start; + *ptr = data->password; data->password = NULL; return FALSE; } @@ -1376,12 +1407,15 @@ static void parse_userinfo(const WCHAR **ptr, parse_data *data, DWORD flags) { return; } - if(!parse_password(ptr, data, flags, 0)) { - *ptr = start; - data->username = NULL; - data->username_len = 0; - TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags); - return; + if(**ptr == ':') { + ++(*ptr); + if(!parse_password(ptr, data, flags, 0)) { + *ptr = start; + data->username = NULL; + data->username_len = 0; + TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags); + return; + } } if(**ptr != '@') { @@ -1524,8 +1558,11 @@ static BOOL parse_ipv4address(const WCHAR **ptr, parse_data *data, DWORD flags) static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) { const BOOL has_start_bracket = **ptr == '['; const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN; + const BOOL is_res = data->scheme_type == URL_SCHEME_RES; BOOL inside_brackets = has_start_bracket; - BOOL ignore_col = extras & IGNORE_PORT_DELIMITER; + + /* res URIs don't have ports. */ + BOOL ignore_col = (extras & IGNORE_PORT_DELIMITER) || is_res; /* We have to be careful with file schemes. */ if(data->scheme_type == URL_SCHEME_FILE) { @@ -1547,7 +1584,11 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWO data->host = *ptr; - while(!is_auth_delim(**ptr, known_scheme)) { + /* For res URIs, everything before the first '/' is + * considered the host. + */ + while((!is_res && !is_auth_delim(**ptr, known_scheme)) || + (is_res && **ptr && **ptr != '/')) { if(**ptr == ':' && !ignore_col) { /* We can ignore ':' if were inside brackets.*/ if(!inside_brackets) { @@ -1571,7 +1612,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWO break; } } - } else if(**ptr == '%' && known_scheme) { + } else if(**ptr == '%' && (known_scheme && !is_res)) { /* Has to be a legit % encoded value. */ if(!check_pct_encoded(ptr)) { *ptr = data->host; @@ -1579,6 +1620,10 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWO return FALSE; } else continue; + } else if(is_res && is_forbidden_dos_path_char(**ptr)) { + *ptr = data->host; + data->host = NULL; + return FALSE; } else if(**ptr == ']') inside_brackets = FALSE; else if(**ptr == '[') @@ -1603,7 +1648,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWO data->host_len = *ptr - data->host; /* If the host is empty, then it's an unknown host type. */ - if(data->host_len == 0) + if(data->host_len == 0 || is_res) data->host_type = Uri_HOST_UNKNOWN; else data->host_type = Uri_HOST_DNS; @@ -2338,6 +2383,9 @@ static BOOL canonicalize_userinfo(const parse_data *data, Uri *uri, DWORD flags, * it isn't an unknown scheme type. * * 4) If it's a file scheme and the host is "localhost" it's removed. + * + * 5) If it's a file scheme and Uri_CREATE_FILE_USE_DOS_PATH is set, + * then the UNC path characters are added before the host name. */ static BOOL canonicalize_reg_name(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) { @@ -2346,8 +2394,6 @@ static BOOL canonicalize_reg_name(const parse_data *data, Uri *uri, const WCHAR *ptr; const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN; - uri->host_start = uri->canon_len; - if(data->scheme_type == URL_SCHEME_FILE && data->host_len == lstrlenW(localhostW)) { if(!StrCmpNIW(data->host, localhostW, data->host_len)) { @@ -2358,6 +2404,17 @@ static BOOL canonicalize_reg_name(const parse_data *data, Uri *uri, } } + if(data->scheme_type == URL_SCHEME_FILE && flags & Uri_CREATE_FILE_USE_DOS_PATH) { + if(!computeOnly) { + uri->canon_uri[uri->canon_len] = '\\'; + uri->canon_uri[uri->canon_len+1] = '\\'; + } + uri->canon_len += 2; + uri->authority_start = uri->canon_len; + } + + uri->host_start = uri->canon_len; + for(ptr = data->host; ptr < data->host+data->host_len; ++ptr) { if(*ptr == '%' && known_scheme) { WCHAR val = decode_pct_val(ptr); @@ -2751,7 +2808,7 @@ static BOOL canonicalize_port(const parse_data *data, Uri *uri, DWORD flags, BOO USHORT default_port = 0; DWORD i; - uri->has_port = FALSE; + uri->port_offset = -1; /* Check if the scheme has a default port. */ for(i = 0; i < sizeof(default_ports)/sizeof(default_ports[0]); ++i) { @@ -2762,8 +2819,7 @@ static BOOL canonicalize_port(const parse_data *data, Uri *uri, DWORD flags, BOO } } - if(data->port || has_default_port) - uri->has_port = TRUE; + uri->has_port = data->has_port || has_default_port; /* Possible cases: * 1) Has a port which is the default port. @@ -2771,38 +2827,44 @@ static BOOL canonicalize_port(const parse_data *data, Uri *uri, DWORD flags, BOO * 3) Doesn't have a port, but, scheme has a default port. * 4) No port. */ - if(has_default_port && data->port && data->port_value == default_port) { + if(has_default_port && data->has_port && data->port_value == default_port) { /* If it's the default port and this flag isn't set, don't do anything. */ if(flags & Uri_CREATE_NO_CANONICALIZE) { - /* Copy the original port over. */ - if(!computeOnly) { + uri->port_offset = uri->canon_len-uri->authority_start; + if(!computeOnly) uri->canon_uri[uri->canon_len] = ':'; - memcpy(uri->canon_uri+uri->canon_len+1, data->port, data->port_len*sizeof(WCHAR)); + ++uri->canon_len; + + if(data->port) { + /* Copy the original port over. */ + if(!computeOnly) + memcpy(uri->canon_uri+uri->canon_len, data->port, data->port_len*sizeof(WCHAR)); + uri->canon_len += data->port_len; + } else { + if(!computeOnly) + uri->canon_len += ui2str(uri->canon_uri+uri->canon_len, data->port_value); + else + uri->canon_len += ui2str(NULL, data->port_value); } - uri->canon_len += data->port_len+1; } uri->port = default_port; - } else if(data->port) { + } else if(data->has_port) { + uri->port_offset = uri->canon_len-uri->authority_start; if(!computeOnly) uri->canon_uri[uri->canon_len] = ':'; ++uri->canon_len; - if(flags & Uri_CREATE_NO_CANONICALIZE) { + if(flags & Uri_CREATE_NO_CANONICALIZE && data->port) { /* Copy the original over without changes. */ if(!computeOnly) memcpy(uri->canon_uri+uri->canon_len, data->port, data->port_len*sizeof(WCHAR)); uri->canon_len += data->port_len; } else { - const WCHAR formatW[] = {'%','u',0}; - INT len = 0; if(!computeOnly) - len = sprintfW(uri->canon_uri+uri->canon_len, formatW, data->port_value); - else { - WCHAR tmp[6]; - len = sprintfW(tmp, formatW, data->port_value); - } - uri->canon_len += len; + uri->canon_len += ui2str(uri->canon_uri+uri->canon_len, data->port_value); + else + uri->canon_len += ui2str(NULL, data->port_value); } uri->port = data->port_value; @@ -2826,7 +2888,7 @@ static BOOL canonicalize_authority(const parse_data *data, Uri *uri, DWORD flags if(!canonicalize_port(data, uri, flags, computeOnly)) return FALSE; - if(uri->host_start != -1) + if(uri->host_start != -1 || (data->is_relative && (data->password || data->username))) uri->authority_len = uri->canon_len - uri->authority_start; else uri->authority_start = -1; @@ -2859,6 +2921,7 @@ static BOOL canonicalize_authority(const parse_data *data, Uri *uri, DWORD flags * NOTES: * file://c:/test%20test -> file:///c:/test%2520test * file://c:/test%3Etest -> file:///c:/test%253Etest + * if Uri_CREATE_FILE_USE_DOS_PATH is not set: * file:///c:/test%20test -> file:///c:/test%20test * file:///c:/test%test -> file:///c:/test%25test */ @@ -2867,6 +2930,7 @@ static BOOL canonicalize_path_hierarchical(const parse_data *data, Uri *uri, const WCHAR *ptr; const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN; const BOOL is_file = data->scheme_type == URL_SCHEME_FILE; + const BOOL is_res = data->scheme_type == URL_SCHEME_RES; BOOL escape_pct = FALSE; @@ -2907,13 +2971,22 @@ static BOOL canonicalize_path_hierarchical(const parse_data *data, Uri *uri, } } + if(!is_file && *(data->path) && *(data->path) != '/') { + /* Prepend a '/' to the path if it doesn't have one. */ + if(!computeOnly) + uri->canon_uri[uri->canon_len] = '/'; + ++uri->canon_len; + } + for(; ptr < data->path+data->path_len; ++ptr) { - if(*ptr == '%') { + BOOL do_default_action = TRUE; + + if(*ptr == '%' && !is_res) { const WCHAR *tmp = ptr; WCHAR val; /* Check if the % represents a valid encoded char, or if it needs encoded. */ - BOOL force_encode = !check_pct_encoded(&tmp) && is_file; + BOOL force_encode = !check_pct_encoded(&tmp) && is_file && !(flags&Uri_CREATE_FILE_USE_DOS_PATH); val = decode_pct_val(ptr); if(force_encode || escape_pct) { @@ -2921,49 +2994,43 @@ static BOOL canonicalize_path_hierarchical(const parse_data *data, Uri *uri, if(!computeOnly) pct_encode_val(*ptr, uri->canon_uri+uri->canon_len); uri->canon_len += 3; + do_default_action = FALSE; } else if((is_unreserved(val) && known_scheme) || - (is_file && (is_unreserved(val) || is_reserved(val)))) { + (is_file && (is_unreserved(val) || is_reserved(val) || + (val && flags&Uri_CREATE_FILE_USE_DOS_PATH && !is_forbidden_dos_path_char(val))))) { if(!computeOnly) uri->canon_uri[uri->canon_len] = val; ++uri->canon_len; ptr += 2; continue; - } else { - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; } } else if(*ptr == '/' && is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) { /* Convert the '/' back to a '\\'. */ if(!computeOnly) uri->canon_uri[uri->canon_len] = '\\'; ++uri->canon_len; + do_default_action = FALSE; } else if(*ptr == '\\' && known_scheme) { - if(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) { - /* Don't convert the '\\' to a '/'. */ - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; - } else { + if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH))) { + /* Convert '\\' into a '/'. */ if(!computeOnly) uri->canon_uri[uri->canon_len] = '/'; ++uri->canon_len; + do_default_action = FALSE; } - } else if(known_scheme && !is_unreserved(*ptr) && !is_reserved(*ptr) && + } else if(known_scheme && !is_res && !is_unreserved(*ptr) && !is_reserved(*ptr) && (!(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS) || is_file)) { - if(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) { - /* Don't escape the character. */ - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; - } else { + if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH))) { /* Escape the forbidden character. */ if(!computeOnly) pct_encode_val(*ptr, uri->canon_uri+uri->canon_len); uri->canon_len += 3; + do_default_action = FALSE; } - } else { + } + + if(do_default_action) { if(!computeOnly) uri->canon_uri[uri->canon_len] = *ptr; ++uri->canon_len; @@ -3041,6 +3108,8 @@ static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD fla } for(ptr = data->path; ptr < data->path+data->path_len; ++ptr) { + BOOL do_default_action = TRUE; + if(*ptr == '%' && known_scheme) { WCHAR val = decode_pct_val(ptr); @@ -3051,47 +3120,31 @@ static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD fla ptr += 2; continue; - } else { - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; } } else if(*ptr == '/' && is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) { if(!computeOnly) uri->canon_uri[uri->canon_len] = '\\'; ++uri->canon_len; - } else if(*ptr == '\\' && is_file) { - if(!(flags & Uri_CREATE_FILE_USE_DOS_PATH)) { + do_default_action = FALSE; + } else if(*ptr == '\\') { + if(is_file && !(flags & Uri_CREATE_FILE_USE_DOS_PATH)) { /* Convert to a '/'. */ if(!computeOnly) uri->canon_uri[uri->canon_len] = '/'; ++uri->canon_len; - } else { - /* Just copy it over. */ - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; + do_default_action = FALSE; } } else if(known_scheme && !is_unreserved(*ptr) && !is_reserved(*ptr) && !(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS)) { - if(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) { - /* Forbidden characters aren't percent encoded for file schemes - * with USE_DOS_PATH set. - */ - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; - } else if(data->scheme_type == URL_SCHEME_MK && *ptr == '\\') { - /* MK URIs don't get '\\' percent encoded. */ - if(!computeOnly) - uri->canon_uri[uri->canon_len] = *ptr; - ++uri->canon_len; - } else { + if(!(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH))) { if(!computeOnly) pct_encode_val(*ptr, uri->canon_uri+uri->canon_len); uri->canon_len += 3; + do_default_action = FALSE; } - } else { + } + + if(do_default_action) { if(!computeOnly) uri->canon_uri[uri->canon_len] = *ptr; ++uri->canon_len; @@ -3112,11 +3165,15 @@ static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD fla * URI is opaque it canonicalizes the path of the URI. */ static BOOL canonicalize_hierpart(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) { - uri->display_absolute = TRUE; - - if(!data->is_opaque) { - /* "//" is only added for non-wildcard scheme types. */ - if(data->scheme_type != URL_SCHEME_WILDCARD) { + if(!data->is_opaque || (data->is_relative && (data->password || data->username))) { + /* "//" is only added for non-wildcard scheme types. + * + * A "//" is only added to a relative URI if it has a + * host or port component (this only happens if a IUriBuilder + * is generating an IUri). + */ + if((data->is_relative && (data->host || data->has_port)) || + (!data->is_relative && data->scheme_type != URL_SCHEME_WILDCARD)) { if(!computeOnly) { INT pos = uri->canon_len; @@ -3129,10 +3186,13 @@ static BOOL canonicalize_hierpart(const parse_data *data, Uri *uri, DWORD flags, if(!canonicalize_authority(data, uri, flags, computeOnly)) return FALSE; - /* TODO: Canonicalize the path of the URI. */ - if(!canonicalize_path_hierarchical(data, uri, flags, computeOnly)) - return FALSE; - + if(data->is_relative && (data->password || data->username)) { + if(!canonicalize_path_opaque(data, uri, flags, computeOnly)) + return FALSE; + } else { + if(!canonicalize_path_hierarchical(data, uri, flags, computeOnly)) + return FALSE; + } } else { /* Opaque URI's don't have an authority. */ uri->userinfo_start = uri->userinfo_split = -1; @@ -3144,6 +3204,7 @@ static BOOL canonicalize_hierpart(const parse_data *data, Uri *uri, DWORD flags, uri->authority_start = -1; uri->authority_len = 0; uri->domain_offset = -1; + uri->port_offset = -1; if(is_hierarchical_scheme(data->scheme_type)) { DWORD i; @@ -3151,7 +3212,7 @@ static BOOL canonicalize_hierpart(const parse_data *data, Uri *uri, DWORD flags, /* Absolute URIs aren't displayed for known scheme types * which should be hierarchical URIs. */ - uri->display_absolute = FALSE; + uri->display_modifiers |= URI_DISPLAY_NO_ABSOLUTE_URI; /* Windows also sets the port for these (if they have one). */ for(i = 0; i < sizeof(default_ports)/sizeof(default_ports[0]); ++i) { @@ -3394,14 +3455,12 @@ static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) { uri->canon_size = len; if(!canonicalize_scheme(data, uri, flags, FALSE)) { ERR("(%p %p %x): Unable to canonicalize the scheme of the URI.\n", data, uri, flags); - heap_free(uri->canon_uri); return E_INVALIDARG; } uri->scheme_type = data->scheme_type; if(!canonicalize_hierpart(data, uri, flags, FALSE)) { ERR("(%p %p %x): Unable to canonicalize the heirpart of the URI\n", data, uri, flags); - heap_free(uri->canon_uri); return E_INVALIDARG; } @@ -3510,12 +3569,9 @@ static HRESULT set_builder_component(LPWSTR *component, DWORD *component_len, LP return S_OK; } -#define URI(x) ((IUri*) &(x)->lpIUriVtbl) -#define URIBUILDER(x) ((IUriBuilder*) &(x)->lpIUriBuilderVtbl) - static void reset_builder(UriBuilder *builder) { if(builder->uri) - IUri_Release(URI(builder->uri)); + IUri_Release(&builder->uri->IUri_iface); builder->uri = NULL; heap_free(builder->fragment); @@ -3720,8 +3776,11 @@ static void setup_port(const UriBuilder *builder, parse_data *data, DWORD flags) static HRESULT validate_path(const UriBuilder *builder, parse_data *data, DWORD flags) { const WCHAR *ptr = NULL; + const WCHAR *component; const WCHAR **pptr; DWORD expected_len; + BOOL check_len = TRUE; + BOOL valid = FALSE; if(builder->path) { ptr = builder->path; @@ -3730,29 +3789,30 @@ static HRESULT validate_path(const UriBuilder *builder, parse_data *data, DWORD builder->uri && builder->uri->path_start > -1) { ptr = builder->uri->canon_uri+builder->uri->path_start; expected_len = builder->uri->path_len; + } else { + static const WCHAR nullW[] = {0}; + ptr = nullW; + check_len = FALSE; } - if(ptr) { - BOOL valid = FALSE; - const WCHAR *component = ptr; - pptr = &ptr; + component = ptr; + pptr = &ptr; - /* How the path is validated depends on what type of - * URI it is. - */ - valid = data->is_opaque ? - parse_path_opaque(pptr, data, flags) : parse_path_hierarchical(pptr, data, flags); + /* How the path is validated depends on what type of + * URI it is. + */ + valid = data->is_opaque ? + parse_path_opaque(pptr, data, flags) : parse_path_hierarchical(pptr, data, flags); - if(!valid || expected_len != data->path_len) { - TRACE("(%p %p %x): Invalid path componet %s.\n", builder, data, flags, - debugstr_wn(component, expected_len)); - return INET_E_INVALID_URL; - } - - TRACE("(%p %p %x): Valid path component %s len=%d.\n", builder, data, flags, - debugstr_wn(data->path, data->path_len), data->path_len); + if(!valid || (check_len && expected_len != data->path_len)) { + TRACE("(%p %p %x): Invalid path component %s.\n", builder, data, flags, + debugstr_wn(component, check_len ? expected_len : -1) ); + return INET_E_INVALID_URL; } + TRACE("(%p %p %x): Valid path component %s len=%d.\n", builder, data, flags, + debugstr_wn(data->path, data->path_len), data->path_len); + return S_OK; } @@ -3805,7 +3865,7 @@ static HRESULT validate_fragment(const UriBuilder *builder, parse_data *data, DW const WCHAR *component = ptr; pptr = &ptr; - if(parse_query(pptr, data, flags) && expected_len == data->fragment_len) + if(parse_fragment(pptr, data, flags) && expected_len == data->fragment_len) TRACE("(%p %p %x): Valid fragment component %s len=%d.\n", builder, data, flags, debugstr_wn(data->fragment, data->fragment_len), data->fragment_len); else { @@ -3847,11 +3907,14 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data, if(FAILED(hr)) return hr; - /* The URI is opaque if it doesn't have an authority component. */ - data->is_opaque = !data->username && !data->password && !data->host; - setup_port(builder, data, flags); + /* The URI is opaque if it doesn't have an authority component. */ + if(!data->is_relative) + data->is_opaque = !data->username && !data->password && !data->host && !data->has_port; + else + data->is_opaque = !data->host && !data->has_port; + hr = validate_path(builder, data, flags); if(FAILED(hr)) return hr; @@ -3869,61 +3932,218 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data, return S_OK; } -static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_flags, - DWORD use_orig_flags, DWORD encoding_mask) +static void convert_to_dos_path(const WCHAR *path, DWORD path_len, + WCHAR *output, DWORD *output_len) { - HRESULT hr; - parse_data data; + const WCHAR *ptr = path; - if(!uri) - return E_POINTER; + if(path_len > 3 && *ptr == '/' && is_drive_path(path+1)) + /* Skip over the leading / before the drive path. */ + ++ptr; - if(encoding_mask && (!builder->uri || builder->modified_props)) { - *uri = NULL; - return E_NOTIMPL; + for(; ptr < path+path_len; ++ptr) { + if(*ptr == '/') { + if(output) + *output++ = '\\'; + (*output_len)++; + } else { + if(output) + *output++ = *ptr; + (*output_len)++; + } + } +} + +/* Generates a raw uri string using the parse_data. */ +static DWORD generate_raw_uri(const parse_data *data, BSTR uri, DWORD flags) { + DWORD length = 0; + + if(data->scheme) { + if(uri) { + memcpy(uri, data->scheme, data->scheme_len*sizeof(WCHAR)); + uri[data->scheme_len] = ':'; + } + length += data->scheme_len+1; } - /* Decide what flags should be used when creating the Uri. */ - if((use_orig_flags & UriBuilder_USE_ORIGINAL_FLAGS) && builder->uri) - create_flags = builder->uri->create_flags; - else { - if(has_invalid_flag_combination(create_flags)) { - *uri = NULL; - return E_INVALIDARG; + if(!data->is_opaque) { + /* For the "//" which appears before the authority component. */ + if(uri) { + uri[length] = '/'; + uri[length+1] = '/'; + } + length += 2; + + /* Check if we need to add the "\\" before the host name + * of a UNC server name in a DOS path. + */ + if(flags & RAW_URI_CONVERT_TO_DOS_PATH && + data->scheme_type == URL_SCHEME_FILE && data->host) { + if(uri) { + uri[length] = '\\'; + uri[length+1] = '\\'; + } + length += 2; + } + } + + if(data->username) { + if(uri) + memcpy(uri+length, data->username, data->username_len*sizeof(WCHAR)); + length += data->username_len; + } + + if(data->password) { + if(uri) { + uri[length] = ':'; + memcpy(uri+length+1, data->password, data->password_len*sizeof(WCHAR)); + } + length += data->password_len+1; + } + + if(data->password || data->username) { + if(uri) + uri[length] = '@'; + ++length; + } + + if(data->host) { + /* IPv6 addresses get the brackets added around them if they don't already + * have them. + */ + const BOOL add_brackets = data->host_type == Uri_HOST_IPV6 && *(data->host) != '['; + if(add_brackets) { + if(uri) + uri[length] = '['; + ++length; } - /* Set the default flags if they don't cause a conflict. */ - apply_default_flags(&create_flags); + if(uri) + memcpy(uri+length, data->host, data->host_len*sizeof(WCHAR)); + length += data->host_len; + + if(add_brackets) { + if(uri) + uri[length] = ']'; + length++; + } } - /* Return the base IUri if no changes have been made and the create_flags match. */ - if(builder->uri && !builder->modified_props && builder->uri->create_flags == create_flags) { - *uri = URI(builder->uri); - IUri_AddRef(*uri); - return S_OK; + if(data->has_port) { + /* The port isn't included in the raw uri if it's the default + * port for the scheme type. + */ + DWORD i; + BOOL is_default = FALSE; + + for(i = 0; i < sizeof(default_ports)/sizeof(default_ports[0]); ++i) { + if(data->scheme_type == default_ports[i].scheme && + data->port_value == default_ports[i].port) + is_default = TRUE; + } + + if(!is_default || flags & RAW_URI_FORCE_PORT_DISP) { + if(uri) + uri[length] = ':'; + ++length; + + if(uri) + length += ui2str(uri+length, data->port_value); + else + length += ui2str(NULL, data->port_value); + } } - hr = validate_components(builder, &data, create_flags); + /* Check if a '/' should be added before the path for hierarchical URIs. */ + if(!data->is_opaque && data->path && *(data->path) != '/') { + if(uri) + uri[length] = '/'; + ++length; + } + + if(data->path) { + if(!data->is_opaque && data->scheme_type == URL_SCHEME_FILE && + flags & RAW_URI_CONVERT_TO_DOS_PATH) { + DWORD len = 0; + + if(uri) + convert_to_dos_path(data->path, data->path_len, uri+length, &len); + else + convert_to_dos_path(data->path, data->path_len, NULL, &len); + + length += len; + } else { + if(uri) + memcpy(uri+length, data->path, data->path_len*sizeof(WCHAR)); + length += data->path_len; + } + } + + if(data->query) { + if(uri) + memcpy(uri+length, data->query, data->query_len*sizeof(WCHAR)); + length += data->query_len; + } + + if(data->fragment) { + if(uri) + memcpy(uri+length, data->fragment, data->fragment_len*sizeof(WCHAR)); + length += data->fragment_len; + } + + if(uri) + TRACE("(%p %p): Generated raw uri=%s len=%d\n", data, uri, debugstr_wn(uri, length), length); + else + TRACE("(%p %p): Computed raw uri len=%d\n", data, uri, length); + + return length; +} + +static HRESULT generate_uri(const UriBuilder *builder, const parse_data *data, Uri *uri, DWORD flags) { + HRESULT hr; + DWORD length = generate_raw_uri(data, NULL, 0); + uri->raw_uri = SysAllocStringLen(NULL, length); + if(!uri->raw_uri) + return E_OUTOFMEMORY; + + generate_raw_uri(data, uri->raw_uri, 0); + + hr = canonicalize_uri(data, uri, flags); if(FAILED(hr)) { - *uri = NULL; + if(hr == E_INVALIDARG) + return INET_E_INVALID_URL; return hr; } - return E_NOTIMPL; + uri->create_flags = flags; + return S_OK; } -#define URI_THIS(iface) DEFINE_THIS(Uri, IUri, iface) +static inline Uri* impl_from_IUri(IUri *iface) +{ + return CONTAINING_RECORD(iface, Uri, IUri_iface); +} + +static inline void destory_uri_obj(Uri *This) +{ + SysFreeString(This->raw_uri); + heap_free(This->canon_uri); + heap_free(This); +} static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = URI(This); + *ppv = &This->IUri_iface; }else if(IsEqualGUID(&IID_IUri, riid)) { TRACE("(%p)->(IID_IUri %p)\n", This, ppv); - *ppv = URI(This); + *ppv = &This->IUri_iface; + }else if(IsEqualGUID(&IID_IUriBuilderFactory, riid)) { + TRACE("(%p)->(IID_IUriBuilderFactory %p)\n", This, riid); + *ppv = &This->IUriBuilderFactory_iface; }else if(IsEqualGUID(&IID_IUriObj, riid)) { TRACE("(%p)->(IID_IUriObj %p)\n", This, ppv); *ppv = This; @@ -3940,7 +4160,7 @@ static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv) static ULONG WINAPI Uri_AddRef(IUri *iface) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -3950,23 +4170,20 @@ static ULONG WINAPI Uri_AddRef(IUri *iface) static ULONG WINAPI Uri_Release(IUri *iface) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); - if(!ref) { - SysFreeString(This->raw_uri); - heap_free(This->canon_uri); - heap_free(This); - } + if(!ref) + destory_uri_obj(This); return ref; } static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BSTR *pbstrProperty, DWORD dwFlags) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); HRESULT hres; TRACE("(%p)->(%d %p %x)\n", This, uriProp, pbstrProperty, dwFlags); @@ -3994,7 +4211,7 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST switch(uriProp) { case Uri_PROPERTY_ABSOLUTE_URI: - if(!This->display_absolute) { + if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) { *pbstrProperty = SysAllocStringLen(NULL, 0); hres = S_FALSE; } else { @@ -4036,7 +4253,12 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST break; case Uri_PROPERTY_AUTHORITY: if(This->authority_start > -1) { - *pbstrProperty = SysAllocStringLen(This->canon_uri+This->authority_start, This->authority_len); + if(This->port_offset > -1 && is_default_port(This->scheme_type, This->port) && + This->display_modifiers & URI_DISPLAY_NO_DEFAULT_PORT_AUTH) + /* Don't include the port in the authority component. */ + *pbstrProperty = SysAllocStringLen(This->canon_uri+This->authority_start, This->port_offset); + else + *pbstrProperty = SysAllocStringLen(This->canon_uri+This->authority_start, This->authority_len); hres = S_OK; } else { *pbstrProperty = SysAllocStringLen(NULL, 0); @@ -4251,7 +4473,7 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, DWORD *pcchProperty, DWORD dwFlags) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); HRESULT hres; TRACE("(%p)->(%d %p %x)\n", This, uriProp, pcchProperty, dwFlags); @@ -4270,7 +4492,7 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D switch(uriProp) { case Uri_PROPERTY_ABSOLUTE_URI: - if(!This->display_absolute) { + if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) { *pcchProperty = 0; hres = S_FALSE; } else { @@ -4292,7 +4514,13 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D break; case Uri_PROPERTY_AUTHORITY: - *pcchProperty = This->authority_len; + if(This->port_offset > -1 && + This->display_modifiers & URI_DISPLAY_NO_DEFAULT_PORT_AUTH && + is_default_port(This->scheme_type, This->port)) + /* Only count up until the port in the authority. */ + *pcchProperty = This->port_offset; + else + *pcchProperty = This->authority_len; hres = (This->authority_start > -1) ? S_OK : S_FALSE; break; case Uri_PROPERTY_DISPLAY_URI: @@ -4379,7 +4607,7 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D static HRESULT WINAPI Uri_GetPropertyDWORD(IUri *iface, Uri_PROPERTY uriProp, DWORD *pcchProperty, DWORD dwFlags) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); HRESULT hres; TRACE("(%p)->(%d %p %x)\n", This, uriProp, pcchProperty, dwFlags); @@ -4431,7 +4659,7 @@ static HRESULT WINAPI Uri_GetPropertyDWORD(IUri *iface, Uri_PROPERTY uriProp, DW static HRESULT WINAPI Uri_HasProperty(IUri *iface, Uri_PROPERTY uriProp, BOOL *pfHasProperty) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); TRACE("(%p)->(%d %p)\n", This, uriProp, pfHasProperty); if(!pfHasProperty) @@ -4439,7 +4667,7 @@ static HRESULT WINAPI Uri_HasProperty(IUri *iface, Uri_PROPERTY uriProp, BOOL *p switch(uriProp) { case Uri_PROPERTY_ABSOLUTE_URI: - *pfHasProperty = This->display_absolute; + *pfHasProperty = !(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI); break; case Uri_PROPERTY_AUTHORITY: *pfHasProperty = This->authority_start > -1; @@ -4509,121 +4737,120 @@ static HRESULT WINAPI Uri_HasProperty(IUri *iface, Uri_PROPERTY uriProp, BOOL *p static HRESULT WINAPI Uri_GetAbsoluteUri(IUri *iface, BSTR *pstrAbsoluteUri) { TRACE("(%p)->(%p)\n", iface, pstrAbsoluteUri); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_ABSOLUTE_URI, pstrAbsoluteUri, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_ABSOLUTE_URI, pstrAbsoluteUri, 0); } static HRESULT WINAPI Uri_GetAuthority(IUri *iface, BSTR *pstrAuthority) { TRACE("(%p)->(%p)\n", iface, pstrAuthority); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_AUTHORITY, pstrAuthority, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_AUTHORITY, pstrAuthority, 0); } static HRESULT WINAPI Uri_GetDisplayUri(IUri *iface, BSTR *pstrDisplayUri) { TRACE("(%p)->(%p)\n", iface, pstrDisplayUri); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_DISPLAY_URI, pstrDisplayUri, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_DISPLAY_URI, pstrDisplayUri, 0); } static HRESULT WINAPI Uri_GetDomain(IUri *iface, BSTR *pstrDomain) { TRACE("(%p)->(%p)\n", iface, pstrDomain); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_DOMAIN, pstrDomain, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_DOMAIN, pstrDomain, 0); } static HRESULT WINAPI Uri_GetExtension(IUri *iface, BSTR *pstrExtension) { TRACE("(%p)->(%p)\n", iface, pstrExtension); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_EXTENSION, pstrExtension, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_EXTENSION, pstrExtension, 0); } static HRESULT WINAPI Uri_GetFragment(IUri *iface, BSTR *pstrFragment) { TRACE("(%p)->(%p)\n", iface, pstrFragment); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_FRAGMENT, pstrFragment, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_FRAGMENT, pstrFragment, 0); } static HRESULT WINAPI Uri_GetHost(IUri *iface, BSTR *pstrHost) { TRACE("(%p)->(%p)\n", iface, pstrHost); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_HOST, pstrHost, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_HOST, pstrHost, 0); } static HRESULT WINAPI Uri_GetPassword(IUri *iface, BSTR *pstrPassword) { TRACE("(%p)->(%p)\n", iface, pstrPassword); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_PASSWORD, pstrPassword, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PASSWORD, pstrPassword, 0); } static HRESULT WINAPI Uri_GetPath(IUri *iface, BSTR *pstrPath) { TRACE("(%p)->(%p)\n", iface, pstrPath); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH, pstrPath, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH, pstrPath, 0); } static HRESULT WINAPI Uri_GetPathAndQuery(IUri *iface, BSTR *pstrPathAndQuery) { TRACE("(%p)->(%p)\n", iface, pstrPathAndQuery); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH_AND_QUERY, pstrPathAndQuery, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_PATH_AND_QUERY, pstrPathAndQuery, 0); } static HRESULT WINAPI Uri_GetQuery(IUri *iface, BSTR *pstrQuery) { TRACE("(%p)->(%p)\n", iface, pstrQuery); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_QUERY, pstrQuery, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_QUERY, pstrQuery, 0); } static HRESULT WINAPI Uri_GetRawUri(IUri *iface, BSTR *pstrRawUri) { TRACE("(%p)->(%p)\n", iface, pstrRawUri); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_RAW_URI, pstrRawUri, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_RAW_URI, pstrRawUri, 0); } static HRESULT WINAPI Uri_GetSchemeName(IUri *iface, BSTR *pstrSchemeName) { TRACE("(%p)->(%p)\n", iface, pstrSchemeName); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_SCHEME_NAME, pstrSchemeName, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_SCHEME_NAME, pstrSchemeName, 0); } static HRESULT WINAPI Uri_GetUserInfo(IUri *iface, BSTR *pstrUserInfo) { TRACE("(%p)->(%p)\n", iface, pstrUserInfo); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_INFO, pstrUserInfo, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_INFO, pstrUserInfo, 0); } static HRESULT WINAPI Uri_GetUserName(IUri *iface, BSTR *pstrUserName) { TRACE("(%p)->(%p)\n", iface, pstrUserName); - return Uri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_NAME, pstrUserName, 0); + return IUri_GetPropertyBSTR(iface, Uri_PROPERTY_USER_NAME, pstrUserName, 0); } static HRESULT WINAPI Uri_GetHostType(IUri *iface, DWORD *pdwHostType) { TRACE("(%p)->(%p)\n", iface, pdwHostType); - return Uri_GetPropertyDWORD(iface, Uri_PROPERTY_HOST_TYPE, pdwHostType, 0); + return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_HOST_TYPE, pdwHostType, 0); } static HRESULT WINAPI Uri_GetPort(IUri *iface, DWORD *pdwPort) { TRACE("(%p)->(%p)\n", iface, pdwPort); - return Uri_GetPropertyDWORD(iface, Uri_PROPERTY_PORT, pdwPort, 0); + return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_PORT, pdwPort, 0); } static HRESULT WINAPI Uri_GetScheme(IUri *iface, DWORD *pdwScheme) { - Uri *This = URI_THIS(iface); - TRACE("(%p)->(%p)\n", This, pdwScheme); - return Uri_GetPropertyDWORD(iface, Uri_PROPERTY_SCHEME, pdwScheme, 0); + TRACE("(%p)->(%p)\n", iface, pdwScheme); + return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_SCHEME, pdwScheme, 0); } static HRESULT WINAPI Uri_GetZone(IUri *iface, DWORD *pdwZone) { TRACE("(%p)->(%p)\n", iface, pdwZone); - return Uri_GetPropertyDWORD(iface, Uri_PROPERTY_ZONE,pdwZone, 0); + return IUri_GetPropertyDWORD(iface, Uri_PROPERTY_ZONE,pdwZone, 0); } static HRESULT WINAPI Uri_GetProperties(IUri *iface, DWORD *pdwProperties) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); TRACE("(%p)->(%p)\n", This, pdwProperties); if(!pdwProperties) @@ -4632,7 +4859,7 @@ static HRESULT WINAPI Uri_GetProperties(IUri *iface, DWORD *pdwProperties) /* All URIs have these. */ *pdwProperties = Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_SCHEME|Uri_HAS_HOST_TYPE; - if(This->display_absolute) + if(!(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI)) *pdwProperties |= Uri_HAS_ABSOLUTE_URI; if(This->scheme_start > -1) @@ -4671,7 +4898,7 @@ static HRESULT WINAPI Uri_GetProperties(IUri *iface, DWORD *pdwProperties) static HRESULT WINAPI Uri_IsEqual(IUri *iface, IUri *pUri, BOOL *pfEqual) { - Uri *This = URI_THIS(iface); + Uri *This = impl_from_IUri(iface); Uri *other; TRACE("(%p)->(%p %p)\n", This, pUri, pfEqual); @@ -4698,8 +4925,6 @@ static HRESULT WINAPI Uri_IsEqual(IUri *iface, IUri *pUri, BOOL *pfEqual) return S_OK; } -#undef URI_THIS - static const IUriVtbl UriVtbl = { Uri_QueryInterface, Uri_AddRef, @@ -4731,6 +4956,114 @@ static const IUriVtbl UriVtbl = { Uri_IsEqual }; +static inline Uri* impl_from_IUriBuilderFactory(IUriBuilderFactory *iface) +{ + return CONTAINING_RECORD(iface, Uri, IUriBuilderFactory_iface); +} + +static HRESULT WINAPI UriBuilderFactory_QueryInterface(IUriBuilderFactory *iface, REFIID riid, void **ppv) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IUriBuilderFactory_iface; + }else if(IsEqualGUID(&IID_IUriBuilderFactory, riid)) { + TRACE("(%p)->(IID_IUriBuilderFactory %p)\n", This, ppv); + *ppv = &This->IUriBuilderFactory_iface; + }else if(IsEqualGUID(&IID_IUri, riid)) { + TRACE("(%p)->(IID_IUri %p)\n", This, ppv); + *ppv = &This->IUri_iface; + }else { + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI UriBuilderFactory_AddRef(IUriBuilderFactory *iface) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI UriBuilderFactory_Release(IUriBuilderFactory *iface) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) + destory_uri_obj(This); + + return ref; +} + +static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilderFactory *iface, + DWORD dwFlags, + DWORD_PTR dwReserved, + IUriBuilder **ppIUriBuilder) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder); + + if(!ppIUriBuilder) + return E_POINTER; + + if(dwFlags || dwReserved) { + *ppIUriBuilder = NULL; + return E_INVALIDARG; + } + + return CreateIUriBuilder(NULL, 0, 0, ppIUriBuilder); +} + +static HRESULT WINAPI UriBuilderFactory_CreateIUriBuilder(IUriBuilderFactory *iface, + DWORD dwFlags, + DWORD_PTR dwReserved, + IUriBuilder **ppIUriBuilder) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder); + + if(!ppIUriBuilder) + return E_POINTER; + + if(dwFlags || dwReserved) { + *ppIUriBuilder = NULL; + return E_INVALIDARG; + } + + return CreateIUriBuilder(&This->IUri_iface, 0, 0, ppIUriBuilder); +} + +static const IUriBuilderFactoryVtbl UriBuilderFactoryVtbl = { + UriBuilderFactory_QueryInterface, + UriBuilderFactory_AddRef, + UriBuilderFactory_Release, + UriBuilderFactory_CreateInitializedIUriBuilder, + UriBuilderFactory_CreateIUriBuilder +}; + +static Uri* create_uri_obj(void) { + Uri *ret = heap_alloc_zero(sizeof(Uri)); + if(ret) { + ret->IUri_iface.lpVtbl = &UriVtbl; + ret->IUriBuilderFactory_iface.lpVtbl = &UriBuilderFactoryVtbl; + ret->ref = 1; + } + + return ret; +} + /*********************************************************************** * CreateUri (urlmon.@) * @@ -4786,12 +5119,11 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU if(dwFlags & ~supported_flags) FIXME("Ignoring unsupported flag(s) %x\n", dwFlags & ~supported_flags); - ret = heap_alloc(sizeof(Uri)); - if(!ret) + ret = create_uri_obj(); + if(!ret) { + *ppURI = NULL; return E_OUTOFMEMORY; - - ret->lpIUriVtbl = &UriVtbl; - ret->ref = 1; + } /* Explicitly set the default flags if it doesn't cause a flag conflict. */ apply_default_flags(&dwFlags); @@ -4813,8 +5145,7 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU /* Validate and parse the URI into it's components. */ if(!parse_uri(&data, dwFlags)) { /* Encountered an unsupported or invalid URI */ - SysFreeString(ret->raw_uri); - heap_free(ret); + IUri_Release(&ret->IUri_iface); *ppURI = NULL; return E_INVALIDARG; } @@ -4822,15 +5153,14 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU /* Canonicalize the URI. */ hr = canonicalize_uri(&data, ret, dwFlags); if(FAILED(hr)) { - SysFreeString(ret->raw_uri); - heap_free(ret); + IUri_Release(&ret->IUri_iface); *ppURI = NULL; return hr; } ret->create_flags = dwFlags; - *ppURI = URI(ret); + *ppURI = &ret->IUri_iface; return S_OK; } @@ -4908,18 +5238,79 @@ HRESULT WINAPI CreateUriWithFragment(LPCWSTR pwzURI, LPCWSTR pwzFragment, DWORD return hres; } -#define URIBUILDER_THIS(iface) DEFINE_THIS(UriBuilder, IUriBuilder, iface) +static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_flags, + DWORD use_orig_flags, DWORD encoding_mask) +{ + HRESULT hr; + parse_data data; + Uri *ret; + + if(!uri) + return E_POINTER; + + if(encoding_mask && (!builder->uri || builder->modified_props)) { + *uri = NULL; + return E_NOTIMPL; + } + + /* Decide what flags should be used when creating the Uri. */ + if((use_orig_flags & UriBuilder_USE_ORIGINAL_FLAGS) && builder->uri) + create_flags = builder->uri->create_flags; + else { + if(has_invalid_flag_combination(create_flags)) { + *uri = NULL; + return E_INVALIDARG; + } + + /* Set the default flags if they don't cause a conflict. */ + apply_default_flags(&create_flags); + } + + /* Return the base IUri if no changes have been made and the create_flags match. */ + if(builder->uri && !builder->modified_props && builder->uri->create_flags == create_flags) { + *uri = &builder->uri->IUri_iface; + IUri_AddRef(*uri); + return S_OK; + } + + hr = validate_components(builder, &data, create_flags); + if(FAILED(hr)) { + *uri = NULL; + return hr; + } + + ret = create_uri_obj(); + if(!ret) { + *uri = NULL; + return E_OUTOFMEMORY; + } + + hr = generate_uri(builder, &data, ret, create_flags); + if(FAILED(hr)) { + IUri_Release(&ret->IUri_iface); + *uri = NULL; + return hr; + } + + *uri = &ret->IUri_iface; + return S_OK; +} + +static inline UriBuilder* impl_from_IUriBuilder(IUriBuilder *iface) +{ + return CONTAINING_RECORD(iface, UriBuilder, IUriBuilder_iface); +} static HRESULT WINAPI UriBuilder_QueryInterface(IUriBuilder *iface, REFIID riid, void **ppv) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = URIBUILDER(This); + *ppv = &This->IUriBuilder_iface; }else if(IsEqualGUID(&IID_IUriBuilder, riid)) { - TRACE("(%p)->(IID_IUri %p)\n", This, ppv); - *ppv = URIBUILDER(This); + TRACE("(%p)->(IID_IUriBuilder %p)\n", This, ppv); + *ppv = &This->IUriBuilder_iface; }else { TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); *ppv = NULL; @@ -4932,7 +5323,7 @@ static HRESULT WINAPI UriBuilder_QueryInterface(IUriBuilder *iface, REFIID riid, static ULONG WINAPI UriBuilder_AddRef(IUriBuilder *iface) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -4942,13 +5333,13 @@ static ULONG WINAPI UriBuilder_AddRef(IUriBuilder *iface) static ULONG WINAPI UriBuilder_Release(IUriBuilder *iface) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - if(This->uri) IUri_Release(URI(This->uri)); + if(This->uri) IUri_Release(&This->uri->IUri_iface); heap_free(This->fragment); heap_free(This->host); heap_free(This->password); @@ -4967,7 +5358,7 @@ static HRESULT WINAPI UriBuilder_CreateUriSimple(IUriBuilder *iface, DWORD_PTR dwReserved, IUri **ppIUri) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); HRESULT hr; TRACE("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); @@ -4983,7 +5374,7 @@ static HRESULT WINAPI UriBuilder_CreateUri(IUriBuilder *iface, DWORD_PTR dwReserved, IUri **ppIUri) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); HRESULT hr; TRACE("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); @@ -5004,7 +5395,7 @@ static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface, DWORD_PTR dwReserved, IUri **ppIUri) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); HRESULT hr; TRACE("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); @@ -5018,14 +5409,14 @@ static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface, static HRESULT WINAPI UriBuilder_GetIUri(IUriBuilder *iface, IUri **ppIUri) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p)\n", This, ppIUri); if(!ppIUri) return E_POINTER; if(This->uri) { - IUri *uri = URI(This->uri); + IUri *uri = &This->uri->IUri_iface; IUri_AddRef(uri); *ppIUri = uri; } else @@ -5036,7 +5427,7 @@ static HRESULT WINAPI UriBuilder_GetIUri(IUriBuilder *iface, IUri **ppIUri) static HRESULT WINAPI UriBuilder_SetIUri(IUriBuilder *iface, IUri *pIUri) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p)\n", This, pIUri); if(pIUri) { @@ -5068,7 +5459,7 @@ static HRESULT WINAPI UriBuilder_SetIUri(IUriBuilder *iface, IUri *pIUri) static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFragment, LPCWSTR *ppwzFragment) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment); if(!This->uri || This->uri->fragment_start == -1 || This->modified_props & Uri_HAS_FRAGMENT) @@ -5080,7 +5471,7 @@ static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFrag static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LPCWSTR *ppwzHost) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchHost, ppwzHost); if(!This->uri || This->uri->host_start == -1 || This->modified_props & Uri_HAS_HOST) @@ -5098,7 +5489,7 @@ static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LP static HRESULT WINAPI UriBuilder_GetPassword(IUriBuilder *iface, DWORD *pcchPassword, LPCWSTR *ppwzPassword) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchPassword, ppwzPassword); if(!This->uri || This->uri->userinfo_split == -1 || This->modified_props & Uri_HAS_PASSWORD) @@ -5112,7 +5503,7 @@ static HRESULT WINAPI UriBuilder_GetPassword(IUriBuilder *iface, DWORD *pcchPass static HRESULT WINAPI UriBuilder_GetPath(IUriBuilder *iface, DWORD *pcchPath, LPCWSTR *ppwzPath) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchPath, ppwzPath); if(!This->uri || This->uri->path_start == -1 || This->modified_props & Uri_HAS_PATH) @@ -5124,7 +5515,7 @@ static HRESULT WINAPI UriBuilder_GetPath(IUriBuilder *iface, DWORD *pcchPath, LP static HRESULT WINAPI UriBuilder_GetPort(IUriBuilder *iface, BOOL *pfHasPort, DWORD *pdwPort) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pfHasPort, pdwPort); if(!pfHasPort) { @@ -5145,7 +5536,7 @@ static HRESULT WINAPI UriBuilder_GetPort(IUriBuilder *iface, BOOL *pfHasPort, DW static HRESULT WINAPI UriBuilder_GetQuery(IUriBuilder *iface, DWORD *pcchQuery, LPCWSTR *ppwzQuery) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchQuery, ppwzQuery); if(!This->uri || This->uri->query_start == -1 || This->modified_props & Uri_HAS_QUERY) @@ -5157,7 +5548,7 @@ static HRESULT WINAPI UriBuilder_GetQuery(IUriBuilder *iface, DWORD *pcchQuery, static HRESULT WINAPI UriBuilder_GetSchemeName(IUriBuilder *iface, DWORD *pcchSchemeName, LPCWSTR *ppwzSchemeName) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchSchemeName, ppwzSchemeName); if(!This->uri || This->uri->scheme_start == -1 || This->modified_props & Uri_HAS_SCHEME_NAME) @@ -5169,7 +5560,7 @@ static HRESULT WINAPI UriBuilder_GetSchemeName(IUriBuilder *iface, DWORD *pcchSc static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUserName, LPCWSTR *ppwzUserName) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p %p)\n", This, pcchUserName, ppwzUserName); if(!This->uri || This->uri->userinfo_start == -1 || This->uri->userinfo_split == 0 || @@ -5191,7 +5582,7 @@ static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUser static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); return set_builder_component(&This->fragment, &This->fragment_len, pwzNewValue, '#', &This->modified_props, Uri_HAS_FRAGMENT); @@ -5199,7 +5590,7 @@ static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewV static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); /* Host name can't be set to NULL. */ @@ -5212,7 +5603,7 @@ static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue static HRESULT WINAPI UriBuilder_SetPassword(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); return set_builder_component(&This->password, &This->password_len, pwzNewValue, 0, &This->modified_props, Uri_HAS_PASSWORD); @@ -5220,7 +5611,7 @@ static HRESULT WINAPI UriBuilder_SetPassword(IUriBuilder *iface, LPCWSTR pwzNewV static HRESULT WINAPI UriBuilder_SetPath(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); return set_builder_component(&This->path, &This->path_len, pwzNewValue, 0, &This->modified_props, Uri_HAS_PATH); @@ -5228,7 +5619,7 @@ static HRESULT WINAPI UriBuilder_SetPath(IUriBuilder *iface, LPCWSTR pwzNewValue static HRESULT WINAPI UriBuilder_SetPort(IUriBuilder *iface, BOOL fHasPort, DWORD dwNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%d %d)\n", This, fHasPort, dwNewValue); This->has_port = fHasPort; @@ -5239,7 +5630,7 @@ static HRESULT WINAPI UriBuilder_SetPort(IUriBuilder *iface, BOOL fHasPort, DWOR static HRESULT WINAPI UriBuilder_SetQuery(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); return set_builder_component(&This->query, &This->query_len, pwzNewValue, '?', &This->modified_props, Uri_HAS_QUERY); @@ -5247,7 +5638,7 @@ static HRESULT WINAPI UriBuilder_SetQuery(IUriBuilder *iface, LPCWSTR pwzNewValu static HRESULT WINAPI UriBuilder_SetSchemeName(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); /* Only set the scheme name if it's not NULL or empty. */ @@ -5260,7 +5651,7 @@ static HRESULT WINAPI UriBuilder_SetSchemeName(IUriBuilder *iface, LPCWSTR pwzNe static HRESULT WINAPI UriBuilder_SetUserName(IUriBuilder *iface, LPCWSTR pwzNewValue) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); return set_builder_component(&This->username, &This->username_len, pwzNewValue, 0, &This->modified_props, Uri_HAS_USER_NAME); @@ -5272,7 +5663,7 @@ static HRESULT WINAPI UriBuilder_RemoveProperties(IUriBuilder *iface, DWORD dwPr Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY| Uri_HAS_USER_INFO|Uri_HAS_USER_NAME; - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(0x%08x)\n", This, dwPropertyMask); if(dwPropertyMask & ~accepted_flags) @@ -5308,7 +5699,7 @@ static HRESULT WINAPI UriBuilder_RemoveProperties(IUriBuilder *iface, DWORD dwPr static HRESULT WINAPI UriBuilder_HasBeenModified(IUriBuilder *iface, BOOL *pfModified) { - UriBuilder *This = URIBUILDER_THIS(iface); + UriBuilder *This = impl_from_IUriBuilder(iface); TRACE("(%p)->(%p)\n", This, pfModified); if(!pfModified) @@ -5318,8 +5709,6 @@ static HRESULT WINAPI UriBuilder_HasBeenModified(IUriBuilder *iface, BOOL *pfMod return S_OK; } -#undef URIBUILDER_THIS - static const IUriBuilderVtbl UriBuilderVtbl = { UriBuilder_QueryInterface, UriBuilder_AddRef, @@ -5365,7 +5754,7 @@ HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserve if(!ret) return E_OUTOFMEMORY; - ret->lpIUriBuilderVtbl = &UriBuilderVtbl; + ret->IUriBuilder_iface.lpVtbl = &UriBuilderVtbl; ret->ref = 1; if(pIUri) { @@ -5388,6 +5777,915 @@ HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserve } } - *ppIUriBuilder = URIBUILDER(ret); + *ppIUriBuilder = &ret->IUriBuilder_iface; return S_OK; } + +/* Merges the base path with the relative path and stores the resulting path + * and path len in 'result' and 'result_len'. + */ +static HRESULT merge_paths(parse_data *data, const WCHAR *base, DWORD base_len, const WCHAR *relative, + DWORD relative_len, WCHAR **result, DWORD *result_len, DWORD flags) +{ + const WCHAR *end = NULL; + DWORD base_copy_len = 0; + WCHAR *ptr; + + if(base_len) { + /* Find the characters the will be copied over from + * the base path. + */ + end = str_last_of(base, base+(base_len-1), '/'); + if(!end && data->scheme_type == URL_SCHEME_FILE) + /* Try looking for a '\\'. */ + end = str_last_of(base, base+(base_len-1), '\\'); + } + + if(end) { + base_copy_len = (end+1)-base; + *result = heap_alloc((base_copy_len+relative_len+1)*sizeof(WCHAR)); + } else + *result = heap_alloc((relative_len+1)*sizeof(WCHAR)); + + if(!(*result)) { + *result_len = 0; + return E_OUTOFMEMORY; + } + + ptr = *result; + if(end) { + memcpy(ptr, base, base_copy_len*sizeof(WCHAR)); + ptr += base_copy_len; + } + + memcpy(ptr, relative, relative_len*sizeof(WCHAR)); + ptr += relative_len; + *ptr = '\0'; + + *result_len = (ptr-*result); + return S_OK; +} + +static HRESULT combine_uri(Uri *base, Uri *relative, DWORD flags, IUri **result, DWORD extras) { + Uri *ret; + HRESULT hr; + parse_data data; + DWORD create_flags = 0, len = 0; + + memset(&data, 0, sizeof(parse_data)); + + /* Base case is when the relative Uri has a scheme name, + * if it does, then 'result' will contain the same data + * as the relative Uri. + */ + if(relative->scheme_start > -1) { + data.uri = SysAllocString(relative->raw_uri); + if(!data.uri) { + *result = NULL; + return E_OUTOFMEMORY; + } + + parse_uri(&data, 0); + + ret = create_uri_obj(); + if(!ret) { + *result = NULL; + return E_OUTOFMEMORY; + } + + if(extras & COMBINE_URI_FORCE_FLAG_USE) { + if(flags & URL_DONT_SIMPLIFY) + create_flags |= Uri_CREATE_NO_CANONICALIZE; + if(flags & URL_DONT_UNESCAPE_EXTRA_INFO) + create_flags |= Uri_CREATE_NO_DECODE_EXTRA_INFO; + } + + ret->raw_uri = data.uri; + hr = canonicalize_uri(&data, ret, create_flags); + if(FAILED(hr)) { + IUri_Release(&ret->IUri_iface); + *result = NULL; + return hr; + } + + apply_default_flags(&create_flags); + ret->create_flags = create_flags; + + *result = &ret->IUri_iface; + } else { + WCHAR *path = NULL; + DWORD raw_flags = 0; + + if(base->scheme_start > -1) { + data.scheme = base->canon_uri+base->scheme_start; + data.scheme_len = base->scheme_len; + data.scheme_type = base->scheme_type; + } else { + data.is_relative = TRUE; + data.scheme_type = URL_SCHEME_UNKNOWN; + create_flags |= Uri_CREATE_ALLOW_RELATIVE; + } + + if(base->authority_start > -1) { + if(base->userinfo_start > -1 && base->userinfo_split != 0) { + data.username = base->canon_uri+base->userinfo_start; + data.username_len = (base->userinfo_split > -1) ? base->userinfo_split : base->userinfo_len; + } + + if(base->userinfo_split > -1) { + data.password = base->canon_uri+base->userinfo_start+base->userinfo_split+1; + data.password_len = base->userinfo_len-base->userinfo_split-1; + } + + if(base->host_start > -1) { + data.host = base->canon_uri+base->host_start; + data.host_len = base->host_len; + data.host_type = base->host_type; + } + + if(base->has_port) { + data.has_port = TRUE; + data.port_value = base->port; + } + } else if(base->scheme_type != URL_SCHEME_FILE) + data.is_opaque = TRUE; + + if(relative->path_start == -1 || !relative->path_len) { + if(base->path_start > -1) { + data.path = base->canon_uri+base->path_start; + data.path_len = base->path_len; + } else if((base->path_start == -1 || !base->path_len) && !data.is_opaque) { + /* Just set the path as a '/' if the base didn't have + * one and if it's an hierarchical URI. + */ + static const WCHAR slashW[] = {'/',0}; + data.path = slashW; + data.path_len = 1; + } + + if(relative->query_start > -1) { + data.query = relative->canon_uri+relative->query_start; + data.query_len = relative->query_len; + } else if(base->query_start > -1) { + data.query = base->canon_uri+base->query_start; + data.query_len = base->query_len; + } + } else { + const WCHAR *ptr, **pptr; + DWORD path_offset = 0, path_len = 0; + + /* There's two possibilities on what will happen to the path component + * of the result IUri. First, if the relative path begins with a '/' + * then the resulting path will just be the relative path. Second, if + * relative path doesn't begin with a '/' then the base path and relative + * path are merged together. + */ + if(relative->path_len && *(relative->canon_uri+relative->path_start) == '/') { + WCHAR *tmp = NULL; + BOOL copy_drive_path = FALSE; + + /* If the relative IUri's path starts with a '/', then we + * don't use the base IUri's path. Unless the base IUri + * is a file URI, in which case it uses the drive path of + * the base IUri (if it has any) in the new path. + */ + if(base->scheme_type == URL_SCHEME_FILE) { + if(base->path_len > 3 && *(base->canon_uri+base->path_start) == '/' && + is_drive_path(base->canon_uri+base->path_start+1)) { + path_len += 3; + copy_drive_path = TRUE; + } + } + + path_len += relative->path_len; + + path = heap_alloc((path_len+1)*sizeof(WCHAR)); + if(!path) { + *result = NULL; + return E_OUTOFMEMORY; + } + + tmp = path; + + /* Copy the base paths, drive path over. */ + if(copy_drive_path) { + memcpy(tmp, base->canon_uri+base->path_start, 3*sizeof(WCHAR)); + tmp += 3; + } + + memcpy(tmp, relative->canon_uri+relative->path_start, relative->path_len*sizeof(WCHAR)); + path[path_len] = '\0'; + } else { + /* Merge the base path with the relative path. */ + hr = merge_paths(&data, base->canon_uri+base->path_start, base->path_len, + relative->canon_uri+relative->path_start, relative->path_len, + &path, &path_len, flags); + if(FAILED(hr)) { + *result = NULL; + return hr; + } + + /* If the resulting IUri is a file URI, the drive path isn't + * reduced out when the dot segments are removed. + */ + if(path_len >= 3 && data.scheme_type == URL_SCHEME_FILE && !data.host) { + if(*path == '/' && is_drive_path(path+1)) + path_offset = 2; + else if(is_drive_path(path)) + path_offset = 1; + } + } + + /* Check if the dot segments need to be removed from the path. */ + if(!(flags & URL_DONT_SIMPLIFY) && !data.is_opaque) { + DWORD offset = (path_offset > 0) ? path_offset+1 : 0; + DWORD new_len = remove_dot_segments(path+offset,path_len-offset); + + if(new_len != path_len) { + WCHAR *tmp = heap_realloc(path, (path_offset+new_len+1)*sizeof(WCHAR)); + if(!tmp) { + heap_free(path); + *result = NULL; + return E_OUTOFMEMORY; + } + + tmp[new_len+offset] = '\0'; + path = tmp; + path_len = new_len+offset; + } + } + + /* Make sure the path component is valid. */ + ptr = path; + pptr = &ptr; + if((data.is_opaque && !parse_path_opaque(pptr, &data, 0)) || + (!data.is_opaque && !parse_path_hierarchical(pptr, &data, 0))) { + heap_free(path); + *result = NULL; + return E_INVALIDARG; + } + } + + if(relative->fragment_start > -1) { + data.fragment = relative->canon_uri+relative->fragment_start; + data.fragment_len = relative->fragment_len; + } + + if(flags & URL_DONT_SIMPLIFY) + raw_flags |= RAW_URI_FORCE_PORT_DISP; + if(flags & URL_FILE_USE_PATHURL) + raw_flags |= RAW_URI_CONVERT_TO_DOS_PATH; + + len = generate_raw_uri(&data, data.uri, raw_flags); + data.uri = SysAllocStringLen(NULL, len); + if(!data.uri) { + heap_free(path); + *result = NULL; + return E_OUTOFMEMORY; + } + + generate_raw_uri(&data, data.uri, raw_flags); + + ret = create_uri_obj(); + if(!ret) { + SysFreeString(data.uri); + heap_free(path); + *result = NULL; + return E_OUTOFMEMORY; + } + + if(flags & URL_DONT_SIMPLIFY) + create_flags |= Uri_CREATE_NO_CANONICALIZE; + if(flags & URL_FILE_USE_PATHURL) + create_flags |= Uri_CREATE_FILE_USE_DOS_PATH; + + ret->raw_uri = data.uri; + hr = canonicalize_uri(&data, ret, create_flags); + if(FAILED(hr)) { + IUri_Release(&ret->IUri_iface); + *result = NULL; + return hr; + } + + if(flags & URL_DONT_SIMPLIFY) + ret->display_modifiers |= URI_DISPLAY_NO_DEFAULT_PORT_AUTH; + + apply_default_flags(&create_flags); + ret->create_flags = create_flags; + *result = &ret->IUri_iface; + + heap_free(path); + } + + return S_OK; +} + +/*********************************************************************** + * CoInternetCombineIUri (urlmon.@) + */ +HRESULT WINAPI CoInternetCombineIUri(IUri *pBaseUri, IUri *pRelativeUri, DWORD dwCombineFlags, + IUri **ppCombinedUri, DWORD_PTR dwReserved) +{ + HRESULT hr; + IInternetProtocolInfo *info; + Uri *relative, *base; + TRACE("(%p %p %x %p %x)\n", pBaseUri, pRelativeUri, dwCombineFlags, ppCombinedUri, (DWORD)dwReserved); + + if(!ppCombinedUri) + return E_INVALIDARG; + + if(!pBaseUri || !pRelativeUri) { + *ppCombinedUri = NULL; + return E_INVALIDARG; + } + + relative = get_uri_obj(pRelativeUri); + base = get_uri_obj(pBaseUri); + if(!relative || !base) { + *ppCombinedUri = NULL; + FIXME("(%p %p %x %p %x) Unknown IUri types not supported yet.\n", + pBaseUri, pRelativeUri, dwCombineFlags, ppCombinedUri, (DWORD)dwReserved); + return E_NOTIMPL; + } + + info = get_protocol_info(base->canon_uri); + if(info) { + WCHAR result[INTERNET_MAX_URL_LENGTH+1]; + DWORD result_len = 0; + + hr = IInternetProtocolInfo_CombineUrl(info, base->canon_uri, relative->canon_uri, dwCombineFlags, + result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0); + IInternetProtocolInfo_Release(info); + if(SUCCEEDED(hr)) { + hr = CreateUri(result, Uri_CREATE_ALLOW_RELATIVE, 0, ppCombinedUri); + if(SUCCEEDED(hr)) + return hr; + } + } + + return combine_uri(base, relative, dwCombineFlags, ppCombinedUri, 0); +} + +/*********************************************************************** + * CoInternetCombineUrlEx (urlmon.@) + */ +HRESULT WINAPI CoInternetCombineUrlEx(IUri *pBaseUri, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, + IUri **ppCombinedUri, DWORD_PTR dwReserved) +{ + IUri *relative; + Uri *base; + HRESULT hr; + IInternetProtocolInfo *info; + + TRACE("(%p %s %x %p %x) stub\n", pBaseUri, debugstr_w(pwzRelativeUrl), dwCombineFlags, + ppCombinedUri, (DWORD)dwReserved); + + if(!ppCombinedUri) + return E_POINTER; + + if(!pwzRelativeUrl) { + *ppCombinedUri = NULL; + return E_UNEXPECTED; + } + + if(!pBaseUri) { + *ppCombinedUri = NULL; + return E_INVALIDARG; + } + + base = get_uri_obj(pBaseUri); + if(!base) { + *ppCombinedUri = NULL; + FIXME("(%p %s %x %p %x) Unknown IUri's not supported yet.\n", pBaseUri, debugstr_w(pwzRelativeUrl), + dwCombineFlags, ppCombinedUri, (DWORD)dwReserved); + return E_NOTIMPL; + } + + info = get_protocol_info(base->canon_uri); + if(info) { + WCHAR result[INTERNET_MAX_URL_LENGTH+1]; + DWORD result_len = 0; + + hr = IInternetProtocolInfo_CombineUrl(info, base->canon_uri, pwzRelativeUrl, dwCombineFlags, + result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0); + IInternetProtocolInfo_Release(info); + if(SUCCEEDED(hr)) { + hr = CreateUri(result, Uri_CREATE_ALLOW_RELATIVE, 0, ppCombinedUri); + if(SUCCEEDED(hr)) + return hr; + } + } + + hr = CreateUri(pwzRelativeUrl, Uri_CREATE_ALLOW_RELATIVE, 0, &relative); + if(FAILED(hr)) { + *ppCombinedUri = NULL; + return hr; + } + + hr = combine_uri(base, get_uri_obj(relative), dwCombineFlags, ppCombinedUri, COMBINE_URI_FORCE_FLAG_USE); + + IUri_Release(relative); + return hr; +} + +static HRESULT parse_canonicalize(const Uri *uri, DWORD flags, LPWSTR output, + DWORD output_len, DWORD *result_len) +{ + const WCHAR *ptr = NULL; + WCHAR *path = NULL; + const WCHAR **pptr; + WCHAR buffer[INTERNET_MAX_URL_LENGTH+1]; + DWORD len = 0; + BOOL reduce_path; + + /* URL_UNESCAPE only has effect if none of the URL_ESCAPE flags are set. */ + const BOOL allow_unescape = !(flags & URL_ESCAPE_UNSAFE) && + !(flags & URL_ESCAPE_SPACES_ONLY) && + !(flags & URL_ESCAPE_PERCENT); + + + /* Check if the dot segments need to be removed from the + * path component. + */ + if(uri->scheme_start > -1 && uri->path_start > -1) { + ptr = uri->canon_uri+uri->scheme_start+uri->scheme_len+1; + pptr = &ptr; + } + reduce_path = !(flags & URL_NO_META) && + !(flags & URL_DONT_SIMPLIFY) && + ptr && check_hierarchical(pptr); + + for(ptr = uri->canon_uri; ptr < uri->canon_uri+uri->canon_len; ++ptr) { + BOOL do_default_action = TRUE; + + /* Keep track of the path if we need to remove dot segments from + * it later. + */ + if(reduce_path && !path && ptr == uri->canon_uri+uri->path_start) + path = buffer+len; + + /* Check if it's time to reduce the path. */ + if(reduce_path && ptr == uri->canon_uri+uri->path_start+uri->path_len) { + DWORD current_path_len = (buffer+len) - path; + DWORD new_path_len = remove_dot_segments(path, current_path_len); + + /* Update the current length. */ + len -= (current_path_len-new_path_len); + reduce_path = FALSE; + } + + if(*ptr == '%') { + const WCHAR decoded = decode_pct_val(ptr); + if(decoded) { + if(allow_unescape && (flags & URL_UNESCAPE)) { + buffer[len++] = decoded; + ptr += 2; + do_default_action = FALSE; + } + } + + /* See if %'s needed to encoded. */ + if(do_default_action && (flags & URL_ESCAPE_PERCENT)) { + pct_encode_val(*ptr, buffer+len); + len += 3; + do_default_action = FALSE; + } + } else if(*ptr == ' ') { + if((flags & URL_ESCAPE_SPACES_ONLY) && + !(flags & URL_ESCAPE_UNSAFE)) { + pct_encode_val(*ptr, buffer+len); + len += 3; + do_default_action = FALSE; + } + } else if(!is_reserved(*ptr) && !is_unreserved(*ptr)) { + if(flags & URL_ESCAPE_UNSAFE) { + pct_encode_val(*ptr, buffer+len); + len += 3; + do_default_action = FALSE; + } + } + + if(do_default_action) + buffer[len++] = *ptr; + } + + /* Sometimes the path is the very last component of the IUri, so + * see if the dot segments need to be reduced now. + */ + if(reduce_path && path) { + DWORD current_path_len = (buffer+len) - path; + DWORD new_path_len = remove_dot_segments(path, current_path_len); + + /* Update the current length. */ + len -= (current_path_len-new_path_len); + } + + buffer[len++] = 0; + + /* The null terminator isn't included the length. */ + *result_len = len-1; + if(len > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + else + memcpy(output, buffer, len*sizeof(WCHAR)); + + return S_OK; +} + +static HRESULT parse_friendly(IUri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + HRESULT hr; + DWORD display_len; + BSTR display; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DISPLAY_URI, &display_len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = display_len; + if(display_len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetDisplayUri(uri, &display); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, display, (display_len+1)*sizeof(WCHAR)); + SysFreeString(display); + return S_OK; +} + +static HRESULT parse_rootdocument(const Uri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + static const WCHAR colon_slashesW[] = {':','/','/'}; + + WCHAR *ptr; + DWORD len = 0; + + /* Windows only returns the root document if the URI has an authority + * and it's not an unknown scheme type or a file scheme type. + */ + if(uri->authority_start == -1 || + uri->scheme_type == URL_SCHEME_UNKNOWN || + uri->scheme_type == URL_SCHEME_FILE) { + *result_len = 0; + if(!output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + output[0] = 0; + return S_OK; + } + + len = uri->scheme_len+uri->authority_len; + /* For the "://" and '/' which will be added. */ + len += 4; + + if(len+1 > output_len) { + *result_len = len; + return STRSAFE_E_INSUFFICIENT_BUFFER; + } + + ptr = output; + memcpy(ptr, uri->canon_uri+uri->scheme_start, uri->scheme_len*sizeof(WCHAR)); + + /* Add the "://". */ + ptr += uri->scheme_len; + memcpy(ptr, colon_slashesW, sizeof(colon_slashesW)); + + /* Add the authority. */ + ptr += sizeof(colon_slashesW)/sizeof(WCHAR); + memcpy(ptr, uri->canon_uri+uri->authority_start, uri->authority_len*sizeof(WCHAR)); + + /* Add the '/' after the authority. */ + ptr += uri->authority_len; + *ptr = '/'; + ptr[1] = 0; + + *result_len = len; + return S_OK; +} + +static HRESULT parse_document(const Uri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + DWORD len = 0; + + /* It has to be a known scheme type, but, it can't be a file + * scheme. It also has to hierarchical. + */ + if(uri->scheme_type == URL_SCHEME_UNKNOWN || + uri->scheme_type == URL_SCHEME_FILE || + uri->authority_start == -1) { + *result_len = 0; + if(output_len < 1) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + output[0] = 0; + return S_OK; + } + + if(uri->fragment_start > -1) + len = uri->fragment_start; + else + len = uri->canon_len; + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + memcpy(output, uri->canon_uri, len*sizeof(WCHAR)); + output[len] = 0; + return S_OK; +} + +static HRESULT parse_path_from_url(const Uri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + const WCHAR *path_ptr; + WCHAR buffer[INTERNET_MAX_URL_LENGTH+1]; + WCHAR *ptr; + + if(uri->scheme_type != URL_SCHEME_FILE) { + *result_len = 0; + if(output_len > 0) + output[0] = 0; + return E_INVALIDARG; + } + + ptr = buffer; + if(uri->host_start > -1) { + static const WCHAR slash_slashW[] = {'\\','\\'}; + + memcpy(ptr, slash_slashW, sizeof(slash_slashW)); + ptr += sizeof(slash_slashW)/sizeof(WCHAR); + memcpy(ptr, uri->canon_uri+uri->host_start, uri->host_len*sizeof(WCHAR)); + ptr += uri->host_len; + } + + path_ptr = uri->canon_uri+uri->path_start; + if(uri->path_len > 3 && *path_ptr == '/' && is_drive_path(path_ptr+1)) + /* Skip past the '/' in front of the drive path. */ + ++path_ptr; + + for(; path_ptr < uri->canon_uri+uri->path_start+uri->path_len; ++path_ptr, ++ptr) { + BOOL do_default_action = TRUE; + + if(*path_ptr == '%') { + const WCHAR decoded = decode_pct_val(path_ptr); + if(decoded) { + *ptr = decoded; + path_ptr += 2; + do_default_action = FALSE; + } + } else if(*path_ptr == '/') { + *ptr = '\\'; + do_default_action = FALSE; + } + + if(do_default_action) + *ptr = *path_ptr; + } + + *ptr = 0; + + *result_len = ptr-buffer; + if(*result_len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + memcpy(output, buffer, (*result_len+1)*sizeof(WCHAR)); + return S_OK; +} + +static HRESULT parse_url_from_path(IUri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + HRESULT hr; + BSTR received; + DWORD len = 0; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_ABSOLUTE_URI, &len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetAbsoluteUri(uri, &received); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, received, (len+1)*sizeof(WCHAR)); + SysFreeString(received); + + return S_OK; +} + +static HRESULT parse_schema(IUri *uri, LPWSTR output, DWORD output_len, + DWORD *result_len) +{ + HRESULT hr; + DWORD len; + BSTR received; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_SCHEME_NAME, &len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetSchemeName(uri, &received); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, received, (len+1)*sizeof(WCHAR)); + SysFreeString(received); + + return S_OK; +} + +static HRESULT parse_site(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len) +{ + HRESULT hr; + DWORD len; + BSTR received; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_HOST, &len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetHost(uri, &received); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, received, (len+1)*sizeof(WCHAR)); + SysFreeString(received); + + return S_OK; +} + +static HRESULT parse_domain(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len) +{ + HRESULT hr; + DWORD len; + BSTR received; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DOMAIN, &len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetDomain(uri, &received); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, received, (len+1)*sizeof(WCHAR)); + SysFreeString(received); + + return S_OK; +} + +static HRESULT parse_anchor(IUri *uri, LPWSTR output, DWORD output_len, DWORD *result_len) +{ + HRESULT hr; + DWORD len; + BSTR received; + + hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_FRAGMENT, &len, 0); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + *result_len = len; + if(len+1 > output_len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + hr = IUri_GetFragment(uri, &received); + if(FAILED(hr)) { + *result_len = 0; + return hr; + } + + memcpy(output, received, (len+1)*sizeof(WCHAR)); + SysFreeString(received); + + return S_OK; +} + +/*********************************************************************** + * CoInternetParseIUri (urlmon.@) + */ +HRESULT WINAPI CoInternetParseIUri(IUri *pIUri, PARSEACTION ParseAction, DWORD dwFlags, + LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, + DWORD_PTR dwReserved) +{ + HRESULT hr; + Uri *uri; + IInternetProtocolInfo *info; + + TRACE("(%p %d %x %p %d %p %x)\n", pIUri, ParseAction, dwFlags, pwzResult, + cchResult, pcchResult, (DWORD)dwReserved); + + if(!pcchResult) + return E_POINTER; + + if(!pwzResult || !pIUri) { + *pcchResult = 0; + return E_INVALIDARG; + } + + if(!(uri = get_uri_obj(pIUri))) { + *pcchResult = 0; + FIXME("(%p %d %x %p %d %p %x) Unknown IUri's not supported for this action.\n", + pIUri, ParseAction, dwFlags, pwzResult, cchResult, pcchResult, (DWORD)dwReserved); + return E_NOTIMPL; + } + + info = get_protocol_info(uri->canon_uri); + if(info) { + hr = IInternetProtocolInfo_ParseUrl(info, uri->canon_uri, ParseAction, dwFlags, + pwzResult, cchResult, pcchResult, 0); + IInternetProtocolInfo_Release(info); + if(SUCCEEDED(hr)) return hr; + } + + switch(ParseAction) { + case PARSE_CANONICALIZE: + hr = parse_canonicalize(uri, dwFlags, pwzResult, cchResult, pcchResult); + break; + case PARSE_FRIENDLY: + hr = parse_friendly(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_ROOTDOCUMENT: + hr = parse_rootdocument(uri, pwzResult, cchResult, pcchResult); + break; + case PARSE_DOCUMENT: + hr = parse_document(uri, pwzResult, cchResult, pcchResult); + break; + case PARSE_PATH_FROM_URL: + hr = parse_path_from_url(uri, pwzResult, cchResult, pcchResult); + break; + case PARSE_URL_FROM_PATH: + hr = parse_url_from_path(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_SCHEMA: + hr = parse_schema(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_SITE: + hr = parse_site(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_DOMAIN: + hr = parse_domain(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_LOCATION: + case PARSE_ANCHOR: + hr = parse_anchor(pIUri, pwzResult, cchResult, pcchResult); + break; + case PARSE_SECURITY_URL: + case PARSE_MIME: + case PARSE_SERVER: + case PARSE_SECURITY_DOMAIN: + *pcchResult = 0; + hr = E_FAIL; + break; + default: + *pcchResult = 0; + hr = E_NOTIMPL; + FIXME("(%p %d %x %p %d %p %x) Partial stub.\n", pIUri, ParseAction, dwFlags, + pwzResult, cchResult, pcchResult, (DWORD)dwReserved); + } + + return hr; +} diff --git a/reactos/dll/win32/urlmon/urlmon.spec b/reactos/dll/win32/urlmon/urlmon.spec index 61093850d24..9d3de3a61dc 100644 --- a/reactos/dll/win32/urlmon/urlmon.spec +++ b/reactos/dll/win32/urlmon/urlmon.spec @@ -11,7 +11,9 @@ @ stdcall CoGetClassObjectFromURL(ptr wstr long long wstr ptr long ptr ptr ptr) @ stub CoInstall @ stdcall CoInternetCombineUrl(wstr wstr long wstr long ptr long) +@ stdcall CoInternetCombineUrlEx(ptr wstr long ptr long) @ stdcall CoInternetCompareUrl(wstr wstr long) +@ stdcall CoInternetCombineIUri(ptr ptr long ptr long) @ stdcall CoInternetCreateSecurityManager(ptr ptr long) @ stdcall CoInternetCreateZoneManager(ptr ptr long) @ stub CoInternetGetProtocolFlags @@ -19,6 +21,7 @@ @ stdcall CoInternetGetSession(long ptr long) @ stdcall CoInternetIsFeatureEnabled(long long) @ stdcall CoInternetParseUrl(wstr long long wstr long ptr long) +@ stdcall CoInternetParseIUri(ptr long long wstr long ptr long) @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) @ stdcall CoInternetSetFeatureEnabled(long long long) @ stub CompareSecurityIds diff --git a/reactos/dll/win32/urlmon/urlmon_main.c b/reactos/dll/win32/urlmon/urlmon_main.c index edaad42289f..6ecd1dec954 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.c +++ b/reactos/dll/win32/urlmon/urlmon_main.c @@ -636,6 +636,127 @@ static BOOL application_octet_stream_filter(const BYTE *b, DWORD size) return TRUE; } +static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime) +{ + LPCWSTR ret = NULL; + DWORD len, i; + + static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0}; + static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0}; + static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0}; + static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0}; + static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0}; + static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0}; + static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0}; + static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0}; + static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0}; + static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0}; + static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0}; + static const WCHAR app_postscriptW[] = + {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0}; + static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0}; + static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', + 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; + static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', + 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; + static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', + 'j','a','v','a',0}; + static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', + 'x','-','m','s','d','o','w','n','l','o','a','d',0}; + static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'}; + static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', + 'o','c','t','e','t','-','s','t','r','e','a','m','\0'}; + + static const struct { + LPCWSTR mime; + BOOL (*filter)(const BYTE *,DWORD); + } mime_filters[] = { + {text_htmlW, text_html_filter}, + {text_richtextW, text_richtext_filter}, + /* {audio_xaiffW, audio_xaiff_filter}, */ + {audio_basicW, audio_basic_filter}, + {audio_wavW, audio_wav_filter}, + {image_gifW, image_gif_filter}, + {image_pjpegW, image_pjpeg_filter}, + {image_tiffW, image_tiff_filter}, + {image_xpngW, image_xpng_filter}, + /* {image_xbitmapW, image_xbitmap_filter}, */ + {image_bmpW, image_bmp_filter}, + /* {image_xjgW, image_xjg_filter}, */ + /* {image_xemfW, image_xemf_filter}, */ + /* {image_xwmfW, image_xwmf_filter}, */ + {video_aviW, video_avi_filter}, + {video_mpegW, video_mpeg_filter}, + {app_postscriptW, application_postscript_filter}, + /* {app_base64W, application_base64_filter}, */ + /* {app_macbinhex40W, application_macbinhex40_filter}, */ + {app_pdfW, application_pdf_filter}, + /* {app_zcompressedW, application_xcompressed_filter}, */ + {app_xzipW, application_xzip_filter}, + {app_xgzipW, application_xgzip_filter}, + {app_javaW, application_java_filter}, + {app_xmsdownloadW, application_xmsdownload}, + {text_plainW, text_plain_filter}, + {app_octetstreamW, application_octet_stream_filter} + }; + + if(!buf || !size) { + if(!proposed_mime) + return E_FAIL; + + len = strlenW(proposed_mime)+1; + *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); + if(!*ret_mime) + return E_OUTOFMEMORY; + + memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR)); + return S_OK; + } + + if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) { + for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) { + if(!strcmpW(proposed_mime, mime_filters[i].mime)) + break; + } + + if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) { + len = strlenW(proposed_mime)+1; + *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); + if(!*ret_mime) + return E_OUTOFMEMORY; + + memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR)); + return S_OK; + } + } + + i=0; + while(!ret) { + if(mime_filters[i].filter(buf, size)) + ret = mime_filters[i].mime; + i++; + } + + TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size))); + + if(proposed_mime) { + if(i == sizeof(mime_filters)/sizeof(*mime_filters)) + ret = proposed_mime; + + /* text/html is a special case */ + if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW)) + ret = text_htmlW; + } + + len = strlenW(ret)+1; + *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); + if(!*ret_mime) + return E_OUTOFMEMORY; + + memcpy(*ret_mime, ret, len*sizeof(WCHAR)); + return S_OK; +} + /*********************************************************************** * FindMimeFromData (URLMON.@) * @@ -658,128 +779,8 @@ HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, if(!ppwzMimeOut || (!pwzUrl && !pBuffer)) return E_INVALIDARG; - if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) { - DWORD len; - - if(!pwzMimeProposed) - return E_FAIL; - - len = strlenW(pwzMimeProposed)+1; - *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); - memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR)); - return S_OK; - } - - if(pBuffer) { - const BYTE *buf = pBuffer; - DWORD len; - LPCWSTR ret = NULL; - unsigned int i; - - static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0}; - static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0}; - static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0}; - static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0}; - static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0}; - static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0}; - static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0}; - static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0}; - static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0}; - static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0}; - static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0}; - static const WCHAR wszAppPostscript[] = - {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0}; - static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'p','d','f',0}; - static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; - static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; - static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'j','a','v','a',0}; - static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'x','-','m','s','d','o','w','n','l','o','a','d',0}; - static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'}; - static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/', - 'o','c','t','e','t','-','s','t','r','e','a','m','\0'}; - - static const struct { - LPCWSTR mime; - BOOL (*filter)(const BYTE *,DWORD); - } mime_filters[] = { - {wszTextHtml, text_html_filter}, - {wszTextRichtext, text_richtext_filter}, - /* {wszAudioXAiff, audio_xaiff_filter}, */ - {wszAudioBasic, audio_basic_filter}, - {wszAudioWav, audio_wav_filter}, - {wszImageGif, image_gif_filter}, - {wszImagePjpeg, image_pjpeg_filter}, - {wszImageTiff, image_tiff_filter}, - {wszImageXPng, image_xpng_filter}, - /* {wszImageXBitmap, image_xbitmap_filter}, */ - {wszImageBmp, image_bmp_filter}, - /* {wszImageXJg, image_xjg_filter}, */ - /* {wszImageXEmf, image_xemf_filter}, */ - /* {wszImageXWmf, image_xwmf_filter}, */ - {wszVideoAvi, video_avi_filter}, - {wszVideoMpeg, video_mpeg_filter}, - {wszAppPostscript, application_postscript_filter}, - /* {wszAppBase64, application_base64_filter}, */ - /* {wszAppMacbinhex40, application_macbinhex40_filter}, */ - {wszAppPdf, application_pdf_filter}, - /* {wszAppXCompressed, application_xcompressed_filter}, */ - {wszAppXZip, application_xzip_filter}, - {wszAppXGzip, application_xgzip_filter}, - {wszAppJava, application_java_filter}, - {wszAppXMSDownload, application_xmsdownload}, - {wszTextPlain, text_plain_filter}, - {wszAppOctetStream, application_octet_stream_filter} - }; - - if(!cbSize) - return E_FAIL; - - if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) { - for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) { - if(!strcmpW(pwzMimeProposed, mime_filters[i].mime)) - break; - } - - if(i == sizeof(mime_filters)/sizeof(*mime_filters) - || mime_filters[i].filter(buf, cbSize)) { - len = strlenW(pwzMimeProposed)+1; - *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); - memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR)); - return S_OK; - } - } - - i=0; - while(!ret) { - if(mime_filters[i].filter(buf, cbSize)) - ret = mime_filters[i].mime; - i++; - } - - TRACE("found %s for data\n" - "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7], - buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]); - - if(pwzMimeProposed) { - if(i == sizeof(mime_filters)/sizeof(*mime_filters)) - ret = pwzMimeProposed; - - /* text/html is a special case */ - if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain)) - ret = wszTextHtml; - } - - len = strlenW(ret)+1; - *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR)); - memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR)); - return S_OK; - } + if(pwzMimeProposed || pBuffer) + return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut); if(pwzUrl) { HKEY hkey; diff --git a/reactos/dll/win32/urlmon/urlmon_main.h b/reactos/dll/win32/urlmon/urlmon_main.h index 3aada09ce60..ea33f152bae 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.h +++ b/reactos/dll/win32/urlmon/urlmon_main.h @@ -66,7 +66,7 @@ static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_ref #define DEFINE_THIS(cls,ifc,iface) DEFINE_THIS2(cls,lp ## ifc ## Vtbl,iface) IInternetProtocolInfo *get_protocol_info(LPCWSTR); -HRESULT get_protocol_handler(LPCWSTR,CLSID*,BOOL*,IClassFactory**); +HRESULT get_protocol_handler(IUri*,CLSID*,BOOL*,IClassFactory**); IInternetProtocol *get_mime_filter(LPCWSTR); BOOL is_registered_protocol(LPCWSTR); void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL); @@ -74,12 +74,14 @@ HINTERNET get_internet_session(IInternetBindInfo*); LPWSTR get_useragent(void); void free_session(void); -HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv); -HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv); +HRESULT bind_to_storage(IUri*,IBindCtx*,REFIID,void**); +HRESULT bind_to_object(IMoniker*,IUri*,IBindCtx*,REFIID,void**ppv); -HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol); -void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info); -IWinInetInfo *get_wininet_info(IInternetProtocol*); +HRESULT create_binding_protocol(BOOL,IInternetProtocolEx**); +void set_binding_sink(IInternetProtocolEx*,IInternetProtocolSink*,IInternetBindInfo*); +IWinInetInfo *get_wininet_info(IInternetProtocolEx*); +HRESULT create_default_callback(IBindStatusCallback**); +HRESULT wrap_callback(IBindStatusCallback*,IBindStatusCallback**); typedef struct ProtocolVtbl ProtocolVtbl; @@ -101,11 +103,14 @@ typedef struct { ULONG content_length; ULONG available_bytes; + IStream *post_stream; + LONG priority; } Protocol; struct ProtocolVtbl { HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*); + HRESULT (*end_request)(Protocol*); HRESULT (*start_downloading)(Protocol*); void (*close_connection)(Protocol*); }; @@ -115,6 +120,7 @@ HRESULT protocol_continue(Protocol*,PROTOCOLDATA*); HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*); HRESULT protocol_lock_request(Protocol*); HRESULT protocol_unlock_request(Protocol*); +HRESULT protocol_abort(Protocol*,HRESULT); void protocol_close_connection(Protocol*); typedef struct {