URLDownloadToFile
http 를 이용해 파일을 다운받기 위한 함수. 예전에 잠깐 테스트를 위해서 써본적이 있고, 단순히 파일을 받는것에는 아무 문제가 없었다. 하지만 당시 일반적인 http request 가 아니었기 때문에 http socket class 를 코딩했었다. URLDownloadToFile 자체 보다는 콜백 인터페이스를 상속받아서 구현한 부분이 오히려 가치가 있는 소스다.
source
부를때
CBindTransferStatus m_bindTransfer;
...
...
HRESULT hr = URLDownloadToFile(NULL, "http://a.b.c/d.avi", "c:\\d.avi", dwReserved, &m_bindTransfer);
콜백 인터페이스 구현
CBindTransferStatus.h
#include <urlmon.h>
#pragma comment(lib, "urlmon.lib")
class CBindTransferStatus : public IBindStatusCallback
{
public:
CBindTransferStatus();
virtual ~CBindTransferStatus();
//////////////////////////////////////////////////////////////////////////////////////////
// callee 의 포인터 저장
//////////////////////////////////////////////////////////////////////////////////////////
protected:
CComicGetDlg* m_pThis;
public:
void Init(CComicGetDlg* pThis){m_pThis=pThis;};
//////////////////////////////////////////////////////////////////////////////////////////
// IUnknown Method 구현
//////////////////////////////////////////////////////////////////////////////////////////
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj);
//////////////////////////////////////////////////////////////////////////////////////////
// IBindStatusCallback Method 구현
//////////////////////////////////////////////////////////////////////////////////////////
STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindinfo);
STDMETHOD(GetPriority)(LONG *pnPriotity);
STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc, STGMEDIUM *pstgmed);
STDMETHOD(OnLowResource)(DWORD dwReserved);
STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown* punk);
STDMETHOD(OnProgress)(ULONG ulProgess, ULONG ulProgessMax, ULONG ulStatusCode, LPCWSTR szStatusCode);
STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pbinding);
STDMETHOD(OnStopBinding)(HRESULT hrStatus, LPCWSTR szStatusText);
};
CBindTransferStatus.cpp
CBindTransferStatus::CBindTransferStatus()
{
}
CBindTransferStatus::~CBindTransferStatus()
{
}
STDMETHODIMP_(ULONG) CBindTransferStatus::AddRef()
{
return 1;
}
STDMETHODIMP_(ULONG) CBindTransferStatus::Release()
{
return 0;
}
STDMETHODIMP CBindTransferStatus::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
if( iid == __uuidof(IBindStatusCallback) ) {
*ppvObj = (IBindStatusCallback*)this;
return S_OK;
}
else if( iid == __uuidof(IUnknown) ) {
*ppvObj = (IUnknown*)this;
return S_OK;
}
return E_NOINTERFACE;
}
// Provides information about how the bind operation should be handled when called by an asynchronous moniker.
STDMETHODIMP CBindTransferStatus::GetBindInfo(DWORD* pgrfBINDF, BINDINFO *pbindinfo)
{
#ifdef _DEBUG
CString strHowBound;
switch( *pgrfBINDF )
{
case 0x00000001:strHowBound = "BINDF_ASYNCHRONOUS";break;
case 0x00000002:strHowBound = "BINDF_ASYNCSTORAGE";break;
case 0x00000004:strHowBound = "BINDF_NOPROGRESSIVERENDERING";break;
case 0x00000008:strHowBound = "BINDF_OFFLINEOPERATION";break;
case 0x00000010:strHowBound = "BINDF_GETNEWESTVERSION";break;
case 0x00000020:strHowBound = "BINDF_NOWRITECACHE";break;
case 0x00000040:strHowBound = "BINDF_NEEDFILE";break;
case 0x00000080:strHowBound = "BINDF_PULLDATA";break;
case 0x00000100:strHowBound = "BINDF_IGNORESECURITYPROBLEM";break;
case 0x00000200:strHowBound = "BINDF_RESYNCHRONIZE";break;
case 0x00000400:strHowBound = "BINDF_HYPERLINK";break;
case 0x00000800:strHowBound = "BINDF_NO_UI";break;
case 0x00001000:strHowBound = "BINDF_SILENTOPERATION";break;
case 0x00002000:strHowBound = "BINDF_PRAGMA_NO_CACHE";break;
case 0x00004000:strHowBound = "BINDF_GETCLASSOBJECT";break;
case 0x00008000:strHowBound = "BINDF_RESERVED_1";break;
case 0x00010000:strHowBound = "BINDF_FREE_THREADED";break;
case 0x00020000:strHowBound = "BINDF_DIRECT_READ";break;
case 0x00040000:strHowBound = "BINDF_FORMS_SUBMIT";break;
case 0x00080000:strHowBound = "BINDF_GETFROMCACHE_IF_NET_FAIL";break;
case 0x00100000:strHowBound = "BINDF_FROMURLMON";break;
case 0x00200000:strHowBound = "BINDF_FWD_BACK";break;
case 0x00400000:strHowBound = "BINDF_RESERVED_2";break;
case 0x00800000:strHowBound = "BINDF_RESERVED_3";break;
default:strHowBound="*UNKNOWN*";
}
TRACE("GetBindInfo Called, how : %s\n", strHowBound );
#endif
return S_NOTIMPL;
}
// Obtains the priority for the bind operation when called by an asynchronous moniker.
STDMETHODIMP CBindTransferStatus::GetPriority(LONG* pnPriority)
{
TRACE("GetPriority Called\n");
return E_NOTIMPL;
}
// Provides data to the client as it becomes available during asynchronous bind operations
STDMETHODIMP CBindTransferStatus::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc, STGMEDIUM* pstgmed)
{
TRACE("OnDataAvailable Called\n");
return E_NOTIMPL;
}
// Not currently implemented
STDMETHODIMP CBindTransferStatus::OnLowResource(DWORD dwReserved)
{
return E_NOTIMPL;
}
// Passes the requested object interface pointer to the client.
STDMETHODIMP CBindTransferStatus::OnObjectAvailable(REFIID riid, IUnknown* punk)
{
TRACE("OnObjectAvailable Called\n");
return E_NOTIMPL;
}
STDMETHODIMP CBindTransferStatus::OnProgress(ULONG ulProgess, ULONG ulProgessMax, ULONG ulStatusCode, LPCWSTR szStatusCode)
{
return E_NOTIMPL;
}
STDMETHODIMP CBindTransferStatus::OnStartBinding(DWORD dwReserved, IBinding* pbinding)
{
return E_NOTIMPL;
}
STDMETHODIMP CBindTransferStatus::OnStopBinding(HRESULT hrStatus, LPCWSTR szStatusText)
{
return E_NOTIMPL;
}