773 lines
19 KiB
C++
773 lines
19 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: cdlprot.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <eapp.h>
|
|
#include <tchar.h>
|
|
#ifdef unix
|
|
#include "../download/cdl.h"
|
|
#else
|
|
#include "..\download\cdl.h"
|
|
#endif /* !unix */
|
|
|
|
|
|
// From shlwapip.h
|
|
LWSTDAPI_(HRESULT) CLSIDFromStringWrap(LPOLESTR lpsz, LPCLSID pclsid);
|
|
|
|
|
|
#define VALUE_EQUAL_CHAR '='
|
|
#define VALUE_SEPARATOR_CHAR ';'
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::CCdlProtocol
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCdlProtocol::CCdlProtocol(REFCLSID rclsid, IUnknown *pUnkOuter,
|
|
IUnknown **ppUnkInner)
|
|
: CBaseProtocol(rclsid, pUnkOuter, ppUnkInner)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::CCdlProtocol \n", this));
|
|
|
|
DllAddRef();
|
|
|
|
_clsidReport = CLSID_NULL;
|
|
_pCodeDLBSC = NULL;
|
|
_fDataPending = TRUE;
|
|
_fNotStarted = TRUE;
|
|
_iid = IID_IUnknown;
|
|
_pbc = NULL;
|
|
_fGetClassObject = FALSE;
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::CCdlProtocol \n", this));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::~CCdlProtocol
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCdlProtocol::~CCdlProtocol()
|
|
{
|
|
if (_pbc)
|
|
{
|
|
_pbc->Release();
|
|
}
|
|
|
|
DllRelease();
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN/OUT CCdlProtocol::~CCdlProtocol \n", this));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::Start
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifdef _WIN64
|
|
LWSTDAPI_(BOOL) StrToInt64ExW(LPCWSTR pszString, DWORD dwFlags, LONGLONG * pllRet);
|
|
#endif
|
|
|
|
STDMETHODIMP CCdlProtocol::Start(LPCWSTR pwzUrl,
|
|
IOInetProtocolSink *pIOInetProtocolSink,
|
|
IOInetBindInfo *pIOInetBindInfo,
|
|
DWORD grfSTI,
|
|
DWORD_PTR dwReserved)
|
|
{
|
|
DWORD cElFetched = 0;
|
|
LPOLESTR pwzIID = NULL;
|
|
BINDINFO bindinfo;
|
|
DWORD grfBINDF = 0;
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Start\n", this));
|
|
HRESULT hr = NOERROR;
|
|
WCHAR wzURL[MAX_URL_SIZE];
|
|
|
|
EProtAssert((!_pProtSink && pIOInetBindInfo && pIOInetProtocolSink));
|
|
EProtAssert((_pwzUrl == NULL));
|
|
|
|
bindinfo.cbSize = sizeof(BINDINFO);
|
|
pIOInetBindInfo->GetBindInfo(&grfBINDF, &bindinfo);
|
|
|
|
if (grfBINDF & BINDF_GETCLASSOBJECT)
|
|
{
|
|
LPWSTR pwzBC = NULL;
|
|
DWORD cElFetched = 0;
|
|
|
|
hr = pIOInetBindInfo->GetBindString(BINDSTRING_PTR_BIND_CONTEXT,
|
|
&pwzBC, 0,
|
|
&cElFetched);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
#ifdef _WIN64
|
|
StrToInt64ExW(pwzBC, 0, (LONGLONG *)&_pbc);
|
|
#else
|
|
_pbc = (IBindCtx *)StrToIntW(pwzBC);
|
|
#endif
|
|
|
|
EProtAssert(_pbc);
|
|
|
|
delete [] pwzBC;
|
|
pwzBC = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto Exit;
|
|
}
|
|
|
|
_fGetClassObject = TRUE;
|
|
}
|
|
|
|
grfSTI |= PI_FORCE_ASYNC;
|
|
hr = CBaseProtocol::Start(pwzUrl, pIOInetProtocolSink, pIOInetBindInfo, grfSTI, dwReserved);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIOInetBindInfo->GetBindString(BINDSTRING_IID, &pwzIID, 0,
|
|
&cElFetched);
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = CLSIDFromString(pwzIID, &_iid);
|
|
delete [] pwzIID;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ParseURL();
|
|
}
|
|
|
|
Exit:
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Start (hr:%lx)\n",this, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::Continue
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::Continue(PROTOCOLDATA *pStateInfoIn)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Continue\n", this));
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (_fNotStarted && pStateInfoIn->dwState == CDL_STATE_BIND)
|
|
{
|
|
_fNotStarted = FALSE;
|
|
hr = ParseURL();
|
|
}
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Continue (hr:%lx)\n",this, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::Read
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::Read(void *pv,ULONG cb,ULONG *pcbRead)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Read\n", this));
|
|
HRESULT hr;
|
|
|
|
hr = (_fDataPending) ? (E_PENDING) : (S_FALSE);
|
|
*pcbRead = (_fDataPending) ? (0x0) : (0x100);
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Read\n", this));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::Abort
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::Abort(HRESULT hrReason, DWORD dwOptions)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Abort\n", this));
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
EProtAssert( _pCodeDLBSC != NULL );
|
|
if (_pCodeDLBSC != NULL)
|
|
{
|
|
hr = _pCodeDLBSC->Abort();
|
|
}
|
|
|
|
#if 0
|
|
if (_pProtSink)
|
|
{
|
|
hr = CBaseProtocol::Abort(hrReason, dwOptions);
|
|
}
|
|
#endif
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Abort\n", this));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::Seek
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
|
|
ULARGE_INTEGER *plibNewPosition)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Seek\n", this));
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Seek\n", this));
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::LockRequest
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::LockRequest(DWORD dwOptions)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::LockRequest\n", this));
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::LockRequest\n", this));
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::UnlockRequest
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::UnlockRequest()
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::UnlockRequest\n", this));
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::UnlockRequest\n", this));
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::ParseURL
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCdlProtocol::ParseURL()
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::ParseURL\n", this));
|
|
HRESULT hr = MK_E_SYNTAX;
|
|
WCHAR wzlURL[MAX_URL_SIZE];
|
|
LPWSTR pwz = NULL;
|
|
LPWSTR pwzValue = NULL;
|
|
LPWSTR pwzTag = NULL;
|
|
LPWSTR pwzPound = NULL;
|
|
BOOL fGotRequiredField = FALSE;
|
|
CodeDownloadData cdldata;
|
|
CHAR szValue[MAX_PATH];
|
|
|
|
cdldata.szDistUnit = NULL;
|
|
cdldata.szClassString = NULL;
|
|
cdldata.szURL = NULL;
|
|
cdldata.szMimeType = NULL;
|
|
cdldata.szExtension = NULL;
|
|
cdldata.szDll = NULL;
|
|
cdldata.dwFileVersionMS = 0;
|
|
cdldata.dwFileVersionLS = 0;
|
|
cdldata.dwFlags = 0;
|
|
|
|
|
|
// URL is of the form:
|
|
// (1) cdl://[unused]?[clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
|
|
// [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
|
|
// [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];...
|
|
//
|
|
// OR
|
|
//
|
|
// (2) cdl:[clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
|
|
// [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];...
|
|
//
|
|
//
|
|
// NOTE: [distunit=xxx] added to support AsyncInstallDistributionUnit
|
|
// [flags=xxx] added flags (as an integer so that we can dictate
|
|
// silent mode, async. etc.
|
|
|
|
wcscpy(wzlURL, _wzFullURL);
|
|
|
|
// ensure correct format: "cdl://[stuff]?"
|
|
|
|
pwz = wcschr(wzlURL, ':');
|
|
pwz++;
|
|
if (!(wcsnicmp(pwz, L"//", 2) && wcsnicmp(pwz, L"\\\\", 2)))
|
|
{
|
|
// URL is of form (1)
|
|
pwz = wcschr(pwz, '?');
|
|
if( pwz == NULL ) {
|
|
// error, no '?' found
|
|
hr = MK_E_SYNTAX;
|
|
goto Exit;
|
|
}
|
|
pwz++; // pwz now points to the start of the param list (start boundry)
|
|
}
|
|
|
|
pwzValue = pwz + wcslen( pwz ); // points to NULL
|
|
|
|
|
|
// If there is a pound, NULL terminate there instead
|
|
|
|
pwzPound = pwzValue - 1;
|
|
|
|
while (pwzPound >= pwz)
|
|
{
|
|
if (*pwzPound == VALUE_POUND_CHAR)
|
|
{
|
|
*pwzPound = NULL;
|
|
pwzValue = pwzPound;
|
|
break;
|
|
}
|
|
pwzPound--;
|
|
}
|
|
|
|
for ( ;; )
|
|
{
|
|
while (pwzValue >= pwz && *pwzValue != VALUE_EQUAL_CHAR &&
|
|
*pwzValue != VALUE_SEPARATOR_CHAR)
|
|
{
|
|
pwzValue--;
|
|
}
|
|
if (pwzValue < pwz || *pwzValue == VALUE_SEPARATOR_CHAR)
|
|
{
|
|
// error, expected '='
|
|
hr = MK_E_SYNTAX;
|
|
goto Exit;
|
|
}
|
|
|
|
// pwzValue now points to '='
|
|
*pwzValue = NULL;
|
|
pwzTag = pwzValue;
|
|
pwzValue++;
|
|
|
|
while (pwzTag >= pwz && *pwzTag != VALUE_EQUAL_CHAR &&
|
|
*pwzTag != VALUE_SEPARATOR_CHAR)
|
|
{
|
|
pwzTag--;
|
|
}
|
|
if (*pwzTag == VALUE_EQUAL_CHAR)
|
|
{
|
|
// error, expected either a separator, or the beginning
|
|
hr = MK_E_SYNTAX;
|
|
goto Exit;
|
|
}
|
|
pwzTag++;
|
|
|
|
if (!wcsicmp(L"codebase", pwzTag))
|
|
{
|
|
cdldata.szURL = pwzValue;
|
|
}
|
|
else if (!wcsicmp(L"clsid", pwzTag))
|
|
{
|
|
cdldata.szClassString = pwzValue;
|
|
fGotRequiredField = TRUE;
|
|
}
|
|
else if (!wcsicmp(L"mimetype", pwzTag))
|
|
{
|
|
cdldata.szMimeType = pwzValue;
|
|
fGotRequiredField = TRUE;
|
|
}
|
|
else if (!wcsicmp(L"extension", pwzTag))
|
|
{
|
|
cdldata.szExtension = pwzValue;
|
|
fGotRequiredField = TRUE;
|
|
}
|
|
else if (!wcsicmp(L"verMS", pwzTag))
|
|
{
|
|
//cdldata.dwFileVersionMS = _wtol(pwzValue);
|
|
W2A(pwzValue, szValue, MAX_PATH);
|
|
cdldata.dwFileVersionMS = atol(szValue);
|
|
|
|
}
|
|
else if (!wcsicmp(L"verLS", pwzTag))
|
|
{
|
|
//cdldata.dwFileVersionLS = _wtol(pwzValue);
|
|
W2A(pwzValue, szValue, MAX_PATH);
|
|
cdldata.dwFileVersionLS = atol(szValue);
|
|
}
|
|
else if (!wcsicmp(L"distunit", pwzTag))
|
|
{
|
|
cdldata.szDistUnit = pwzValue;
|
|
fGotRequiredField = TRUE;
|
|
}
|
|
else if (!wcsicmp(L"flags", pwzTag))
|
|
{
|
|
cdldata.dwFlags = StrToIntW(pwzValue);
|
|
}
|
|
else if (!wcsicmp(L"version", pwzTag))
|
|
{
|
|
W2A(pwzValue, szValue, MAX_PATH);
|
|
GetVersionFromString(szValue, &(cdldata.dwFileVersionMS), &(cdldata.dwFileVersionLS));
|
|
}
|
|
else if (!wcsicmp(L"dllname",pwzTag))
|
|
{
|
|
cdldata.szDll = pwzValue;
|
|
}
|
|
|
|
if (pwzTag <= pwz)
|
|
{
|
|
break; // we are done
|
|
}
|
|
else
|
|
{
|
|
pwzValue = pwzTag;
|
|
pwzValue--;
|
|
*pwzValue = NULL;
|
|
pwzTag = NULL;
|
|
}
|
|
}
|
|
|
|
// backwards compatability with clsid can be dist unit
|
|
if(cdldata.szClassString && ! cdldata.szDistUnit)
|
|
{
|
|
cdldata.szDistUnit = cdldata.szClassString;
|
|
}
|
|
if(cdldata.szDistUnit && ! cdldata.szClassString)
|
|
{
|
|
cdldata.szClassString = cdldata.szDistUnit;
|
|
}
|
|
|
|
if (fGotRequiredField)
|
|
{
|
|
// The client must provide a host security manager for
|
|
// CDL:// protocol bindings. Otherwise, a file:// URL codebase
|
|
// will be executed without WVT UI.
|
|
|
|
IInternetHostSecurityManager *phsm = NULL;
|
|
IServiceProvider *psp = NULL;
|
|
|
|
hr = _pProtSink->QueryInterface(IID_IServiceProvider,
|
|
(void **)&psp);
|
|
if (FAILED(hr)) {
|
|
hr = TRUST_E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = psp->QueryService(IID_IInternetHostSecurityManager,
|
|
IID_IInternetHostSecurityManager, (void **)&phsm);
|
|
|
|
if (FAILED(hr)) {
|
|
hr = TRUST_E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
psp->Release();
|
|
phsm->Release();
|
|
|
|
if (IsEqualGUID(_clsidReport , CLSID_NULL))
|
|
CLSIDFromString((LPOLESTR)cdldata.szClassString, &_clsidReport);
|
|
hr = StartDownload(cdldata);
|
|
}
|
|
else
|
|
{
|
|
hr = MK_E_SYNTAX;
|
|
}
|
|
|
|
Exit:
|
|
|
|
// if we error for any reason here, then CodeDL BSC was never initiated and we will
|
|
// never get an BSC::OSB to shut up sink.
|
|
|
|
if (hr != E_PENDING)
|
|
{
|
|
_fDataPending = FALSE;
|
|
|
|
if (_pProtSink)
|
|
{
|
|
if (!IsEqualGUID(_clsidReport, CLSID_NULL))
|
|
{
|
|
LPOLESTR pwzStrClsId;
|
|
StringFromCLSID(_clsidReport, &pwzStrClsId);
|
|
_pProtSink->ReportProgress(BINDSTATUS_CLSIDCANINSTANTIATE, pwzStrClsId);
|
|
|
|
delete [] pwzStrClsId;
|
|
}
|
|
|
|
_pProtSink->ReportResult(hr, 0, 0);
|
|
}
|
|
}
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::ParseURL\n", this));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::StartDownload
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CCdlProtocol::StartDownload(CodeDownloadData &cdldata)
|
|
{
|
|
EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::StartDownload\n", this));
|
|
HRESULT hr = S_OK;
|
|
IBindCtx *pbc = NULL;
|
|
IUnknown *pUnk = NULL;
|
|
|
|
// Kick off the download
|
|
|
|
_pCodeDLBSC = new CCodeDLBSC(_pProtSink, _pOIBindInfo, this, _fGetClassObject);
|
|
if (_pCodeDLBSC == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
hr = CreateBindCtx(0, &pbc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = RegisterBindStatusCallback(pbc, _pCodeDLBSC, NULL, 0);
|
|
if (_pCodeDLBSC != NULL)
|
|
{
|
|
_pCodeDLBSC->Release();
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
cdldata.dwFlags = (_fGetClassObject) ? (CD_FLAGS_NEED_CLASSFACTORY) : (0);
|
|
|
|
hr = AsyncInstallDistributionUnitEx(&cdldata, pbc, _iid, &pUnk, NULL);
|
|
|
|
if (hr == MK_S_ASYNCHRONOUS)
|
|
{
|
|
hr = E_PENDING;
|
|
}
|
|
else
|
|
{
|
|
if (_fGetClassObject)
|
|
{
|
|
if (pUnk && SUCCEEDED(hr))
|
|
{
|
|
hr = RegisterIUnknown(pUnk);
|
|
pUnk->Release();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _pProtSink->ReportProgress(BINDSTATUS_IUNKNOWNAVAILABLE, NULL);
|
|
}
|
|
}
|
|
_pProtSink->ReportResult(hr, 0, 0);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (pbc != NULL)
|
|
{
|
|
// NOTE: This instruction can cause deletion of this object,
|
|
// referencing "this" afterwords may be a bad idea.
|
|
pbc->Release();
|
|
}
|
|
|
|
EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::StartDownload\n", this));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::SetDataPending
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 02-06-1997 t-alans (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCdlProtocol::SetDataPending(BOOL fPending)
|
|
{
|
|
_fDataPending = fPending;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CCdlProtocol::RegisterIUnknown
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-12-1998 AlanShi (Alan Shi) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCdlProtocol::RegisterIUnknown(IUnknown *pUnk)
|
|
{
|
|
EProtAssert(_pbc);
|
|
|
|
return _pbc->RegisterObjectParam(SZ_IUNKNOWN_PTR, pUnk);
|
|
}
|
|
|