📄 binding.c
字号:
if(This->buf_size) {
read = cb;
if(read > This->buf_size)
read = This->buf_size;
memcpy(pv, This->buf, read);
if(read < This->buf_size)
memmove(This->buf, This->buf+read, This->buf_size-read);
This->buf_size -= read;
}
if(read == cb) {
*pcbRead = read;
return S_OK;
}
This->hres = IInternetProtocol_Read(This->protocol, (PBYTE)pv+read, cb-read, &pread);
*pcbRead = read + pread;
if(This->hres == E_PENDING)
return E_PENDING;
else if(FAILED(This->hres))
FIXME("Read failed: %08x\n", This->hres);
return read || pread ? S_OK : S_FALSE;
}
static HRESULT WINAPI ProtocolStream_Write(IStream *iface, const void *pv,
ULONG cb, ULONG *pcbWritten)
{
ProtocolStream *This = STREAM_THIS(iface);
TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbWritten);
return STG_E_ACCESSDENIED;
}
static HRESULT WINAPI ProtocolStream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%d %08x %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%d)\n", This, libNewSize.u.LowPart);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_CopyTo(IStream *iface, IStream *pstm,
ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%p %d %p %p)\n", This, pstm, cb.u.LowPart, pcbRead, pcbWritten);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_Commit(IStream *iface, DWORD grfCommitFlags)
{
ProtocolStream *This = STREAM_THIS(iface);
TRACE("(%p)->(%08x)\n", This, grfCommitFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_Revert(IStream *iface)
{
ProtocolStream *This = STREAM_THIS(iface);
TRACE("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_UnlockRegion(IStream *iface,
ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_Stat(IStream *iface, STATSTG *pstatstg,
DWORD dwStatFlag)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%p %08x)\n", This, pstatstg, dwStatFlag);
return E_NOTIMPL;
}
static HRESULT WINAPI ProtocolStream_Clone(IStream *iface, IStream **ppstm)
{
ProtocolStream *This = STREAM_THIS(iface);
FIXME("(%p)->(%p)\n", This, ppstm);
return E_NOTIMPL;
}
#undef STREAM_THIS
static const IStreamVtbl ProtocolStreamVtbl = {
ProtocolStream_QueryInterface,
ProtocolStream_AddRef,
ProtocolStream_Release,
ProtocolStream_Read,
ProtocolStream_Write,
ProtocolStream_Seek,
ProtocolStream_SetSize,
ProtocolStream_CopyTo,
ProtocolStream_Commit,
ProtocolStream_Revert,
ProtocolStream_LockRegion,
ProtocolStream_UnlockRegion,
ProtocolStream_Stat,
ProtocolStream_Clone
};
#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
static ProtocolStream *create_stream(IInternetProtocol *protocol)
{
ProtocolStream *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ProtocolStream));
ret->lpStreamVtbl = &ProtocolStreamVtbl;
ret->ref = 1;
ret->buf_size = 0;
ret->init_buf = FALSE;
ret->hres = S_OK;
IInternetProtocol_AddRef(protocol);
ret->protocol = protocol;
URLMON_LockModule();
return ret;
}
static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv)
{
Binding *This = BINDING_THIS(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = BINDING(This);
}else if(IsEqualGUID(&IID_IBinding, riid)) {
TRACE("(%p)->(IID_IBinding %p)\n", This, ppv);
*ppv = BINDING(This);
}else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
*ppv = PROTSINK(This);
}else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
*ppv = BINDINF(This);
}else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
*ppv = SERVPROV(This);
}
if(*ppv) {
IBinding_AddRef(BINDING(This));
return S_OK;
}
WARN("Unsupported interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI Binding_AddRef(IBinding *iface)
{
Binding *This = BINDING_THIS(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI Binding_Release(IBinding *iface)
{
Binding *This = BINDING_THIS(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
if (This->notif_hwnd)
DestroyWindow( This->notif_hwnd );
if(This->callback)
IBindStatusCallback_Release(This->callback);
if(This->protocol)
IInternetProtocol_Release(This->protocol);
if(This->service_provider)
IServiceProvider_Release(This->service_provider);
if(This->stream)
IStream_Release(STREAM(This->stream));
if(This->httpneg2_wrapper)
IHttpNegotiate2_Release(HTTPNEG2(This->httpneg2_wrapper));
ReleaseBindInfo(&This->bindinfo);
This->section.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->section);
HeapFree(GetProcessHeap(), 0, This->mime);
HeapFree(GetProcessHeap(), 0, This->url);
HeapFree(GetProcessHeap(), 0, This);
URLMON_UnlockModule();
}
return ref;
}
static HRESULT WINAPI Binding_Abort(IBinding *iface)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_Suspend(IBinding *iface)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_Resume(IBinding *iface)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_SetPriority(IBinding *iface, LONG nPriority)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)->(%d)\n", This, nPriority);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_GetPriority(IBinding *iface, LONG *pnPriority)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)->(%p)\n", This, pnPriority);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_GetBindResult(IBinding *iface, CLSID *pclsidProtocol,
DWORD *pdwResult, LPOLESTR *pszResult, DWORD *pdwReserved)
{
Binding *This = BINDING_THIS(iface);
FIXME("(%p)->(%p %p %p %p)\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
return E_NOTIMPL;
}
#undef BINDING_THIS
static const IBindingVtbl BindingVtbl = {
Binding_QueryInterface,
Binding_AddRef,
Binding_Release,
Binding_Abort,
Binding_Suspend,
Binding_Resume,
Binding_SetPriority,
Binding_GetPriority,
Binding_GetBindResult
};
#define PROTSINK_THIS(iface) DEFINE_THIS(Binding, InternetProtocolSink, iface)
static HRESULT WINAPI InternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
REFIID riid, void **ppv)
{
Binding *This = PROTSINK_THIS(iface);
return IBinding_QueryInterface(BINDING(This), riid, ppv);
}
static ULONG WINAPI InternetProtocolSink_AddRef(IInternetProtocolSink *iface)
{
Binding *This = PROTSINK_THIS(iface);
return IBinding_AddRef(BINDING(This));
}
static ULONG WINAPI InternetProtocolSink_Release(IInternetProtocolSink *iface)
{
Binding *This = PROTSINK_THIS(iface);
return IBinding_Release(BINDING(This));
}
typedef struct {
task_header_t header;
PROTOCOLDATA *data;
} switch_task_t;
static void switch_proc(Binding *binding, task_header_t *t)
{
switch_task_t *task = (switch_task_t*)t;
IInternetProtocol_Continue(binding->protocol, task->data);
HeapFree(GetProcessHeap(), 0, task);
}
static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface,
PROTOCOLDATA *pProtocolData)
{
Binding *This = PROTSINK_THIS(iface);
switch_task_t *task;
TRACE("(%p)->(%p)\n", This, pProtocolData);
task = HeapAlloc(GetProcessHeap(), 0, sizeof(switch_task_t));
task->data = pProtocolData;
push_task(This, &task->header, switch_proc);
IBinding_AddRef(BINDING(This));
PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
return S_OK;
}
typedef struct {
task_header_t header;
Binding *binding;
ULONG progress;
ULONG progress_max;
ULONG status_code;
LPWSTR status_text;
} on_progress_task_t;
static void on_progress_proc(Binding *binding, task_header_t *t)
{
on_progress_task_t *task = (on_progress_task_t*)t;
IBindStatusCallback_OnProgress(binding->callback, task->progress,
task->progress_max, task->status_code, task->status_text);
HeapFree(GetProcessHeap(), 0, task->status_text);
HeapFree(GetProcessHeap(), 0, task);
}
static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
ULONG status_code, LPCWSTR status_text)
{
on_progress_task_t *task;
if(GetCurrentThreadId() == This->apartment_thread && !This->continue_call) {
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
status_code, status_text);
return;
}
task = HeapAlloc(GetProcessHeap(), 0, sizeof(on_progress_task_t));
task->progress = progress;
task->progress_max = progress_max;
task->status_code = status_code;
if(status_text) {
DWORD size = (strlenW(status_text)+1)*sizeof(WCHAR);
task->status_text = HeapAlloc(GetProcessHeap(), 0, size);
memcpy(task->status_text, status_text, size);
}else {
task->status_text = NULL;
}
push_task(This, &task->header, on_progress_proc);
if(GetCurrentThreadId() != This->apartment_thread) {
IBinding_AddRef(BINDING(This));
PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
}
}
static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
ULONG ulStatusCode, LPCWSTR szStatusText)
{
Binding *This = PROTSINK_THIS(iface);
TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
switch(ulStatusCode) {
case BINDSTATUS_FINDINGRESOURCE:
on_progress(This, 0, 0, BINDSTATUS_FINDINGRESOURCE, szStatusText);
break;
case BINDSTATUS_CONNECTING:
on_progress(This, 0, 0, BINDSTATUS_CONNECTING, szStatusText);
break;
case BINDSTATUS_BEGINDOWNLOADDATA:
fill_stream_buffer(This->stream);
break;
case BINDSTATUS_MIMETYPEAVAILABLE: {
int len = strlenW(szStatusText)+1;
This->mime = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
memcpy(This->mime, szStatusText, len*sizeof(WCHAR));
break;
}
case BINDSTATUS_SENDINGREQUEST:
on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText);
break;
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
This->report_mime = FALSE;
on_progress(This, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
break;
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
break;
case BINDSTATUS_DIRECTBIND:
This->report_mime = FALSE;
break;
default:
FIXME("Unhandled status code %d\n", ulStatusCode);
return E_NOTIMPL;
};
return S_OK;
}
static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progress_max)
{
FORMATETC formatetc = {0, NULL, 1, -1, TYMED_ISTREAM};
TRACE("(%p)->(%d %u %u)\n", This, bscf, progress, progress_max);
if(This->download_state == END_DOWNLOAD)
return;
if(GetCurrentThreadId() != This->apartment_thread)
FIXME("called from worked hread\n");
if(This->report_mime) {
LPWSTR mime;
This->report_mime = FALSE;
fill_stream_buffer(This->stream);
FindMimeFromData(NULL, This->url, This->stream->buf,
min(This->stream->buf_size, 255), This->mime, 0, &mime, 0);
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
BINDSTATUS_MIMETYPEAVAILABLE, mime);
}
if(This->download_state == BEFORE_DOWNLOAD) {
fill_stream_buffer(This->stream);
This->download_state = DOWNLOADING;
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
BINDSTATUS_BEGINDOWNLOADDATA, This->url);
}
if(This->stream->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) {
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
BINDSTATUS_ENDDOWNLOADDATA, This->url);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -