mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=32859
This commit is contained in:
parent
6cf19300da
commit
eefe82711d
|
@ -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)
|
||||
|
|
406
reactos/dll/win32/urlmon/download.c
Normal file
406
reactos/dll/win32/urlmon/download.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.@)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue