Autosyncing with Wine HEAD

svn path=/trunk/; revision=32859
This commit is contained in:
The Wine Synchronizer 2008-04-04 14:41:46 +00:00
parent 6cf19300da
commit eefe82711d
14 changed files with 1200 additions and 552 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
/********************************************************************

View file

@ -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;
}

View file

@ -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.@)

View file

@ -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)

View file

@ -9,18 +9,10 @@
<define name="__WINESRC__" />
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>ole32</library>
<library>shlwapi</library>
<library>wininet</library>
<library>user32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
<library>uuid</library>
<file>bindctx.c</file>
<file>binding.c</file>
<file>bindprot.c</file>
<file>download.c</file>
<file>file.c</file>
<file>format.c</file>
<file>ftp.c</file>
@ -35,5 +27,14 @@
<file>urlmon_main.c</file>
<file>rsrc.rc</file>
<file>urlmon.spec</file>
<library>wine</library>
<library>ole32</library>
<library>shlwapi</library>
<library>wininet</library>
<library>user32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
</module>
</group>

View file

@ -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)

View file

@ -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},

View file

@ -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 */