📄 umon.c
字号:
/*
* UrlMon
*
* Copyright 1999 Ulrich Czekalla for Corel Corporation
* Copyright 2002 Huw D M Davies for CodeWeavers
* Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define COM_NO_WINDOWS_H
#include <stdarg.h>
#include <stdio.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "winuser.h"
#include "objbase.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "ole2.h"
#include "urlmon.h"
#include "wininet.h"
#include "shlwapi.h"
#include "urlmon_main.h"
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
/* native urlmon.dll uses this key, too */
static const WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
/*static BOOL registered_wndclass = FALSE;*/
typedef struct {
const IBindingVtbl *lpVtbl;
LONG ref;
LPWSTR URLName;
HWND hwndCallback;
IBindCtx *pBC;
HINTERNET hinternet, hconnect, hrequest;
HANDLE hCacheFile;
IUMCacheStream *pstrCache;
IBindStatusCallback *pbscb;
DWORD total_read, expected_size;
} Binding;
static HRESULT WINAPI Binding_QueryInterface(IBinding* iface, REFIID riid, void **ppvObject)
{
Binding *This = (Binding*)iface;
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
if((This == NULL) || (ppvObject == NULL))
return E_INVALIDARG;
if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid)) {
*ppvObject = iface;
IBinding_AddRef(iface);
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI Binding_AddRef(IBinding* iface)
{
Binding *This = (Binding*)iface;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
static ULONG WINAPI Binding_Release(IBinding* iface)
{
Binding *This = (Binding*)iface;
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%ld\n",This, ref);
if(!ref) {
HeapFree(GetProcessHeap(), 0, This->URLName);
if (This->hCacheFile)
CloseHandle(This->hCacheFile);
if (This->pstrCache)
{
UMCloseCacheFileStream(This->pstrCache);
IStream_Release((IStream *)This->pstrCache);
}
if (This->pbscb)
IBindStatusCallback_Release(This->pbscb);
HeapFree(GetProcessHeap(), 0, This);
URLMON_UnlockModule();
}
return ref;
}
static HRESULT WINAPI Binding_Abort(IBinding* iface)
{
Binding *This = (Binding*)iface;
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved)
{
Binding *This = (Binding*)iface;
FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_GetPriority(IBinding* iface, LONG* pnPriority)
{
Binding *This = (Binding*)iface;
FIXME("(%p)->(%p): stub\n", This, pnPriority);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_Resume(IBinding* iface)
{
Binding *This = (Binding*)iface;
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_SetPriority(IBinding* iface, LONG nPriority)
{
Binding *This = (Binding*)iface;
FIXME("(%p)->(%ld): stub\n", This, nPriority);
return E_NOTIMPL;
}
static HRESULT WINAPI Binding_Suspend(IBinding* iface)
{
Binding *This = (Binding*)iface;
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
}
static void Binding_CloseCacheDownload(Binding *This)
{
CloseHandle(This->hCacheFile);
This->hCacheFile = 0;
UMCloseCacheFileStream(This->pstrCache);
IStream_Release((IStream *)This->pstrCache);
This->pstrCache = 0;
}
static HRESULT Binding_MoreCacheData(Binding *This, char *buf, DWORD dwBytes)
{
DWORD written;
if (WriteFile(This->hCacheFile, buf, dwBytes, &written, NULL) && written == dwBytes)
{
HRESULT hr;
This->total_read += written;
hr = IBindStatusCallback_OnProgress(This->pbscb,
This->total_read + written,
This->expected_size,
(This->total_read == written) ?
BINDSTATUS_BEGINDOWNLOADDATA :
BINDSTATUS_DOWNLOADINGDATA,
This->URLName);
if (!hr)
{
STGMEDIUM stg;
FORMATETC fmt;
fmt.cfFormat = 0;
fmt.ptd = NULL;
fmt.dwAspect = 0;
fmt.lindex = -1;
fmt.tymed = TYMED_ISTREAM;
stg.tymed = TYMED_ISTREAM;
stg.u.pstm = (IStream *)This->pstrCache;
stg.pUnkForRelease = NULL;
hr = IBindStatusCallback_OnDataAvailable(This->pbscb,
(This->total_read == written) ?
BSCF_FIRSTDATANOTIFICATION :
BSCF_INTERMEDIATEDATANOTIFICATION,
This->total_read + written,
&fmt,
&stg);
}
if (written < dwBytes)
return STG_E_MEDIUMFULL;
else
return hr;
}
return HRESULT_FROM_WIN32(GetLastError());
}
static void Binding_FinishedDownload(Binding *This, HRESULT hr)
{
STGMEDIUM stg;
FORMATETC fmt;
fmt.ptd = NULL;
fmt.dwAspect = 0;
fmt.lindex = -1;
fmt.tymed = TYMED_ISTREAM;
stg.tymed = TYMED_ISTREAM;
stg.u.pstm = (IStream *)This->pstrCache;
stg.pUnkForRelease = NULL;
IBindStatusCallback_OnProgress(This->pbscb, This->total_read, This->expected_size,
BINDSTATUS_ENDDOWNLOADDATA, This->URLName);
IBindStatusCallback_OnDataAvailable(This->pbscb, BSCF_LASTDATANOTIFICATION, This->total_read, &fmt, &stg);
if (hr)
{
WCHAR *pwchError = 0;
FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, (DWORD) hr,
0, (LPWSTR) &pwchError,
0, NULL);
if (!pwchError)
{
static const WCHAR achFormat[] = { '%', '0', '8', 'x', 0 };
pwchError =(WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * 9);
wsprintfW(pwchError, achFormat, hr);
}
IBindStatusCallback_OnStopBinding(This->pbscb, hr, pwchError);
LocalFree(pwchError);
}
else
{
IBindStatusCallback_OnStopBinding(This->pbscb, hr, NULL);
}
IBindStatusCallback_Release(This->pbscb);
This->pbscb = 0;
}
static const IBindingVtbl BindingVtbl =
{
Binding_QueryInterface,
Binding_AddRef,
Binding_Release,
Binding_Abort,
Binding_Suspend,
Binding_Resume,
Binding_SetPriority,
Binding_GetPriority,
Binding_GetBindResult
};
/* filemoniker data structure */
typedef struct {
const IMonikerVtbl* lpvtbl; /* VTable relative to the IMoniker interface.*/
LONG ref; /* reference counter for this object */
LPOLESTR URLName; /* URL string identified by this URLmoniker */
} URLMonikerImpl;
/*******************************************************************************
* URLMoniker_QueryInterface
*******************************************************************************/
static HRESULT WINAPI URLMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
/* Perform a sanity check on the parameters.*/
if ( (This==0) || (ppvObject==0) )
return E_INVALIDARG;
/* Initialize the return parameter */
*ppvObject = 0;
/* Compare the riid with the interface IDs implemented by this object.*/
if (IsEqualIID(&IID_IUnknown, riid) ||
IsEqualIID(&IID_IPersist, riid) ||
IsEqualIID(&IID_IPersistStream,riid) ||
IsEqualIID(&IID_IMoniker, riid)
)
*ppvObject = iface;
/* Check that we obtained an interface.*/
if ((*ppvObject)==0)
return E_NOINTERFACE;
/* Query Interface always increases the reference count by one when it is successful */
IMoniker_AddRef(iface);
return S_OK;
}
/******************************************************************************
* URLMoniker_AddRef
******************************************************************************/
static ULONG WINAPI URLMonikerImpl_AddRef(IMoniker* iface)
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);
return refCount;
}
/******************************************************************************
* URLMoniker_Release
******************************************************************************/
static ULONG WINAPI URLMonikerImpl_Release(IMoniker* iface)
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);
/* destroy the object if there's no more reference on it */
if (!refCount) {
HeapFree(GetProcessHeap(),0,This->URLName);
HeapFree(GetProcessHeap(),0,This);
URLMON_UnlockModule();
}
return refCount;
}
/******************************************************************************
* URLMoniker_GetClassID
******************************************************************************/
static HRESULT WINAPI URLMonikerImpl_GetClassID(IMoniker* iface,
CLSID *pClassID)/* Pointer to CLSID of object */
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
TRACE("(%p,%p)\n",This,pClassID);
if (pClassID==NULL)
return E_POINTER;
/* Windows always returns CLSID_StdURLMoniker */
*pClassID = CLSID_StdURLMoniker;
return S_OK;
}
/******************************************************************************
* URLMoniker_IsDirty
******************************************************************************/
static HRESULT WINAPI URLMonikerImpl_IsDirty(IMoniker* iface)
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
/* Note that the OLE-provided implementations of the IPersistStream::IsDirty
method in the OLE-provided moniker interfaces always return S_FALSE because
their internal state never changes. */
TRACE("(%p)\n",This);
return S_FALSE;
}
/******************************************************************************
* URLMoniker_Load
*
* NOTE
* Writes a ULONG containing length of unicode string, followed
* by that many unicode characters
******************************************************************************/
static HRESULT WINAPI URLMonikerImpl_Load(IMoniker* iface,IStream* pStm)
{
URLMonikerImpl *This = (URLMonikerImpl *)iface;
HRESULT res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -