Commit 6b854ff4 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

urlmon: Separate buffer from stream object.

parent e7885cf2
......@@ -38,16 +38,26 @@ 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;
} stgmed_buf_t;
#define STGMEDUNK(x) ((IUnknown*) &(x)->lpUnknownVtbl)
typedef struct {
const IStreamVtbl *lpStreamVtbl;
LONG ref;
stgmed_buf_t *buf;
} ProtocolStream;
typedef enum {
......@@ -71,6 +81,8 @@ struct Binding {
IBindStatusCallback *callback;
IInternetProtocol *protocol;
IServiceProvider *service_provider;
stgmed_buf_t *stgmed_buf;
ProtocolStream *stream;
BINDINFO bindinfo;
......@@ -143,18 +155,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 +293,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);
......@@ -460,6 +472,61 @@ static void create_object(Binding *binding)
stop_binding(binding, S_OK, NULL);
}
#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);
URLMON_UnlockModule();
}
return ref;
}
#undef STGMEDUNK_THIS
static const IUnknownVtbl StgMedUnkVtbl = {
StgMedUnk_QueryInterface,
StgMedUnk_AddRef,
StgMedUnk_Release
};
#define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface)
static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface,
......@@ -507,7 +574,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 +584,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 +611,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;
}
......@@ -658,14 +726,14 @@ static const IStreamVtbl ProtocolStreamVtbl = {
#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
static ProtocolStream *create_stream(IInternetProtocol *protocol)
static stgmed_buf_t *create_stgmed_buf(IInternetProtocol *protocol)
{
ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream));
stgmed_buf_t *ret = heap_alloc(sizeof(*ret));
ret->lpStreamVtbl = &ProtocolStreamVtbl;
ret->lpUnknownVtbl = &StgMedUnkVtbl;
ret->ref = 1;
ret->buf_size = 0;
ret->init_buf = FALSE;
ret->size = 0;
ret->init = FALSE;
ret->hres = S_OK;
IInternetProtocol_AddRef(protocol);
......@@ -676,6 +744,21 @@ static ProtocolStream *create_stream(IInternetProtocol *protocol)
return ret;
}
static ProtocolStream *create_stream(stgmed_buf_t *buf)
{
ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream));
ret->lpStreamVtbl = &ProtocolStreamVtbl;
ret->ref = 1;
IUnknown_AddRef(STGMEDUNK(buf));
ret->buf = buf;
URLMON_LockModule();
return ret;
}
static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv)
{
Binding *This = BINDING_THIS(iface);
......@@ -736,6 +819,8 @@ static ULONG WINAPI Binding_Release(IBinding *iface)
IInternetProtocol_Release(This->protocol);
if(This->service_provider)
IServiceProvider_Release(This->service_provider);
if(This->stgmed_buf)
IUnknown_Release(STGMEDUNK(This->stgmed_buf));
if(This->stream)
IStream_Release(STREAM(This->stream));
if(This->obj)
......@@ -957,7 +1042,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);
......@@ -1000,7 +1085,7 @@ 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;
......@@ -1008,7 +1093,7 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
BINDSTATUS_BEGINDOWNLOADDATA, This->url);
}
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);
......@@ -1406,14 +1491,17 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url,
ret->url = heap_strdupW(url);
if(binding_ctx) {
ret->stgmed_buf = binding_ctx->stgmed_buf;
IUnknown_AddRef(STGMEDUNK(ret->stgmed_buf));
ret->stream = binding_ctx->stream;
IStream_AddRef(STREAM(ret->stream));
IStream_AddRef(STREAM(binding_ctx->stream));
ret->clipboard_format = binding_ctx->clipboard_format;
}else {
ret->stream = create_stream(ret->protocol);
ret->stgmed_buf = create_stgmed_buf(ret->protocol);
ret->stream = create_stream(ret->stgmed_buf);
}
ret->stgmed.tymed = TYMED_ISTREAM;
ret->stgmed.u.pstm = STREAM(ret->stream);
ret->stgmed.u.pstm = STREAM((ProtocolStream*)ret->stream);
ret->stgmed.pUnkForRelease = (IUnknown*)BINDING(ret); /* NOTE: Windows uses other IUnknown */
*binding = ret;
......@@ -1484,12 +1572,12 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv)
if(FAILED(hres))
return hres;
if(binding->hres == S_OK && 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;
*ppv = binding->stgmed.u.pstm;
IStream_AddRef(binding->stgmed.u.pstm);
hres = S_OK;
}else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment