You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
754 lines
19 KiB
754 lines
19 KiB
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
//
|
|
|
|
#include "activexmime.h"
|
|
|
|
#include <wininet.h>
|
|
|
|
#define GOBACKHACK
|
|
#ifdef GOBACKHACK
|
|
#include <exdisp.h> // for IWebBrowser2
|
|
#endif
|
|
|
|
#include "macros.h"
|
|
|
|
static const GUID CLSID_ActiveXMimePlayer =
|
|
{ 0xFDCDCCE0, 0xCBC4, 0x49FB, { 0x85, 0x8D, 0x92, 0x53, 0xA6, 0xB8, 0x16, 0x1F} };
|
|
|
|
extern ULONG DllAddRef(void);
|
|
extern ULONG DllRelease(void);
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------
|
|
|
|
CActiveXMimeClassFactory::CActiveXMimeClassFactory()
|
|
{
|
|
_cRef = 1;
|
|
_hr = S_OK;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CActiveXMimeClassFactory::QueryInterface(REFIID iid, void **ppv)
|
|
{
|
|
_hr = S_OK;
|
|
|
|
*ppv = NULL;
|
|
|
|
if (iid == IID_IUnknown || iid == IID_IClassFactory)
|
|
{
|
|
*ppv = (IClassFactory *)this;
|
|
}
|
|
else
|
|
{
|
|
_hr = E_NOINTERFACE;
|
|
goto exit;
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CActiveXMimeClassFactory::AddRef()
|
|
{
|
|
return (ULONG) InterlockedIncrement(&_cRef);
|
|
}
|
|
|
|
ULONG
|
|
CActiveXMimeClassFactory::Release()
|
|
{
|
|
LONG ulCount = InterlockedDecrement(&_cRef);
|
|
|
|
if (ulCount <= 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return (ULONG) ulCount;
|
|
}
|
|
|
|
HRESULT
|
|
CActiveXMimeClassFactory::LockServer(BOOL lock)
|
|
{
|
|
if (lock)
|
|
DllAddRef();
|
|
else
|
|
DllRelease();
|
|
|
|
return (_hr = S_OK);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CActiveXMimeClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID iid, void** ppv)
|
|
{
|
|
_hr = S_OK;
|
|
CActiveXMimePlayer *pMimePlayer = NULL;
|
|
|
|
*ppv = NULL;
|
|
|
|
IF_FALSE_EXIT(!pUnkOuter || iid == IID_IUnknown, CLASS_E_NOAGGREGATION);
|
|
|
|
pMimePlayer = new CActiveXMimePlayer();
|
|
IF_ALLOC_FAILED_EXIT(pMimePlayer);
|
|
|
|
if (iid == IID_IUnknown)
|
|
{
|
|
*ppv = (IOleObject *)pMimePlayer;
|
|
pMimePlayer->AddRef();
|
|
}
|
|
else
|
|
{
|
|
IF_FAILED_EXIT(pMimePlayer->QueryInterface(iid, ppv));
|
|
}
|
|
|
|
exit:
|
|
SAFERELEASE(pMimePlayer);
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------
|
|
// CActiveXMimePlayer
|
|
|
|
CActiveXMimePlayer::CActiveXMimePlayer()
|
|
{
|
|
_cRef = 1;
|
|
_hr = S_OK;
|
|
}
|
|
|
|
CActiveXMimePlayer::~CActiveXMimePlayer()
|
|
{
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::QueryInterface(REFIID iid, void** ppv)
|
|
{
|
|
_hr = S_OK;
|
|
*ppv = NULL;
|
|
|
|
if (iid == IID_IOleObject ||
|
|
iid == IID_IUnknown)
|
|
{
|
|
*ppv = (IOleObject *)this;
|
|
}
|
|
else if (iid == IID_IObjectSafety)
|
|
{
|
|
*ppv = (IObjectSafety *)this;
|
|
}
|
|
else
|
|
{
|
|
_hr = E_NOINTERFACE;
|
|
goto exit;
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CActiveXMimePlayer::AddRef()
|
|
{
|
|
return (ULONG) InterlockedIncrement(&_cRef);
|
|
}
|
|
|
|
ULONG
|
|
CActiveXMimePlayer::Release()
|
|
{
|
|
LONG ulCount = InterlockedDecrement(&_cRef);
|
|
|
|
if (ulCount <= 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return (ULONG) ulCount;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////
|
|
// IOleObject interface
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetClientSite(IOleClientSite *pClientSite)
|
|
{
|
|
_hr = S_OK;
|
|
|
|
if (pClientSite != NULL)
|
|
{
|
|
// Obtain URL from container moniker.
|
|
IMoniker* pmk = NULL;
|
|
|
|
if (SUCCEEDED(_hr = pClientSite->GetMoniker(
|
|
OLEGETMONIKER_TEMPFORUSER,
|
|
OLEWHICHMK_CONTAINER,
|
|
&pmk)))
|
|
{
|
|
LPOLESTR pwzDisplayName = NULL;
|
|
|
|
if (SUCCEEDED(_hr = pmk->GetDisplayName(NULL, NULL, &pwzDisplayName)))
|
|
{
|
|
_hr = _sURL.Assign(pwzDisplayName);
|
|
CoTaskMemFree((LPVOID)pwzDisplayName);
|
|
|
|
// _hr from _sURL.Assign() above
|
|
if (SUCCEEDED(_hr) && FAILED(StartManifestHandler(_sURL)))
|
|
MessageBox(NULL, L"Error downloading manifest or starting manifest handler. Cannot continue.", L"ClickOnce", MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
}
|
|
|
|
SAFERELEASE(pmk);
|
|
|
|
if (FAILED(_hr))
|
|
MessageBox(NULL, L"Error accessing manifest URL.", L"ClickOnce", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
#ifdef GOBACKHACK
|
|
// ask IE to go back instead of staying in the blank page
|
|
IServiceProvider* pISP = NULL;
|
|
if (SUCCEEDED(_hr = pClientSite->QueryInterface(IID_IServiceProvider, (void **)&pISP)))
|
|
{
|
|
IWebBrowser2* pIWebBrowser2 = NULL;
|
|
if (SUCCEEDED(_hr = pISP->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void **)&pIWebBrowser2)))
|
|
{
|
|
// if (FAILED(
|
|
_hr = pIWebBrowser2->GoBack();//))
|
|
// NOTICE-2002/03/12-felixybc Go back can fail if new IE window with no viewed page, Start Run url, or Internet Shortcut
|
|
// should close IE window instead?
|
|
}
|
|
SAFERELEASE(pIWebBrowser2);
|
|
}
|
|
|
|
SAFERELEASE(pISP);
|
|
#endif
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetClientSite(IOleClientSite **ppClientSite)
|
|
{
|
|
_hr = S_OK;
|
|
if (ppClientSite == NULL)
|
|
_hr = E_INVALIDARG;
|
|
else
|
|
*ppClientSite = NULL; // return clientsite?
|
|
return _hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetHostNames(LPCOLESTR szContainerApp,
|
|
/* [in] */
|
|
LPCOLESTR szContainerObj)
|
|
/* [unique][in] */
|
|
{
|
|
// note: can check the name of container app here
|
|
|
|
return (_hr = S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::Close(DWORD dwSaveOption)
|
|
/* [in] */
|
|
{
|
|
return (_hr = S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetMoniker(DWORD dwWhichMoniker,
|
|
/* [in] */
|
|
IMoniker *pmk)
|
|
/* [unique][in] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetMoniker(DWORD dwAssign,
|
|
/* [in] */
|
|
DWORD dwWhichMoniker,
|
|
/* [in] */
|
|
IMoniker **ppmk)
|
|
/* [out] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::InitFromData(IDataObject *pDataObject,
|
|
/* [unique][in] */
|
|
BOOL fCreation,
|
|
/* [in] */
|
|
DWORD dwReserved)
|
|
/* [in] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetClipboardData(DWORD dwReserved,
|
|
/* [in] */
|
|
IDataObject **ppDataObject)
|
|
/* [out] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::DoVerb(LONG iVerb,
|
|
/* [in] */
|
|
LPMSG lpmsg,
|
|
/* [unique][in] */
|
|
IOleClientSite *pActiveSite,
|
|
/* [unique][in] */
|
|
LONG lindex,
|
|
/* [in] */
|
|
HWND hwndParent,
|
|
/* [in] */
|
|
LPCRECT lprcPosRect)
|
|
/* [unique][in] */
|
|
{
|
|
return (_hr = OLEOBJ_E_NOVERBS); //E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::EnumVerbs(IEnumOLEVERB **ppEnumOleVerb)
|
|
/* [out] */
|
|
{
|
|
return (_hr = OLEOBJ_E_NOVERBS); //E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::Update( void)
|
|
{
|
|
return (_hr = S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::IsUpToDate( void)
|
|
{
|
|
return (_hr = S_OK); //OLE_E_UNAVAILABLE;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetUserClassID(CLSID *pClsid)
|
|
{
|
|
if (pClsid != NULL)
|
|
{
|
|
*pClsid = CLSID_ActiveXMimePlayer;
|
|
_hr = S_OK;
|
|
}
|
|
else
|
|
_hr = E_INVALIDARG;
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetUserType(DWORD dwFormOfType,
|
|
/* [in] */
|
|
LPOLESTR *pszUserType)
|
|
/* [out] */
|
|
{
|
|
return (_hr = OLE_S_USEREG); //E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetExtent(DWORD dwDrawAspect,
|
|
/* [in] */
|
|
SIZEL *psizel)
|
|
/* [in] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetExtent(DWORD dwDrawAspect,
|
|
/* [in] */
|
|
SIZEL *psizel)
|
|
/* [out] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::Advise(IAdviseSink *pAdvSink,
|
|
/* [unique][in] */
|
|
DWORD *pdwConnection)
|
|
/* [out] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::Unadvise(DWORD dwConnection)
|
|
/* [in] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::EnumAdvise(IEnumSTATDATA **ppenumAdvise)
|
|
/* [out] */
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetMiscStatus(DWORD dwAspect,
|
|
DWORD *pdwStatus)
|
|
{
|
|
_hr = S_OK;
|
|
|
|
// ignore dwAspect
|
|
if (pdwStatus == NULL)
|
|
_hr = E_INVALIDARG;
|
|
else
|
|
*pdwStatus = OLEMISC_SETCLIENTSITEFIRST | OLEMISC_NOUIACTIVATE; //OLEMISC_INVISIBLEATRUNTIME
|
|
return _hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetColorScheme(LOGPALETTE *pLogpal)
|
|
{
|
|
return (_hr = E_NOTIMPL);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
// IOjbectSafety interface
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::GetInterfaceSafetyOptions(REFIID riid,
|
|
DWORD* pdwSupportedOptions,
|
|
DWORD* pdwEnabledOptions)
|
|
{
|
|
_hr = S_OK;
|
|
|
|
// regardless riid
|
|
|
|
if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
|
|
_hr = E_INVALIDARG;
|
|
else
|
|
{
|
|
// do _not_ support safe for scripting - INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
|
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
|
|
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
|
|
}
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CActiveXMimePlayer::SetInterfaceSafetyOptions(REFIID riid,
|
|
DWORD dwOptionSetMask,
|
|
DWORD dwEnabledOptions)
|
|
{
|
|
_hr = E_FAIL;
|
|
|
|
if (riid == IID_IDispatch)
|
|
{
|
|
// do _not_ support IDispatch interface
|
|
// The dwOptionSetMask parameter specifies an option that is not supported by the object.
|
|
_hr = E_FAIL;
|
|
}
|
|
else //if (riid == IID_IPersist) // IID_IPersist*? what about IID_IUnknown?
|
|
{
|
|
// regardless riid
|
|
|
|
// only acknowledge if only INTERFACESAFE_FOR_UNTRUSTED_DATA is passed in
|
|
if (dwOptionSetMask == INTERFACESAFE_FOR_UNTRUSTED_DATA)
|
|
_hr = S_OK; // The object is safe for loading.
|
|
else
|
|
_hr = E_FAIL;
|
|
}
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define DEFAULT_PATH_LEN MAX_PATH
|
|
#define TEMP_FILE_NAME_LEN sizeof("preuuuu.TMP") // from msdn
|
|
HRESULT
|
|
CActiveXMimePlayer::StartManifestHandler(CString& sURL)
|
|
{
|
|
HKEY hkey = NULL;
|
|
DWORD dwcbData = 0;
|
|
DWORD dwType = 0;
|
|
LONG lReturn = 0;
|
|
CString sOpenCommand;
|
|
CString sCmdLine;
|
|
LPWSTR pwzOpenCommand = NULL;
|
|
|
|
CString sTempPath;
|
|
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
si.cb = sizeof(si);
|
|
|
|
// check if sURL empty (including ending L'\0')
|
|
// note: could do better check here, eg. check for http://
|
|
IF_FALSE_EXIT(sURL._cc > 1, E_INVALIDARG);
|
|
|
|
// assemble temp file path
|
|
|
|
IF_FAILED_EXIT(sTempPath.ResizeBuffer(DEFAULT_PATH_LEN));
|
|
|
|
{
|
|
// ISSUE-2002/03/12-felixybc GetTempPath can overrun the buffer?
|
|
DWORD dwLen = GetTempPath(DEFAULT_PATH_LEN, sTempPath._pwz);
|
|
|
|
IF_WIN32_FALSE_EXIT(dwLen);
|
|
|
|
if (dwLen >= DEFAULT_PATH_LEN)
|
|
{
|
|
// resize, add 1 for terminating null
|
|
IF_FAILED_EXIT(sTempPath.ResizeBuffer(dwLen+1));
|
|
|
|
DWORD dwLenNew = GetTempPath(dwLen+1, sTempPath._pwz);
|
|
|
|
IF_WIN32_FALSE_EXIT(dwLenNew);
|
|
|
|
IF_FALSE_EXIT(dwLenNew < dwLen+1, E_FAIL); // why is it still not enough?
|
|
}
|
|
}
|
|
|
|
// why is the temp file created already?
|
|
ASSERT(_sTempFile._pwz == NULL);
|
|
|
|
{
|
|
DWORD dwBufLen = lstrlen(sTempPath._pwz)+1;
|
|
// note: can do a better check here
|
|
IF_FALSE_EXIT(dwBufLen > 1, E_FAIL);
|
|
|
|
// allocate buffer large enough for temp path and temp file name
|
|
DWORD dwLenNew = (dwBufLen > DEFAULT_PATH_LEN)? dwBufLen : DEFAULT_PATH_LEN;
|
|
dwLenNew += TEMP_FILE_NAME_LEN;
|
|
|
|
// check for overflow
|
|
IF_FALSE_EXIT(dwLenNew > dwBufLen, E_FAIL);
|
|
|
|
IF_FAILED_EXIT(_sTempFile.ResizeBuffer(dwLenNew));
|
|
|
|
*(_sTempFile._pwz) = L'\0';
|
|
|
|
// note: temp file to be deleted by the child handler process created below
|
|
IF_WIN32_FALSE_EXIT(GetTempFileName(sTempPath._pwz, L"FMA", 0, _sTempFile._pwz)); // fusion manifest file
|
|
}
|
|
|
|
IF_FAILED_EXIT(DownloadInternetFile(sURL, _sTempFile._pwz));
|
|
|
|
// get the execution string (esp. path) from reg key
|
|
|
|
|
|
// ISSUE-2002/03/21-adriaanc
|
|
// This code should live in regclass.cpp and CRegImport/CRegEmit should accept
|
|
// a root hive handle and fall back to HKCU if not provided.
|
|
|
|
// HKEY_CLASSES_ROOT\manifestfile\shell\Open\command
|
|
lReturn = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"manifestfile\\shell\\Open\\command", 0,
|
|
KEY_EXECUTE | KEY_QUERY_VALUE, &hkey);
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
lReturn = RegQueryValueEx(hkey, NULL, NULL, &dwType, NULL, &dwcbData);
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
IF_FALSE_EXIT(dwcbData, E_FAIL);
|
|
|
|
// validate reg value type
|
|
IF_FALSE_EXIT(dwType == REG_SZ || dwType == REG_EXPAND_SZ, E_UNEXPECTED);
|
|
|
|
{
|
|
// Allocate for call to RQEX, with one extra char in case
|
|
// returned buffer is not null terminated.
|
|
LPWSTR pwz = NULL;
|
|
DWORD dwStrLen = dwcbData / sizeof(WCHAR);
|
|
DWORD dwBufLen = dwStrLen+1;
|
|
CStringAccessor<CString> acc;
|
|
|
|
// Allocate and call RQVEX
|
|
IF_ALLOC_FAILED_EXIT(pwzOpenCommand = new WCHAR[dwBufLen]);
|
|
lReturn = RegQueryValueEx(hkey, NULL, NULL,
|
|
&dwType, (LPBYTE) pwzOpenCommand, &dwcbData);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
// Null terminate returned buffer.
|
|
*(pwzOpenCommand + dwStrLen) = L'\0';
|
|
|
|
// rundll32.exe fnsshell.dll,Start "%1" --> L"rundll32.exe fnsshell.dll,Start \"%s\" \"%s\""
|
|
pwz = wcsrchr(pwzOpenCommand, L'%');
|
|
IF_NULL_EXIT(pwz, E_FAIL);
|
|
*pwz = L'\0';
|
|
|
|
// Attach accessor, set buffer, detach with corrected length.
|
|
IF_FAILED_EXIT(acc.Attach(sOpenCommand));
|
|
*(&acc) = pwzOpenCommand;
|
|
|
|
// Could avoid the strlen if we bothered to track the strlen.
|
|
IF_FAILED_EXIT(acc.Detach());
|
|
// If Detach succeeds, reset pointer so that it is freed once.
|
|
pwzOpenCommand = NULL;
|
|
}
|
|
|
|
// NTRAID#NTBUG9-574001-2002/03/12-felixybc check format of the returned string value
|
|
|
|
// assemble the command line
|
|
|
|
|
|
IF_FAILED_EXIT(sCmdLine.Assign(sOpenCommand));
|
|
IF_FAILED_EXIT(sCmdLine.Append(_sTempFile._pwz));
|
|
IF_FAILED_EXIT(sCmdLine.Append(L"\" \""));
|
|
IF_FAILED_EXIT(sCmdLine.Append(sURL));
|
|
IF_FAILED_EXIT(sCmdLine.Append(L"\""));
|
|
|
|
// start the process
|
|
|
|
// NTRAID#NTBUG9-574001-2002/03/12-felixybc string value needs proper format
|
|
// need quotes if executable path contains spaces, or instead pass lpApplicationName for better security
|
|
// rundll32.exe should be in c:\windows\system32
|
|
IF_WIN32_FALSE_EXIT(CreateProcess(NULL, sCmdLine._pwz, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi));
|
|
|
|
exit:
|
|
if(pi.hThread) CloseHandle(pi.hThread);
|
|
if(pi.hProcess) CloseHandle(pi.hProcess);
|
|
|
|
if (hkey)
|
|
RegCloseKey(hkey);
|
|
|
|
if (FAILED(_hr) && _sTempFile._pwz != NULL)
|
|
{
|
|
if (*(_sTempFile._pwz) != L'\0')
|
|
{
|
|
// ignore if error deleting the file
|
|
DeleteFile(_sTempFile._pwz);
|
|
}
|
|
_sTempFile.FreeBuffer();
|
|
}
|
|
SAFEDELETEARRAY(pwzOpenCommand);
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// download file from url into path
|
|
HRESULT
|
|
CActiveXMimePlayer::DownloadInternetFile(CString& sUrl,
|
|
LPCWSTR pwzPath)
|
|
{
|
|
HINTERNET hInternet = NULL;
|
|
HINTERNET hTransfer = NULL;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD bytesRead = 0;
|
|
DWORD bytesWritten = 0;
|
|
BYTE *buffer = NULL;
|
|
const DWORD dwBufferSize = 4096;
|
|
BOOL bReadOk = FALSE;
|
|
|
|
_hr = S_OK;
|
|
|
|
// check offline mode
|
|
/* DWORD dwState = 0;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
|
|
if(InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize))
|
|
{
|
|
if(dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
|
|
// error!
|
|
}*/
|
|
|
|
// Step 1: Create the file
|
|
// overwrites the file, if exists. file not shared
|
|
hFile = CreateFile(pwzPath, GENERIC_WRITE, 0, NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_TEMPORARY,
|
|
NULL);
|
|
|
|
IF_WIN32_FALSE_EXIT((hFile != INVALID_HANDLE_VALUE));
|
|
|
|
// Step 2: Copy the files over the internet
|
|
hInternet = InternetOpen(L"ManifestHandler", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
|
IF_WIN32_FALSE_EXIT((hInternet != NULL));
|
|
|
|
// do not keep file in wininet cache
|
|
hTransfer = InternetOpenUrl(hInternet, sUrl._pwz, NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
|
|
IF_WIN32_FALSE_EXIT((hTransfer != NULL));
|
|
|
|
// need to check if there's any error, eg. not found (404)...
|
|
|
|
buffer = new BYTE[dwBufferSize];
|
|
IF_ALLOC_FAILED_EXIT(buffer);
|
|
|
|
// synchronous download
|
|
while((bReadOk = InternetReadFile(hTransfer, buffer, dwBufferSize, &bytesRead)) && bytesRead != 0)
|
|
{
|
|
IF_WIN32_FALSE_EXIT(!( !WriteFile(hFile, buffer, bytesRead, &bytesWritten, NULL) ||
|
|
bytesWritten != bytesRead ));
|
|
}
|
|
|
|
IF_WIN32_FALSE_EXIT(bReadOk);
|
|
|
|
exit:
|
|
SAFEDELETEARRAY(buffer);
|
|
|
|
// ensure file/internet handles are closed
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFile);
|
|
if (hTransfer != NULL)
|
|
InternetCloseHandle(hTransfer);
|
|
if (hInternet != NULL)
|
|
InternetCloseHandle(hInternet);
|
|
hInternet = NULL;
|
|
hTransfer = NULL;
|
|
hFile = INVALID_HANDLE_VALUE;
|
|
|
|
// note: caller's responsibility to delete the file
|
|
|
|
return _hr;
|
|
}
|