From eefe82711d7160a2a815a42d7f8e0e864080b936 Mon Sep 17 00:00:00 2001 From: The Wine Synchronizer Date: Fri, 4 Apr 2008 14:41:46 +0000 Subject: [PATCH] Autosyncing with Wine HEAD svn path=/trunk/; revision=32859 --- reactos/dll/win32/urlmon/binding.c | 405 ++++++++++++++++++------ reactos/dll/win32/urlmon/download.c | 406 +++++++++++++++++++++++++ reactos/dll/win32/urlmon/file.c | 6 +- reactos/dll/win32/urlmon/http.c | 19 +- reactos/dll/win32/urlmon/mk.c | 1 - reactos/dll/win32/urlmon/regsvr.c | 4 +- reactos/dll/win32/urlmon/sec_mgr.c | 370 +++++++++++++--------- reactos/dll/win32/urlmon/session.c | 181 +++++++---- reactos/dll/win32/urlmon/umon.c | 238 ++------------- reactos/dll/win32/urlmon/umstream.c | 2 +- reactos/dll/win32/urlmon/urlmon.rbuild | 19 +- reactos/dll/win32/urlmon/urlmon.spec | 4 +- reactos/dll/win32/urlmon/urlmon_main.c | 82 +++-- reactos/dll/win32/urlmon/urlmon_main.h | 15 + 14 files changed, 1200 insertions(+), 552 deletions(-) create mode 100644 reactos/dll/win32/urlmon/download.c diff --git a/reactos/dll/win32/urlmon/binding.c b/reactos/dll/win32/urlmon/binding.c index 66b5bdfd66b..47b521c68b0 100644 --- a/reactos/dll/win32/urlmon/binding.c +++ b/reactos/dll/win32/urlmon/binding.c @@ -38,17 +38,33 @@ typedef struct _task_header_t { } task_header_t; typedef struct { - const IStreamVtbl *lpStreamVtbl; + const IUnknownVtbl *lpUnknownVtbl; LONG ref; IInternetProtocol *protocol; BYTE buf[1024*8]; - DWORD buf_size; - BOOL init_buf; + DWORD size; + BOOL init; HRESULT hres; -} ProtocolStream; + + LPWSTR cache_file; +} stgmed_buf_t; + +typedef struct _stgmed_obj_t stgmed_obj_t; + +typedef struct { + void (*release)(stgmed_obj_t*); + HRESULT (*fill_stgmed)(stgmed_obj_t*,STGMEDIUM*); + void *(*get_result)(stgmed_obj_t*); +} stgmed_obj_vtbl; + +struct _stgmed_obj_t { + const stgmed_obj_vtbl *vtbl; +}; + +#define STGMEDUNK(x) ((IUnknown*) &(x)->lpUnknownVtbl) typedef enum { BEFORE_DOWNLOAD, @@ -71,7 +87,9 @@ struct Binding { IBindStatusCallback *callback; IInternetProtocol *protocol; IServiceProvider *service_provider; - ProtocolStream *stream; + + stgmed_buf_t *stgmed_buf; + stgmed_obj_t *stgmed_obj; BINDINFO bindinfo; DWORD bindf; @@ -92,8 +110,6 @@ struct Binding { DWORD apartment_thread; HWND notif_hwnd; - STGMEDIUM stgmed; - task_header_t *task_queue_head, *task_queue_tail; CRITICAL_SECTION section; }; @@ -143,18 +159,18 @@ static task_header_t *pop_task(Binding *binding) return ret; } -static void fill_stream_buffer(ProtocolStream *This) +static void fill_stgmed_buffer(stgmed_buf_t *buf) { DWORD read = 0; - if(sizeof(This->buf) == This->buf_size) + if(sizeof(buf->buf) == buf->size) return; - This->hres = IInternetProtocol_Read(This->protocol, This->buf+This->buf_size, - sizeof(This->buf)-This->buf_size, &read); - This->buf_size += read; + buf->hres = IInternetProtocol_Read(buf->protocol, buf->buf+buf->size, + sizeof(buf->buf)-buf->size, &read); + buf->size += read; if(read > 0) - This->init_buf = TRUE; + buf->init = TRUE; } static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -281,9 +297,9 @@ static void handle_mime_available(Binding *binding, BOOL verify) if(verify) { LPWSTR mime = NULL; - fill_stream_buffer(binding->stream); - FindMimeFromData(NULL, binding->url, binding->stream->buf, - min(binding->stream->buf_size, 255), binding->mime, 0, &mime, 0); + fill_stgmed_buffer(binding->stgmed_buf); + FindMimeFromData(NULL, binding->url, binding->stgmed_buf->buf, + min(binding->stgmed_buf->size, 255), binding->mime, 0, &mime, 0); heap_free(binding->mime); binding->mime = heap_strdupW(mime); @@ -404,31 +420,17 @@ static void load_doc_mon(Binding *binding, IPersistMoniker *persist) FIXME("Load failed: %08x\n", hres); } -static void create_object(Binding *binding) +static HRESULT create_mime_object(Binding *binding, const CLSID *clsid, LPCWSTR clsid_str) { IPersistMoniker *persist; - LPWSTR clsid_str; - CLSID clsid; HRESULT hres; - if(!binding->mime) { - FIXME("MIME unavailable\n"); - return; - } - - if(!(clsid_str = get_mime_clsid(binding->mime, &clsid))) { - FIXME("Could not find object for MIME %s\n", debugstr_w(binding->mime)); - return; - } - - IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_CLASSIDAVAILABLE, clsid_str); - - IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_BEGINSYNCOPERATION, NULL); - - hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &binding->iid, (void**)&binding->obj); - if(FAILED(hres)) - FIXME("CoCreateInstance failed: %08x\n", hres); + if(FAILED(hres)) { + WARN("CoCreateInstance failed: %08x\n", hres); + return INET_E_CANNOT_INSTANTIATE_OBJECT; + } binding->state |= BINDING_OBJAVAIL; @@ -451,15 +453,124 @@ static void create_object(Binding *binding) /* FIXME: Try query IPersistFile */ } - heap_free(clsid_str); - IBindStatusCallback_OnObjectAvailable(binding->callback, &binding->iid, binding->obj); + return S_OK; +} + +static void create_object(Binding *binding) +{ + LPWSTR clsid_str; + CLSID clsid; + HRESULT hres; + + if(!binding->mime) { + FIXME("MIME not available\n"); + return; + } + + if(!(clsid_str = get_mime_clsid(binding->mime, &clsid))) { + FIXME("Could not find object for MIME %s\n", debugstr_w(binding->mime)); + return; + } + + IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_CLASSIDAVAILABLE, clsid_str); + IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_BEGINSYNCOPERATION, NULL); + + hres = create_mime_object(binding, &clsid, clsid_str); + heap_free(clsid_str); + IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_ENDSYNCOPERATION, NULL); - stop_binding(binding, S_OK, NULL); + stop_binding(binding, hres, NULL); + if(FAILED(hres)) + IInternetProtocol_Terminate(binding->protocol, 0); } +#define STGMEDUNK_THIS(iface) DEFINE_THIS(stgmed_buf_t, Unknown, iface) + +static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + + *ppv = NULL; + + if(IsEqualGUID(riid, &IID_IUnknown)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + + *ppv = STGMEDUNK(This); + IUnknown_AddRef(STGMEDUNK(This)); + return S_OK; + } + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI StgMedUnk_Release(IUnknown *iface) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + IInternetProtocol_Release(This->protocol); + heap_free(This->cache_file); + heap_free(This); + + URLMON_UnlockModule(); + } + + return ref; +} + +#undef STGMEDUNK_THIS + +static const IUnknownVtbl StgMedUnkVtbl = { + StgMedUnk_QueryInterface, + StgMedUnk_AddRef, + StgMedUnk_Release +}; + +static stgmed_buf_t *create_stgmed_buf(IInternetProtocol *protocol) +{ + stgmed_buf_t *ret = heap_alloc(sizeof(*ret)); + + ret->lpUnknownVtbl = &StgMedUnkVtbl; + ret->ref = 1; + ret->size = 0; + ret->init = FALSE; + ret->hres = S_OK; + ret->cache_file = NULL; + + IInternetProtocol_AddRef(protocol); + ret->protocol = protocol; + + URLMON_LockModule(); + + return ret; +} + +typedef struct { + stgmed_obj_t stgmed_obj; + const IStreamVtbl *lpStreamVtbl; + + LONG ref; + + stgmed_buf_t *buf; +} ProtocolStream; + #define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface) static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface, @@ -507,7 +618,7 @@ static ULONG WINAPI ProtocolStream_Release(IStream *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - IInternetProtocol_Release(This->protocol); + IUnknown_Release(STGMEDUNK(This->buf)); heap_free(This); URLMON_UnlockModule(); @@ -517,24 +628,25 @@ static ULONG WINAPI ProtocolStream_Release(IStream *iface) } static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv, - ULONG cb, ULONG *pcbRead) + ULONG cb, ULONG *pcbRead) { ProtocolStream *This = STREAM_THIS(iface); DWORD read = 0, pread = 0; + HRESULT hres; TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead); - if(This->buf_size) { + if(This->buf->size) { read = cb; - if(read > This->buf_size) - read = This->buf_size; + if(read > This->buf->size) + read = This->buf->size; - memcpy(pv, This->buf, read); + memcpy(pv, This->buf->buf, read); - if(read < This->buf_size) - memmove(This->buf, This->buf+read, This->buf_size-read); - This->buf_size -= read; + if(read < This->buf->size) + memmove(This->buf->buf, This->buf->buf+read, This->buf->size-read); + This->buf->size -= read; } if(read == cb) { @@ -543,14 +655,14 @@ static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv, return S_OK; } - This->hres = IInternetProtocol_Read(This->protocol, (PBYTE)pv+read, cb-read, &pread); + hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv+read, cb-read, &pread); if (pcbRead) *pcbRead = read + pread; - if(This->hres == E_PENDING) + if(hres == E_PENDING) return E_PENDING; - else if(FAILED(This->hres)) - FIXME("Read failed: %08x\n", This->hres); + else if(FAILED(hres)) + FIXME("Read failed: %08x\n", hres); return read || pread ? S_OK : S_FALSE; } @@ -656,26 +768,118 @@ static const IStreamVtbl ProtocolStreamVtbl = { ProtocolStream_Clone }; -#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface) +static void stgmed_stream_release(stgmed_obj_t *obj) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + IStream_Release(STREAM(stream)); +} -static ProtocolStream *create_stream(IInternetProtocol *protocol) +static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + + stgmed->tymed = TYMED_ISTREAM; + stgmed->u.pstm = STREAM(stream); + stgmed->pUnkForRelease = STGMEDUNK(stream->buf); + + return S_OK; +} + +static void *stgmed_stream_get_result(stgmed_obj_t *obj) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + + IStream_AddRef(STREAM(stream)); + return STREAM(stream); +} + +static const stgmed_obj_vtbl stgmed_stream_vtbl = { + stgmed_stream_release, + stgmed_stream_fill_stgmed, + stgmed_stream_get_result +}; + +typedef struct { + stgmed_obj_t stgmed_obj; + stgmed_buf_t *buf; +} stgmed_file_obj_t; + +static stgmed_obj_t *create_stgmed_stream(stgmed_buf_t *buf) { ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream)); + ret->stgmed_obj.vtbl = &stgmed_stream_vtbl; ret->lpStreamVtbl = &ProtocolStreamVtbl; ret->ref = 1; - ret->buf_size = 0; - ret->init_buf = FALSE; - ret->hres = S_OK; - IInternetProtocol_AddRef(protocol); - ret->protocol = protocol; + IUnknown_AddRef(STGMEDUNK(buf)); + ret->buf = buf; URLMON_LockModule(); - return ret; + return &ret->stgmed_obj; } +static void stgmed_file_release(stgmed_obj_t *obj) +{ + stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; + + IUnknown_Release(STGMEDUNK(file_obj->buf)); + heap_free(file_obj); +} + +static HRESULT stgmed_file_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) +{ + stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; + + if(!file_obj->buf->cache_file) { + WARN("cache_file not set\n"); + return INET_E_DATA_NOT_AVAILABLE; + } + + fill_stgmed_buffer(file_obj->buf); + if(file_obj->buf->size == sizeof(file_obj->buf->buf)) { + BYTE buf[1024]; + DWORD read; + HRESULT hres; + + do { + hres = IInternetProtocol_Read(file_obj->buf->protocol, buf, sizeof(buf), &read); + }while(hres == S_OK); + } + + stgmed->tymed = TYMED_FILE; + stgmed->u.lpszFileName = file_obj->buf->cache_file; + stgmed->pUnkForRelease = STGMEDUNK(file_obj->buf); + + return S_OK; +} + +static void *stgmed_file_get_result(stgmed_obj_t *obj) +{ + return NULL; +} + +static const stgmed_obj_vtbl stgmed_file_vtbl = { + stgmed_file_release, + stgmed_file_fill_stgmed, + stgmed_file_get_result +}; + +static stgmed_obj_t *create_stgmed_file(stgmed_buf_t *buf) +{ + stgmed_file_obj_t *ret = heap_alloc(sizeof(*ret)); + + ret->stgmed_obj.vtbl = &stgmed_file_vtbl; + + IUnknown_AddRef(STGMEDUNK(buf)); + ret->buf = buf; + + return &ret->stgmed_obj; +} + +#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface) + static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv) { Binding *This = BINDING_THIS(iface); @@ -736,8 +940,10 @@ static ULONG WINAPI Binding_Release(IBinding *iface) IInternetProtocol_Release(This->protocol); if(This->service_provider) IServiceProvider_Release(This->service_provider); - if(This->stream) - IStream_Release(STREAM(This->stream)); + if(This->stgmed_buf) + IUnknown_Release(STGMEDUNK(This->stgmed_buf)); + if(This->stgmed_obj) + This->stgmed_obj->vtbl->release(This->stgmed_obj); if(This->obj) IUnknown_Release(This->obj); if(This->bctx) @@ -877,7 +1083,7 @@ static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface, TRACE("(%p)->(%p)\n", This, pProtocolData); task = heap_alloc(sizeof(switch_task_t)); - memcpy(&task->data, pProtocolData, sizeof(PROTOCOLDATA)); + task->data = *pProtocolData; push_task(This, &task->header, switch_proc); @@ -957,7 +1163,7 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink on_progress(This, 0, 0, BINDSTATUS_CONNECTING, szStatusText); break; case BINDSTATUS_BEGINDOWNLOADDATA: - fill_stream_buffer(This->stream); + fill_stgmed_buffer(This->stgmed_buf); break; case BINDSTATUS_MIMETYPEAVAILABLE: set_binding_mime(This, szStatusText); @@ -971,6 +1177,8 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink mime_available(This, szStatusText, FALSE); break; case BINDSTATUS_CACHEFILENAMEAVAILABLE: + heap_free(This->stgmed_buf->cache_file); + This->stgmed_buf->cache_file = heap_strdupW(szStatusText); break; case BINDSTATUS_DIRECTBIND: This->report_mime = FALSE; @@ -1000,15 +1208,19 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres mime_available(This, NULL, TRUE); if(This->download_state == BEFORE_DOWNLOAD) { - fill_stream_buffer(This->stream); + fill_stgmed_buffer(This->stgmed_buf); This->download_state = DOWNLOADING; sent_begindownloaddata = TRUE; IBindStatusCallback_OnProgress(This->callback, progress, progress_max, BINDSTATUS_BEGINDOWNLOADDATA, This->url); + + if(This->stgmed_buf->cache_file) + IBindStatusCallback_OnProgress(This->callback, progress, progress_max, + BINDSTATUS_CACHEFILENAMEAVAILABLE, This->stgmed_buf->cache_file); } - if(This->stream->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) { + if(This->stgmed_buf->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) { This->download_state = END_DOWNLOAD; IBindStatusCallback_OnProgress(This->callback, progress, progress_max, BINDSTATUS_ENDDOWNLOADDATA, This->url); @@ -1021,15 +1233,26 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres if(!(This->state & BINDING_OBJAVAIL)) create_object(This); }else { + STGMEDIUM stgmed; + HRESULT hres; + if(!(This->state & BINDING_LOCKED)) { HRESULT hres = IInternetProtocol_LockRequest(This->protocol, 0); if(SUCCEEDED(hres)) This->state |= BINDING_LOCKED; } + hres = This->stgmed_obj->vtbl->fill_stgmed(This->stgmed_obj, &stgmed); + if(FAILED(hres)) { + stop_binding(This, hres, NULL); + return; + } + + formatetc.tymed = stgmed.tymed; formatetc.cfFormat = This->clipboard_format; + IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress, - &formatetc, &This->stgmed); + &formatetc, &stgmed); if(This->download_state == END_DOWNLOAD) stop_binding(This, S_OK, NULL); @@ -1159,7 +1382,7 @@ static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface, *grfBINDF = This->bindf; - memcpy(pbindinfo, &This->bindinfo, sizeof(BINDINFO)); + *pbindinfo = This->bindinfo; if(pbindinfo->szExtraInfo || pbindinfo->szCustomVerb) FIXME("copy strings\n"); @@ -1283,7 +1506,7 @@ static HRESULT get_callback(IBindCtx *pbc, IBindStatusCallback **callback) IUnknown_Release(unk); } - return SUCCEEDED(hres) ? S_OK : MK_E_SYNTAX; + return SUCCEEDED(hres) ? S_OK : INET_E_DATA_NOT_AVAILABLE; } static BOOL is_urlmon_protocol(LPCWSTR url) @@ -1326,11 +1549,6 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, Binding *ret; HRESULT hres; - if(!to_obj && !IsEqualGUID(&IID_IStream, riid)) { - FIXME("Unsupported riid %s\n", debugstr_guid(riid)); - return E_NOTIMPL; - } - URLMON_LockModule(); ret = heap_alloc_zero(sizeof(Binding)); @@ -1406,15 +1624,25 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, ret->url = heap_strdupW(url); if(binding_ctx) { - ret->stream = binding_ctx->stream; - IStream_AddRef(STREAM(ret->stream)); + ret->stgmed_buf = binding_ctx->stgmed_buf; + IUnknown_AddRef(STGMEDUNK(ret->stgmed_buf)); ret->clipboard_format = binding_ctx->clipboard_format; }else { - ret->stream = create_stream(ret->protocol); + ret->stgmed_buf = create_stgmed_buf(ret->protocol); + } + + if(to_obj) { + ret->stgmed_obj = NULL; + }else if(IsEqualGUID(&IID_IStream, riid)) { + ret->stgmed_obj = create_stgmed_stream(ret->stgmed_buf); + }else if(IsEqualGUID(&IID_IUnknown, riid)) { + ret->bindf |= BINDF_NEEDFILE; + ret->stgmed_obj = create_stgmed_file(ret->stgmed_buf); + }else { + FIXME("Unsupported riid %s\n", debugstr_guid(riid)); + IBinding_Release(BINDING(ret)); + return E_NOTIMPL; } - ret->stgmed.tymed = TYMED_ISTREAM; - ret->stgmed.u.pstm = STREAM(ret->stream); - ret->stgmed.pUnkForRelease = (IUnknown*)BINDING(ret); /* NOTE: Windows uses other IUnknown */ *binding = ret; return S_OK; @@ -1434,7 +1662,7 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I hres = IBindStatusCallback_OnStartBinding(binding->callback, 0, BINDING(binding)); if(FAILED(hres)) { WARN("OnStartBinding failed: %08x\n", hres); - stop_binding(binding, 0x800c0008, NULL); + stop_binding(binding, INET_E_DOWNLOAD_FAILURE, NULL); IBinding_Release(BINDING(binding)); return hres; } @@ -1448,7 +1676,7 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I TRACE("start ret %08x\n", hres); - if(FAILED(hres)) { + if(FAILED(hres) && hres != E_PENDING) { stop_binding(binding, hres, NULL); IBinding_Release(BINDING(binding)); @@ -1484,23 +1712,16 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) if(FAILED(hres)) return hres; - if(binding->hres != S_OK) { - hres = SUCCEEDED(binding->hres) ? S_OK : binding->hres; - }else if(binding->stream->init_buf) { + if(binding->hres == S_OK && binding->stgmed_buf->init) { if((binding->state & BINDING_STOPPED) && (binding->state & BINDING_LOCKED)) IInternetProtocol_UnlockRequest(binding->protocol); - IStream_AddRef(STREAM(binding->stream)); - *ppv = binding->stream; - - hres = S_OK; - }else { - hres = MK_S_ASYNCHRONOUS; + *ppv = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj); } IBinding_Release(BINDING(binding)); - return hres; + return *ppv ? S_OK : MK_S_ASYNCHRONOUS; } HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) diff --git a/reactos/dll/win32/urlmon/download.c b/reactos/dll/win32/urlmon/download.c new file mode 100644 index 00000000000..d81dffaedc4 --- /dev/null +++ b/reactos/dll/win32/urlmon/download.c @@ -0,0 +1,406 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "urlmon_main.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +typedef struct { + const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; + const IServiceProviderVtbl *lpServiceProviderVtbl; + + LONG ref; + + IBindStatusCallback *callback; + LPWSTR file_name; + LPWSTR cache_file; +} DownloadBSC; + +#define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl) +#define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl) + +#define STATUSCLB_THIS(iface) DEFINE_THIS(DownloadBSC, BindStatusCallback, iface) + +static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface, + REFIID riid, void **ppv) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); + *ppv = STATUSCLB(This); + }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { + TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); + *ppv = STATUSCLB(This); + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv); + *ppv = SERVPROV(This); + } + + if(*ppv) { + IBindStatusCallback_AddRef((IUnknown*)*ppv); + return S_OK; + } + + TRACE("Unsupported riid = %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref = %d\n", This, ref); + + return ref; +} + +static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref = %d\n", This, ref); + + if(!ref) { + if(This->callback) + IBindStatusCallback_Release(This->callback); + heap_free(This->file_name); + heap_free(This->cache_file); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface, + DWORD dwReserved, IBinding *pbind) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + + TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); + + if(This->callback) + IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind); + + return S_OK; +} + +static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%p)\n", This, pnPriority); + return E_NOTIMPL; +} + +static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD reserved) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%d)\n", This, reserved); + return E_NOTIMPL; +} + +static void on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text) +{ + HRESULT hres; + + if(!This->callback) + return; + + hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text); + if(FAILED(hres)) + FIXME("OnProgress failed: %08x\n", hres); +} + +static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, + ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + + TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, + debugstr_w(szStatusText)); + + switch(ulStatusCode) { + case BINDSTATUS_BEGINDOWNLOADDATA: + case BINDSTATUS_DOWNLOADINGDATA: + case BINDSTATUS_ENDDOWNLOADDATA: + case BINDSTATUS_SENDINGREQUEST: + case BINDSTATUS_MIMETYPEAVAILABLE: + on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText); + break; + + case BINDSTATUS_CACHEFILENAMEAVAILABLE: + on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText); + This->cache_file = heap_strdupW(szStatusText); + break; + + case BINDSTATUS_FINDINGRESOURCE: + case BINDSTATUS_CONNECTING: + break; + + default: + FIXME("Unsupported status %u\n", ulStatusCode); + } + + return S_OK; +} + +static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface, + HRESULT hresult, LPCWSTR szError) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + + TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); + + 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"); + } + + if(This->callback) + IBindStatusCallback_OnStopBinding(This->callback, hresult, szError); + + return S_OK; +} + +static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface, + DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + DWORD bindf = 0; + + TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); + + if(This->callback) { + BINDINFO bindinfo; + HRESULT hres; + + memset(&bindinfo, 0, sizeof(bindinfo)); + bindinfo.cbSize = sizeof(bindinfo); + + hres = IBindStatusCallback_GetBindInfo(This->callback, &bindf, &bindinfo); + if(SUCCEEDED(hres)) + ReleaseBindInfo(&bindinfo); + } + + *grfBINDF = BINDF_PULLDATA | BINDF_NEEDFILE | (bindf & BINDF_ENFORCERESTRICTED); + return S_OK; +} + +static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface, + DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) +{ + DownloadBSC *This = STATUSCLB_THIS(iface); + + TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); + + return S_OK; +} + +static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface, + REFIID riid, IUnknown *punk) +{ + DownloadBSC *This = STATUSCLB_THIS(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, + DownloadBSC_Release, + DownloadBSC_OnStartBinding, + DownloadBSC_GetPriority, + DownloadBSC_OnLowResource, + DownloadBSC_OnProgress, + DownloadBSC_OnStopBinding, + DownloadBSC_GetBindInfo, + DownloadBSC_OnDataAvailable, + 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); +} + +static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface) +{ + DownloadBSC *This = SERVPROV_THIS(iface); + return IBindStatusCallback_AddRef(STATUSCLB(This)); +} + +static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface) +{ + DownloadBSC *This = SERVPROV_THIS(iface); + return IBindStatusCallback_Release(STATUSCLB(This)); +} + +static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface, + REFGUID guidService, REFIID riid, void **ppv) +{ + DownloadBSC *This = SERVPROV_THIS(iface); + IServiceProvider *serv_prov; + HRESULT hres; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); + + if(!This->callback) + return E_NOINTERFACE; + + hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv); + if(SUCCEEDED(hres)) + return S_OK; + + hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IServiceProvider, (void**)&serv_prov); + if(SUCCEEDED(hres)) { + hres = IServiceProvider_QueryService(serv_prov, guidService, riid, ppv); + IServiceProvider_Release(serv_prov); + return hres; + } + + return E_NOINTERFACE; +} + +#undef SERVPROV_THIS + +static const IServiceProviderVtbl ServiceProviderVtbl = { + DwlServiceProvider_QueryInterface, + DwlServiceProvider_AddRef, + DwlServiceProvider_Release, + DwlServiceProvider_QueryService +}; + +static IBindStatusCallback *DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name) +{ + DownloadBSC *ret = heap_alloc(sizeof(*ret)); + + ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; + ret->lpServiceProviderVtbl = &ServiceProviderVtbl; + ret->ref = 1; + ret->file_name = heap_strdupW(file_name); + ret->cache_file = NULL; + + if(callback) + IBindStatusCallback_AddRef(callback); + ret->callback = callback; + + return STATUSCLB(ret); +} + +/*********************************************************************** + * URLDownloadToFileW (URLMON.@) + * + * Downloads URL szURL to file szFileName and call lpfnCB callback to + * report progress. + * + * PARAMS + * pCaller [I] controlling IUnknown interface. + * szURL [I] URL of the file to download + * szFileName [I] file name to store the content of the URL + * dwReserved [I] reserved - set to 0 + * lpfnCB [I] callback for progress report + * + * RETURNS + * S_OK on success + */ +HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFileName, + DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB) +{ + IBindStatusCallback *callback; + IUnknown *unk; + IMoniker *mon; + IBindCtx *bindctx; + HRESULT hres; + + TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_w(szURL), debugstr_w(szFileName), dwReserved, lpfnCB); + + if(pCaller) + FIXME("pCaller not supported\n"); + + callback = DownloadBSC_Create(lpfnCB, szFileName); + hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx); + IBindStatusCallback_Release(callback); + if(FAILED(hres)) + return hres; + + hres = CreateURLMoniker(NULL, szURL, &mon); + if(FAILED(hres)) { + IBindCtx_Release(bindctx); + return hres; + } + + hres = IMoniker_BindToStorage(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk); + IMoniker_Release(mon); + IBindCtx_Release(bindctx); + + if(unk) + IUnknown_Release(unk); + + return hres == MK_S_ASYNCHRONOUS ? S_OK : hres; +} + +/*********************************************************************** + * URLDownloadToFileA (URLMON.@) + * + * Downloads URL szURL to rile szFileName and call lpfnCB callback to + * report progress. + * + * PARAMS + * pCaller [I] controlling IUnknown interface. + * szURL [I] URL of the file to download + * szFileName [I] file name to store the content of the URL + * dwReserved [I] reserved - set to 0 + * lpfnCB [I] callback for progress report + * + * RETURNS + * S_OK on success + */ +HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, LPCSTR szURL, LPCSTR szFileName, DWORD dwReserved, + LPBINDSTATUSCALLBACK lpfnCB) +{ + LPWSTR urlW, file_nameW; + HRESULT hres; + + TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_a(szURL), debugstr_a(szFileName), dwReserved, lpfnCB); + + urlW = heap_strdupAtoW(szURL); + file_nameW = heap_strdupAtoW(szFileName); + + hres = URLDownloadToFileW(pCaller, urlW, file_nameW, dwReserved, lpfnCB); + + heap_free(urlW); + heap_free(file_nameW); + + return hres; +} diff --git a/reactos/dll/win32/urlmon/file.c b/reactos/dll/win32/urlmon/file.c index 41ee6176052..91aca2c780c 100644 --- a/reactos/dll/win32/urlmon/file.c +++ b/reactos/dll/win32/urlmon/file.c @@ -229,10 +229,14 @@ static HRESULT WINAPI FileProtocol_Read(IInternetProtocol *iface, void *pv, TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); + if (pcbRead) + *pcbRead = 0; + if(!This->file) return INET_E_DATA_NOT_AVAILABLE; - ReadFile(This->file, pv, cb, &read, NULL); + if (!ReadFile(This->file, pv, cb, &read, NULL)) + return INET_E_DOWNLOAD_FAILURE; if(pcbRead) *pcbRead = read; diff --git a/reactos/dll/win32/urlmon/http.c b/reactos/dll/win32/urlmon/http.c index 3056febf3e0..ede6f14b916 100644 --- a/reactos/dll/win32/urlmon/http.c +++ b/reactos/dll/win32/urlmon/http.c @@ -380,7 +380,7 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl if (!(user_agent = CoTaskMemAlloc((len)*sizeof(WCHAR)))) WARN("Out of memory\n"); else - MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len); } heap_free(user_agenta); } @@ -419,6 +419,8 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl if (This->grfBINDF & BINDF_NOWRITECACHE) request_flags |= INTERNET_FLAG_NO_CACHE_WRITE; + if (This->grfBINDF & BINDF_NEEDFILE) + request_flags |= INTERNET_FLAG_NEED_FILE; This->request = HttpOpenRequestW(This->connect, This->bind_info.dwBindVerb < BINDVERB_CUSTOM ? wszBindVerb[This->bind_info.dwBindVerb] : This->bind_info.szCustomVerb, @@ -656,6 +658,21 @@ static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDA This->content_length = atoiW(content_length); } + if(This->grfBINDF & BINDF_NEEDFILE) { + WCHAR cache_file[MAX_PATH]; + DWORD buflen = sizeof(cache_file); + + if(InternetQueryOptionW(This->request, INTERNET_OPTION_DATAFILE_NAME, + cache_file, &buflen)) + { + IInternetProtocolSink_ReportProgress(This->protocol_sink, + BINDSTATUS_CACHEFILENAMEAVAILABLE, + cache_file); + }else { + FIXME("Could not get cache file\n"); + } + } + This->flags |= FLAG_FIRST_CONTINUE_COMPLETE; } diff --git a/reactos/dll/win32/urlmon/mk.c b/reactos/dll/win32/urlmon/mk.c index 9476ec0c560..a7edd1bba6a 100644 --- a/reactos/dll/win32/urlmon/mk.c +++ b/reactos/dll/win32/urlmon/mk.c @@ -124,7 +124,6 @@ static HRESULT WINAPI MkProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, ReleaseBindInfo(&bindinfo); - IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL); IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, NULL); hres = FindMimeFromData(NULL, szUrl, NULL, 0, NULL, 0, &mime, 0); diff --git a/reactos/dll/win32/urlmon/regsvr.c b/reactos/dll/win32/urlmon/regsvr.c index 76e06ab7777..ece19158a23 100644 --- a/reactos/dll/win32/urlmon/regsvr.c +++ b/reactos/dll/win32/urlmon/regsvr.c @@ -522,7 +522,7 @@ static HRESULT register_inf(BOOL doregister) { HRESULT hres; HMODULE hAdvpack; - typeof(RegInstallA) *pRegInstall; + HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); STRTABLEA strtable; STRENTRYA pse[7]; static CLSID const *clsids[34]; @@ -550,7 +550,7 @@ static HRESULT register_inf(BOOL doregister) strtable.pse = pse; hAdvpack = LoadLibraryW(wszAdvpack); - pRegInstall = (typeof(RegInstallA)*)GetProcAddress(hAdvpack, "RegInstall"); + pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); hres = pRegInstall(URLMON_hInstance, doregister ? "RegisterDll" : "UnregisterDll", &strtable); diff --git a/reactos/dll/win32/urlmon/sec_mgr.c b/reactos/dll/win32/urlmon/sec_mgr.c index 0b56ba4e700..943b6dd7678 100644 --- a/reactos/dll/win32/urlmon/sec_mgr.c +++ b/reactos/dll/win32/urlmon/sec_mgr.c @@ -23,65 +23,27 @@ #include "urlmon_main.h" #include "winreg.h" +#include "wininet.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(urlmon); -/*********************************************************************** - * InternetSecurityManager implementation - * - */ -typedef struct { - const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl; +static const WCHAR fileW[] = {'f','i','l','e',0}; - LONG ref; - - IInternetSecurityMgrSite *mgrsite; - IInternetSecurityManager *custom_manager; -} SecManagerImpl; - -#define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface) - -static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone) +static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone) { - WCHAR schema[64]; - DWORD res, size=0; + DWORD res, size; HKEY hkey; - HRESULT hres; static const WCHAR wszZoneMapProtocolKey[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\', - 'Z','o','n','e','M','a','p','\\', - 'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0}; - static const WCHAR wszFile[] = {'f','i','l','e',0}; - - *zone = -1; - - hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0); - if(FAILED(hres)) - return hres; - if(!*schema) - return 0x80041001; - - /* file protocol is a special case */ - if(!strcmpW(schema, wszFile)) { - WCHAR path[MAX_PATH]; - - hres = CoInternetParseUrl(url, PARSE_PATH_FROM_URL, 0, path, - sizeof(path)/sizeof(WCHAR), &size, 0); - - if(SUCCEEDED(hres) && strchrW(path, '\\')) { - *zone = 0; - return S_OK; - } - } - - WARN("domains are not yet implemented\n"); + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\', + 'Z','o','n','e','M','a','p','\\', + 'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0}; res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey); if(res != ERROR_SUCCESS) { @@ -111,6 +73,171 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone) return S_OK; } +static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url) +{ + LPWSTR secur_url; + WCHAR schema[64]; + DWORD size=0; + HRESULT hres; + + secur_url = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR)); + *zone = -1; + + hres = CoInternetParseUrl(url, PARSE_SECURITY_URL, 0, secur_url, INTERNET_MAX_URL_LENGTH, &size, 0); + if(hres != S_OK) + strcpyW(secur_url, url); + + hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0); + if(FAILED(hres) || !*schema) { + heap_free(secur_url); + return E_INVALIDARG; + } + + /* file protocol is a special case */ + if(!strcmpW(schema, fileW)) { + WCHAR path[MAX_PATH], root[20]; + WCHAR *ptr; + + hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path, + sizeof(path)/sizeof(WCHAR), &size, 0); + + if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) && ptr-path < sizeof(root)/sizeof(WCHAR)) { + UINT type; + + memcpy(root, path, (ptr-path)*sizeof(WCHAR)); + root[ptr-path] = 0; + + type = GetDriveTypeW(root); + + switch(type) { + case DRIVE_UNKNOWN: + case DRIVE_NO_ROOT_DIR: + break; + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + case DRIVE_CDROM: + case DRIVE_RAMDISK: + *zone = 0; + hres = S_OK; + break; + case DRIVE_REMOTE: + *zone = 3; + hres = S_OK; + break; + default: + FIXME("unsupported drive type %d\n", type); + } + } + } + + if(*zone == -1) { + WARN("domains are not yet implemented\n"); + hres = get_zone_from_reg(schema, zone); + } + + if(FAILED(hres) || !ret_url) + heap_free(secur_url); + else + *ret_url = secur_url; + + return hres; +} + +static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey) +{ + static const WCHAR wszZonesKey[] = + {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\', + 'Z','o','n','e','s','\\',0}; + static const WCHAR wszFormat[] = {'%','s','%','l','d',0}; + + WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8]; + DWORD res; + + wsprintfW(key_name, wszFormat, wszZonesKey, zone); + + res = RegOpenKeyW(parent_key, key_name, hkey); + + if(res != ERROR_SUCCESS) { + WARN("RegOpenKey failed\n"); + return E_INVALIDARG; + } + + return S_OK; +} + +static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size, URLZONEREG zone_reg) +{ + HKEY parent_key; + HKEY hkey; + LONG res; + HRESULT hres; + + switch(action) { + case URLACTION_SCRIPT_OVERRIDE_SAFETY: + *(DWORD*)policy = URLPOLICY_DISALLOW; + return S_OK; + } + + switch(zone_reg) { + case URLZONEREG_DEFAULT: + case URLZONEREG_HKCU: + parent_key = HKEY_CURRENT_USER; + break; + case URLZONEREG_HKLM: + parent_key = HKEY_LOCAL_MACHINE; + break; + default: + WARN("Unknown URLZONEREG: %d\n", zone_reg); + return E_FAIL; + }; + + hres = open_zone_key(parent_key, zone, &hkey); + if(SUCCEEDED(hres)) { + WCHAR action_str[16]; + DWORD len = size; + + static const WCHAR formatW[] = {'%','X',0}; + + wsprintfW(action_str, formatW, action); + + res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len); + if(res == ERROR_MORE_DATA) { + hres = E_INVALIDARG; + }else if(res == ERROR_FILE_NOT_FOUND) { + hres = E_FAIL; + }else if(res != ERROR_SUCCESS) { + ERR("RegQueryValue failed: %d\n", res); + hres = E_UNEXPECTED; + } + + RegCloseKey(hkey); + } + + if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT) + return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM); + + return hres; +} + +/*********************************************************************** + * InternetSecurityManager implementation + * + */ +typedef struct { + const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl; + + LONG ref; + + IInternetSecurityMgrSite *mgrsite; + IInternetSecurityManager *custom_manager; +} SecManagerImpl; + +#define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface) + static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject) { SecManagerImpl *This = SECMGR_THIS(iface); @@ -230,8 +357,6 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac DWORD dwFlags) { SecManagerImpl *This = SECMGR_THIS(iface); - LPWSTR url; - DWORD size; HRESULT hres; TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags); @@ -251,26 +376,15 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac if(dwFlags) FIXME("not supported flags: %08x\n", dwFlags); - size = (strlenW(pwszUrl)+16) * sizeof(WCHAR); - url = heap_alloc(size); - - hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, url, size/sizeof(WCHAR), &size, 0); - if(FAILED(hres)) - memcpy(url, pwszUrl, size); - - hres = map_url_to_zone(url, pdwZone); - - heap_free(url); - - return hres; + return map_url_to_zone(pwszUrl, pdwZone, NULL); } static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) { SecManagerImpl *This = SECMGR_THIS(iface); - LPWSTR buf, ptr, ptr2; - DWORD size, zone, len; + LPWSTR url, ptr, ptr2; + DWORD zone, len; HRESULT hres; static const WCHAR wszFile[] = {'f','i','l','e',':'}; @@ -291,26 +405,17 @@ static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *ifa if(dwReserved) FIXME("dwReserved is not supported\n"); - len = strlenW(pwszUrl)+1; - buf = heap_alloc((len+16)*sizeof(WCHAR)); - - hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, buf, len, &size, 0); + hres = map_url_to_zone(pwszUrl, &zone, &url); if(FAILED(hres)) - memcpy(buf, pwszUrl, len*sizeof(WCHAR)); - - hres = map_url_to_zone(buf, &zone); - if(FAILED(hres)) { - heap_free(buf); return hres == 0x80041001 ? E_INVALIDARG : hres; - } /* file protocol is a special case */ - if(strlenW(pwszUrl) >= sizeof(wszFile)/sizeof(WCHAR) - && !memcmp(buf, wszFile, sizeof(wszFile))) { + if(strlenW(url) >= sizeof(wszFile)/sizeof(WCHAR) + && !memcmp(url, wszFile, sizeof(wszFile)) && strchrW(url, '\\')) { static const BYTE secidFile[] = {'f','i','l','e',':'}; - heap_free(buf); + heap_free(url); if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); @@ -322,7 +427,7 @@ static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *ifa return S_OK; } - ptr = strchrW(buf, ':'); + ptr = strchrW(url, ':'); ptr2 = ++ptr; while(*ptr2 == '/') ptr2++; @@ -333,15 +438,15 @@ static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *ifa if(ptr) *ptr = 0; - len = WideCharToMultiByte(CP_ACP, 0, buf, -1, NULL, 0, NULL, NULL)-1; + len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL)-1; if(len+sizeof(DWORD) > *pcbSecurityId) { - heap_free(buf); + heap_free(url); return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } - WideCharToMultiByte(CP_ACP, 0, buf, -1, (LPSTR)pbSecurityId, -1, NULL, NULL); - heap_free(buf); + WideCharToMultiByte(CP_ACP, 0, url, -1, (LPSTR)pbSecurityId, len, NULL, NULL); + heap_free(url); *(DWORD*)(pbSecurityId+len) = zone; @@ -358,6 +463,7 @@ static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager * DWORD dwFlags, DWORD dwReserved) { SecManagerImpl *This = SECMGR_THIS(iface); + DWORD zone, policy; HRESULT hres; TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction, @@ -370,8 +476,36 @@ static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager * return hres; } - FIXME("Default action is not implemented\n"); - return E_NOTIMPL; + if(pContext || cbContext || dwFlags || dwReserved) + FIXME("Unsupported arguments\n"); + + if(!pwszUrl) + return E_INVALIDARG; + + hres = map_url_to_zone(pwszUrl, &zone, NULL); + if(FAILED(hres)) + return hres; + + hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy), URLZONEREG_DEFAULT); + if(FAILED(hres)) + return hres; + + TRACE("policy %x\n", policy); + + switch(GetUrlPolicyPermissions(policy)) { + case URLPOLICY_ALLOW: + case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE: + return S_OK; + case URLPOLICY_DISALLOW: + return S_FALSE; + case URLPOLICY_QUERY: + FIXME("URLPOLICY_QUERY not implemented\n"); + return E_FAIL; + default: + FIXME("Not implemented policy %x\n", policy); + } + + return E_FAIL; } @@ -481,46 +615,6 @@ typedef struct { LONG ref; } ZoneMgrImpl; -static HRESULT open_zone_key(DWORD zone, HKEY *hkey, URLZONEREG zone_reg) -{ - static const WCHAR wszZonesKey[] = - {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\', - 'Z','o','n','e','s','\\',0}; - static const WCHAR wszFormat[] = {'%','s','%','l','d',0}; - - WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8]; - HKEY parent_key; - DWORD res; - - switch(zone_reg) { - case URLZONEREG_DEFAULT: /* FIXME: TEST */ - case URLZONEREG_HKCU: - parent_key = HKEY_CURRENT_USER; - break; - case URLZONEREG_HKLM: - parent_key = HKEY_LOCAL_MACHINE; - break; - default: - WARN("Unknown URLZONEREG: %d\n", zone_reg); - return E_FAIL; - }; - - wsprintfW(key_name, wszFormat, wszZonesKey, zone); - - res = RegOpenKeyW(parent_key, key_name, hkey); - - if(res != ERROR_SUCCESS) { - WARN("RegOpenKey failed\n"); - return E_INVALIDARG; - } - - return S_OK; -} - /******************************************************************** * IInternetZoneManager_QueryInterface */ @@ -634,39 +728,13 @@ static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManager* ifac static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManager* iface, DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg) { - WCHAR action[16]; - HKEY hkey; - LONG res; - DWORD size = cbPolicy; - HRESULT hres; - - static const WCHAR wszFormat[] = {'%','l','X',0}; - TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg); if(!pPolicy) return E_INVALIDARG; - hres = open_zone_key(dwZone, &hkey, urlZoneReg); - if(FAILED(hres)) - return hres; - - wsprintfW(action, wszFormat, dwAction); - - res = RegQueryValueExW(hkey, action, NULL, NULL, pPolicy, &size); - if(res == ERROR_MORE_DATA) { - hres = E_INVALIDARG; - }else if(res == ERROR_FILE_NOT_FOUND) { - hres = E_FAIL; - }else if(res != ERROR_SUCCESS) { - ERR("RegQueryValue failed: %d\n", res); - hres = E_UNEXPECTED; - } - - RegCloseKey(hkey); - - return hres; + return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg); } /******************************************************************** diff --git a/reactos/dll/win32/urlmon/session.c b/reactos/dll/win32/urlmon/session.c index 3571b050384..72308e1eeec 100644 --- a/reactos/dll/win32/urlmon/session.c +++ b/reactos/dll/win32/urlmon/session.c @@ -27,6 +27,7 @@ typedef struct name_space { LPWSTR protocol; IClassFactory *cf; CLSID clsid; + BOOL urlmon; struct name_space *next; } name_space; @@ -42,6 +43,15 @@ typedef struct mime_filter { static name_space *name_space_list = NULL; static mime_filter *mime_filter_list = NULL; +static CRITICAL_SECTION session_cs; +static CRITICAL_SECTION_DEBUG session_cs_dbg = +{ + 0, 0, &session_cs, + { &session_cs_dbg.ProcessLocksList, &session_cs_dbg.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": session") } +}; +static CRITICAL_SECTION session_cs = { &session_cs_dbg, -1, 0, 0, 0, 0 }; + static name_space *find_name_space(LPCWSTR protocol) { name_space *iter; @@ -95,9 +105,89 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid, if(pclsid) *pclsid = clsid; + if(!ret) + return S_OK; + return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret); } +static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL urlmon_protocol) +{ + name_space *new_name_space; + + new_name_space = heap_alloc(sizeof(name_space)); + + if(!urlmon_protocol) + IClassFactory_AddRef(cf); + new_name_space->cf = cf; + new_name_space->clsid = *clsid; + new_name_space->urlmon = urlmon_protocol; + new_name_space->protocol = heap_strdupW(protocol); + + EnterCriticalSection(&session_cs); + + new_name_space->next = name_space_list; + name_space_list = new_name_space; + + LeaveCriticalSection(&session_cs); + + return S_OK; +} + +static HRESULT unregister_namespace(IClassFactory *cf, LPCWSTR protocol) +{ + name_space *iter, *last = NULL; + + EnterCriticalSection(&session_cs); + + for(iter = name_space_list; iter; iter = iter->next) { + if(iter->cf == cf && !strcmpW(iter->protocol, protocol)) + break; + last = iter; + } + + if(iter) { + if(last) + last->next = iter->next; + else + name_space_list = iter->next; + } + + LeaveCriticalSection(&session_cs); + + if(iter) { + if(!iter->urlmon) + IClassFactory_Release(iter->cf); + heap_free(iter->protocol); + heap_free(iter); + } + + return S_OK; +} + + +void register_urlmon_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL do_register) +{ + if(do_register) + register_namespace(cf, clsid, protocol, TRUE); + else + unregister_namespace(cf, protocol); +} + +BOOL is_registered_protocol(LPCWSTR url) +{ + DWORD schema_len; + WCHAR schema[64]; + HRESULT hres; + + hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), + &schema_len, 0); + if(FAILED(hres)) + return FALSE; + + return get_protocol_cf(schema, schema_len, NULL, NULL) == S_OK; +} + IInternetProtocolInfo *get_protocol_info(LPCWSTR url) { IInternetProtocolInfo *ret = NULL; @@ -112,17 +202,20 @@ IInternetProtocolInfo *get_protocol_info(LPCWSTR url) if(FAILED(hres) || !schema_len) return NULL; - ns = find_name_space(schema); - if(ns) { - hres = IClassFactory_QueryInterface(ns->cf, &IID_IInternetProtocolInfo, (void**)&ret); - if(SUCCEEDED(hres)) - return ret; + EnterCriticalSection(&session_cs); - hres = IClassFactory_CreateInstance(ns->cf, NULL, &IID_IInternetProtocolInfo, (void**)&ret); - if(SUCCEEDED(hres)) - return ret; + ns = find_name_space(schema); + if(ns && !ns->urlmon) { + hres = IClassFactory_QueryInterface(ns->cf, &IID_IInternetProtocolInfo, (void**)&ret); + if(FAILED(hres)) + hres = IClassFactory_CreateInstance(ns->cf, NULL, &IID_IInternetProtocolInfo, (void**)&ret); } + LeaveCriticalSection(&session_cs); + + if(ns && SUCCEEDED(hres)) + return ret; + hres = get_protocol_cf(schema, schema_len, NULL, &cf); if(FAILED(hres)) return NULL; @@ -142,20 +235,28 @@ HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, IClassFactory **ret) DWORD schema_len; 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; + EnterCriticalSection(&session_cs); + ns = find_name_space(schema); if(ns) { *ret = ns->cf; IClassFactory_AddRef(*ret); if(clsid) *clsid = ns->clsid; - return S_OK; } + LeaveCriticalSection(&session_cs); + + if(*ret) + return S_OK; + return get_protocol_cf(schema, schema_len, clsid, ret); } @@ -192,8 +293,6 @@ static HRESULT WINAPI InternetSession_RegisterNameSpace(IInternetSession *iface, IClassFactory *pCF, REFCLSID rclsid, LPCWSTR pwzProtocol, ULONG cPatterns, const LPCWSTR *ppwzPatterns, DWORD dwReserved) { - name_space *new_name_space; - TRACE("(%p %s %s %d %p %d)\n", pCF, debugstr_guid(rclsid), debugstr_w(pwzProtocol), cPatterns, ppwzPatterns, dwReserved); @@ -205,47 +304,18 @@ static HRESULT WINAPI InternetSession_RegisterNameSpace(IInternetSession *iface, if(!pCF || !pwzProtocol) return E_INVALIDARG; - new_name_space = heap_alloc(sizeof(name_space)); - - IClassFactory_AddRef(pCF); - new_name_space->cf = pCF; - new_name_space->clsid = *rclsid; - new_name_space->protocol = heap_strdupW(pwzProtocol); - - new_name_space->next = name_space_list; - name_space_list = new_name_space; - return S_OK; + return register_namespace(pCF, rclsid, pwzProtocol, FALSE); } static HRESULT WINAPI InternetSession_UnregisterNameSpace(IInternetSession *iface, IClassFactory *pCF, LPCWSTR pszProtocol) { - name_space *iter, *last = NULL; - TRACE("(%p %s)\n", pCF, debugstr_w(pszProtocol)); if(!pCF || !pszProtocol) return E_INVALIDARG; - for(iter = name_space_list; iter; iter = iter->next) { - if(iter->cf == pCF && !strcmpW(iter->protocol, pszProtocol)) - break; - last = iter; - } - - if(!iter) - return S_OK; - - if(last) - last->next = iter->next; - else - name_space_list = iter->next; - - IClassFactory_Release(iter->cf); - heap_free(iter->protocol); - heap_free(iter); - - return S_OK; + return unregister_namespace(pCF, pszProtocol); } static HRESULT WINAPI InternetSession_RegisterMimeFilter(IInternetSession *iface, @@ -262,9 +332,13 @@ static HRESULT WINAPI InternetSession_RegisterMimeFilter(IInternetSession *iface filter->clsid = *rclsid; filter->mime = heap_strdupW(pwzType); + EnterCriticalSection(&session_cs); + filter->next = mime_filter_list; mime_filter_list = filter; + LeaveCriticalSection(&session_cs); + return S_OK; } @@ -275,23 +349,28 @@ static HRESULT WINAPI InternetSession_UnregisterMimeFilter(IInternetSession *ifa TRACE("(%p %s)\n", pCF, debugstr_w(pwzType)); + EnterCriticalSection(&session_cs); + for(iter = mime_filter_list; iter; iter = iter->next) { if(iter->cf == pCF && !strcmpW(iter->mime, pwzType)) break; prev = iter; } - if(!iter) - return S_OK; + if(iter) { + if(prev) + prev->next = iter->next; + else + mime_filter_list = iter->next; + } - if(prev) - prev->next = iter->next; - else - mime_filter_list = iter->next; + LeaveCriticalSection(&session_cs); - IClassFactory_Release(iter->cf); - heap_free(iter->mime); - heap_free(iter); + if(iter) { + IClassFactory_Release(iter->cf); + heap_free(iter->mime); + heap_free(iter); + } return S_OK; } diff --git a/reactos/dll/win32/urlmon/umon.c b/reactos/dll/win32/urlmon/umon.c index 5981a1c96d0..f6ea4274f03 100644 --- a/reactos/dll/win32/urlmon/umon.c +++ b/reactos/dll/win32/urlmon/umon.c @@ -493,10 +493,7 @@ static HRESULT WINAPI URLMonikerImpl_BindToObject(IMoniker* iface, /****************************************************************************** * URLMoniker_BindToStorage ******************************************************************************/ -static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, - IBindCtx* pbc, - REFIID riid, - VOID** ppvObject) +static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, VOID** ppvObject) { HRESULT hres; BINDINFO bi; @@ -505,12 +502,7 @@ static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, Binding *bind; int len; - WARN("(%s %p %s %p)\n", debugstr_w(URLName), pbc, debugstr_guid(riid), ppvObject); - - if(!IsEqualIID(&IID_IStream, riid)) { - FIXME("unsupported iid\n"); - return E_NOTIMPL; - } + WARN("(%s %p %p)\n", debugstr_w(URLName), pbc, ppvObject); bind = heap_alloc_zero(sizeof(Binding)); bind->lpVtbl = &BindingVtbl; @@ -741,10 +733,11 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, return E_FAIL; } - if(url.nScheme== INTERNET_SCHEME_HTTPS - || url.nScheme== INTERNET_SCHEME_FTP - || url.nScheme == INTERNET_SCHEME_GOPHER) - return URLMonikerImpl_BindToStorage_hack(This->URLName, pbc, riid, ppvObject); + if(IsEqualGUID(&IID_IStream, riid) && + ( url.nScheme == INTERNET_SCHEME_HTTPS + || url.nScheme == INTERNET_SCHEME_FTP + || url.nScheme == INTERNET_SCHEME_GOPHER)) + return URLMonikerImpl_BindToStorage_hack(This->URLName, pbc, ppvObject); TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject); @@ -1186,218 +1179,25 @@ HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback } /*********************************************************************** - * URLDownloadToFileA (URLMON.@) - * - * Downloads URL szURL to rile szFileName and call lpfnCB callback to - * report progress. - * - * PARAMS - * pCaller [I] controlling IUnknown interface. - * szURL [I] URL of the file to download - * szFileName [I] file name to store the content of the URL - * dwReserved [I] reserved - set to 0 - * lpfnCB [I] callback for progress report - * - * RETURNS - * S_OK on success - * E_OUTOFMEMORY when going out of memory + * MkParseDisplayNameEx (URLMON.@) */ -HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, - LPCSTR szURL, - LPCSTR szFileName, - DWORD dwReserved, - LPBINDSTATUSCALLBACK lpfnCB) +HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk) { - UNICODE_STRING szURL_w, szFileName_w; + TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk); - if ((szURL == NULL) || (szFileName == NULL)) { - FIXME("(%p,%s,%s,%08x,%p) cannot accept NULL strings !\n", pCaller, debugstr_a(szURL), debugstr_a(szFileName), dwReserved, lpfnCB); - return E_INVALIDARG; /* The error code is not specified in this case... */ - } - - if (RtlCreateUnicodeStringFromAsciiz(&szURL_w, szURL)) { - if (RtlCreateUnicodeStringFromAsciiz(&szFileName_w, szFileName)) { - HRESULT ret = URLDownloadToFileW(pCaller, szURL_w.Buffer, szFileName_w.Buffer, dwReserved, lpfnCB); + if(is_registered_protocol(szDisplayName)) { + HRESULT hres; - RtlFreeUnicodeString(&szURL_w); - RtlFreeUnicodeString(&szFileName_w); - - return ret; - } else { - RtlFreeUnicodeString(&szURL_w); - } + hres = CreateURLMoniker(NULL, szDisplayName, ppmk); + if(SUCCEEDED(hres)) { + *pchEaten = strlenW(szDisplayName); + return hres; + } } - - FIXME("(%p,%s,%s,%08x,%p) could not allocate W strings !\n", pCaller, szURL, szFileName, dwReserved, lpfnCB); - return E_OUTOFMEMORY; + + return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk); } -/*********************************************************************** - * URLDownloadToFileW (URLMON.@) - * - * Downloads URL szURL to rile szFileName and call lpfnCB callback to - * report progress. - * - * PARAMS - * pCaller [I] controlling IUnknown interface. - * szURL [I] URL of the file to download - * szFileName [I] file name to store the content of the URL - * dwReserved [I] reserved - set to 0 - * lpfnCB [I] callback for progress report - * - * RETURNS - * S_OK on success - * E_OUTOFMEMORY when going out of memory - */ -HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, - LPCWSTR szURL, - LPCWSTR szFileName, - DWORD dwReserved, - LPBINDSTATUSCALLBACK lpfnCB) -{ - HINTERNET hinternet, hcon, hreq; - BOOL r; - CHAR buffer[0x1000]; - DWORD sz, total, written; - DWORD total_size = 0xFFFFFFFF, arg_size = sizeof(total_size); - URL_COMPONENTSW url; - WCHAR host[0x80], path[0x100]; - HANDLE hfile; - static const WCHAR wszAppName[]={'u','r','l','m','o','n','.','d','l','l',0}; - - /* Note: all error codes would need to be checked agains real Windows behaviour... */ - TRACE("(%p,%s,%s,%08x,%p) stub!\n", pCaller, debugstr_w(szURL), debugstr_w(szFileName), dwReserved, lpfnCB); - - if ((szURL == NULL) || (szFileName == NULL)) { - FIXME(" cannot accept NULL strings !\n"); - return E_INVALIDARG; - } - - /* Would be better to use the application name here rather than 'urlmon' :-/ */ - hinternet = InternetOpenW(wszAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if (hinternet == NULL) { - return E_OUTOFMEMORY; - } - - memset(&url, 0, sizeof(url)); - url.dwStructSize = sizeof(url); - url.lpszHostName = host; - url.dwHostNameLength = sizeof(host); - url.lpszUrlPath = path; - url.dwUrlPathLength = sizeof(path); - - if (!InternetCrackUrlW(szURL, 0, 0, &url)) { - InternetCloseHandle(hinternet); - return E_OUTOFMEMORY; - } - - if (lpfnCB) { - if (IBindStatusCallback_OnProgress(lpfnCB, 0, 0, BINDSTATUS_CONNECTING, url.lpszHostName) == E_ABORT) { - InternetCloseHandle(hinternet); - return S_OK; - } - } - - hcon = InternetConnectW(hinternet, url.lpszHostName, url.nPort, - url.lpszUserName, url.lpszPassword, - INTERNET_SERVICE_HTTP, 0, 0); - if (!hcon) { - InternetCloseHandle(hinternet); - return E_OUTOFMEMORY; - } - - hreq = HttpOpenRequestW(hcon, NULL, url.lpszUrlPath, NULL, NULL, NULL, 0, 0); - if (!hreq) { - InternetCloseHandle(hinternet); - InternetCloseHandle(hcon); - return E_OUTOFMEMORY; - } - - if (!HttpSendRequestW(hreq, NULL, 0, NULL, 0)) { - InternetCloseHandle(hinternet); - InternetCloseHandle(hcon); - InternetCloseHandle(hreq); - return E_OUTOFMEMORY; - } - - if (HttpQueryInfoW(hreq, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, - &total_size, &arg_size, NULL)) { - TRACE(" total size : %d\n", total_size); - } - - hfile = CreateFileW(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL ); - if (hfile == INVALID_HANDLE_VALUE) { - return E_ACCESSDENIED; - } - - if (lpfnCB) { - if (IBindStatusCallback_OnProgress(lpfnCB, 0, total_size != 0xFFFFFFFF ? total_size : 0, - BINDSTATUS_BEGINDOWNLOADDATA, szURL) == E_ABORT) { - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - CloseHandle(hfile); - return S_OK; - } - } - - total = 0; - while (1) { - r = InternetReadFile(hreq, buffer, sizeof(buffer), &sz); - if (!r) { - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - - CloseHandle(hfile); - return E_OUTOFMEMORY; - } - if (!sz) - break; - - total += sz; - - if (lpfnCB) { - if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ? total_size : 0, - BINDSTATUS_DOWNLOADINGDATA, szURL) == E_ABORT) { - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - CloseHandle(hfile); - return S_OK; - } - } - - if (!WriteFile(hfile, buffer, sz, &written, NULL)) { - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - - CloseHandle(hfile); - return E_OUTOFMEMORY; - } - } - - if (lpfnCB) { - if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ? total_size : 0, - BINDSTATUS_ENDDOWNLOADDATA, szURL) == E_ABORT) { - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - CloseHandle(hfile); - return S_OK; - } - } - - InternetCloseHandle(hreq); - InternetCloseHandle(hcon); - InternetCloseHandle(hinternet); - - CloseHandle(hfile); - - return S_OK; -} /*********************************************************************** * URLDownloadToCacheFileA (URLMON.@) diff --git a/reactos/dll/win32/urlmon/umstream.c b/reactos/dll/win32/urlmon/umstream.c index 54037354ea5..7523781d77e 100644 --- a/reactos/dll/win32/urlmon/umstream.c +++ b/reactos/dll/win32/urlmon/umstream.c @@ -221,7 +221,7 @@ static HRESULT WINAPI IStream_fnRead (IStream * iface, if ( !pcbRead) pcbRead = &dwBytesRead; - if ( ! ReadFile( This->handle, pv, cb, (LPDWORD)pcbRead, NULL ) ) + if ( ! ReadFile( This->handle, pv, cb, pcbRead, NULL ) ) return S_FALSE; if (!*pcbRead) diff --git a/reactos/dll/win32/urlmon/urlmon.rbuild b/reactos/dll/win32/urlmon/urlmon.rbuild index 9a13e72c821..ad9dcf3a88e 100644 --- a/reactos/dll/win32/urlmon/urlmon.rbuild +++ b/reactos/dll/win32/urlmon/urlmon.rbuild @@ -9,18 +9,10 @@ 0x600 0x600 - wine - ole32 - shlwapi - wininet - user32 - advapi32 - kernel32 - ntdll - uuid bindctx.c binding.c bindprot.c + download.c file.c format.c ftp.c @@ -35,5 +27,14 @@ urlmon_main.c rsrc.rc urlmon.spec + wine + ole32 + shlwapi + wininet + user32 + advapi32 + kernel32 + uuid + ntdll diff --git a/reactos/dll/win32/urlmon/urlmon.spec b/reactos/dll/win32/urlmon/urlmon.spec index fdb94eb0123..1fa2f941c34 100644 --- a/reactos/dll/win32/urlmon/urlmon.spec +++ b/reactos/dll/win32/urlmon/urlmon.spec @@ -21,7 +21,7 @@ @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) @ stub CompareSecurityIds @ stub CopyBindInfo -@ stub CopyStgMedium +@ stdcall CopyStgMedium(ptr ptr) @ stdcall CreateAsyncBindCtx(long ptr ptr ptr) @ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long) @ stdcall CreateFormatEnumerator(long ptr ptr) @@ -53,7 +53,7 @@ @ stub IsLoggingEnabledA @ stub IsLoggingEnabledW @ stdcall IsValidURL(ptr wstr long) -@ stdcall MkParseDisplayNameEx(ptr ptr ptr ptr) ole32.MkParseDisplayName +@ stdcall MkParseDisplayNameEx(ptr wstr ptr ptr) @ stdcall ObtainUserAgentString(long str ptr) @ stub PrivateCoInstall @ stdcall RegisterBindStatusCallback(ptr ptr ptr long) diff --git a/reactos/dll/win32/urlmon/urlmon_main.c b/reactos/dll/win32/urlmon/urlmon_main.c index 1661bb66c2d..bc3de934b35 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.c +++ b/reactos/dll/win32/urlmon/urlmon_main.c @@ -210,31 +210,14 @@ static const struct object_creation_info object_creation[] = static void init_session(BOOL init) { - IInternetSession *session; int i; - CoInternetGetSession(0, &session, 0); - for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) { - if(object_creation[i].protocol) { - if(init) - { - IInternetSession_RegisterNameSpace(session, object_creation[i].cf, - object_creation[i].clsid, object_creation[i].protocol, 0, NULL, 0); - /* make sure that the AddRef on the class factory doesn't keep us loaded */ - URLMON_UnlockModule(); - } - else - { - /* make sure that the Release on the class factory doesn't unload us */ - URLMON_LockModule(); - IInternetSession_UnregisterNameSpace(session, object_creation[i].cf, - object_creation[i].protocol); - } - } - } - IInternetSession_Release(session); + if(object_creation[i].protocol) + register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid, + object_creation[i].protocol, init); + } } /******************************************************************************* @@ -398,7 +381,6 @@ void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) if(offsetof(BINDINFO, szExtraInfo) < size) CoTaskMemFree(pbindinfo->szCustomVerb); - if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size) IUnknown_Release(pbindinfo->pUnk); @@ -406,6 +388,46 @@ void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) pbindinfo->cbSize = size; } +/*********************************************************************** + * CopyStgMedium (URLMON.@) + */ +HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) +{ + TRACE("(%p %p)\n", src, dst); + + if(!src || !dst) + return E_POINTER; + + *dst = *src; + + switch(dst->tymed) { + case TYMED_NULL: + break; + case TYMED_FILE: + if(src->u.lpszFileName && !src->pUnkForRelease) { + DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR); + dst->u.lpszFileName = CoTaskMemAlloc(size); + memcpy(dst->u.lpszFileName, src->u.lpszFileName, size); + } + break; + case TYMED_ISTREAM: + if(dst->u.pstm) + IStream_AddRef(dst->u.pstm); + break; + case TYMED_ISTORAGE: + if(dst->u.pstg) + IStorage_AddRef(dst->u.pstg); + break; + default: + FIXME("Unimplemented tymed %d\n", src->tymed); + } + + if(dst->pUnkForRelease) + IUnknown_AddRef(dst->pUnkForRelease); + + return S_OK; +} + static BOOL text_richtext_filter(const BYTE *b, DWORD size) { return size > 5 && !memcmp(b, "{\\rtf", 5); @@ -430,6 +452,12 @@ static BOOL text_html_filter(const BYTE *b, DWORD size) return FALSE; } +static BOOL audio_basic_filter(const BYTE *b, DWORD size) +{ + return size > 4 + && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd'; +} + static BOOL audio_wav_filter(const BYTE *b, DWORD size) { return size > 12 @@ -574,6 +602,7 @@ HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, 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}; @@ -604,16 +633,25 @@ HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, } 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}, diff --git a/reactos/dll/win32/urlmon/urlmon_main.h b/reactos/dll/win32/urlmon/urlmon_main.h index d845e6e0feb..17cbd7637ad 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.h +++ b/reactos/dll/win32/urlmon/urlmon_main.h @@ -67,6 +67,8 @@ void UMCloseCacheFileStream(IUMCacheStream *pstr); IInternetProtocolInfo *get_protocol_info(LPCWSTR url); HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, IClassFactory **ret); +BOOL is_registered_protocol(LPCWSTR); +void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL); 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); @@ -109,4 +111,17 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) return ret; } +static inline LPWSTR heap_strdupAtoW(const char *str) +{ + LPWSTR ret = NULL; + + if(str) { + DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = heap_alloc(len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + } + + return ret; +} + #endif /* __WINE_URLMON_MAIN_H */