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.
866 lines
23 KiB
866 lines
23 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
|
//
|
|
// File: object.cxx
|
|
//
|
|
// Contents: Implementation of the CLocalMTProxy class and
|
|
// associated objects.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.hxx"
|
|
|
|
#include "mtscript.h" // MIDL generated file
|
|
#include "localobj.h"
|
|
|
|
long g_lObjectCount = 0;
|
|
|
|
// ***********************************************************************
|
|
//
|
|
// CLocalProxyCP
|
|
//
|
|
// ConnectionPoint for CLocalMTProxy
|
|
//
|
|
// ***********************************************************************
|
|
|
|
CLocalProxyCP::CLocalProxyCP(CLocalMTProxy *pMach)
|
|
{
|
|
_ulRefs = 1;
|
|
_pMTProxy = pMach;
|
|
_pMTProxy->AddRef();
|
|
}
|
|
|
|
CLocalProxyCP::~CLocalProxyCP()
|
|
{
|
|
_pMTProxy->Release();
|
|
}
|
|
|
|
HRESULT
|
|
CLocalProxyCP::QueryInterface(REFIID iid, void **ppv)
|
|
{
|
|
if (iid == IID_IUnknown || iid == IID_IConnectionPoint)
|
|
{
|
|
*ppv = (IConnectionPoint *)this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CLocalProxyCP::GetConnectionInterface(IID * pIID)
|
|
{
|
|
*pIID = DIID_DRemoteMTScriptEvents;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CLocalProxyCP::GetConnectionPointContainer(IConnectionPointContainer ** ppCPC)
|
|
{
|
|
*ppCPC = _pMTProxy;
|
|
(*ppCPC)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalProxyCP::Advise, public
|
|
//
|
|
// Synopsis: Remembers interface pointers that we want to fire events
|
|
// through.
|
|
//
|
|
// Arguments: [pUnkSink] -- Pointer to remember
|
|
// [pdwCookie] -- Place to put cookie for Unadvise
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalProxyCP::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
|
|
{
|
|
IDispatch *pDisp;
|
|
HRESULT hr;
|
|
|
|
TraceTag((tagError, "CLocalProxyCP::Advise: Advising %p", pUnkSink));
|
|
|
|
hr = pUnkSink->QueryInterface(IID_IDispatch, (LPVOID*)&pDisp);
|
|
if (hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// We can only keep one sink at a time.
|
|
|
|
ReleaseInterface(_pMTProxy->_pDispSink);
|
|
|
|
_pMTProxy->_pDispSink = pDisp;
|
|
|
|
*pdwCookie = (DWORD)pDisp;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalProxyCP::Unadvise, public
|
|
//
|
|
// Synopsis: Forgets a pointer we remembered during Advise.
|
|
//
|
|
// Arguments: [dwCookie] -- Cookie returned from Advise
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalProxyCP::Unadvise(DWORD dwCookie)
|
|
{
|
|
TraceTag((tagError, "CLocalProxyCP::Unadvise: Unadvising %p", dwCookie));
|
|
|
|
if (dwCookie == (DWORD)_pMTProxy->_pDispSink)
|
|
{
|
|
ClearInterface(&_pMTProxy->_pDispSink);
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CLocalProxyCP::EnumConnections(LPENUMCONNECTIONS * ppEnum)
|
|
{
|
|
*ppEnum = NULL;
|
|
RRETURN(E_NOTIMPL);
|
|
}
|
|
|
|
// ***********************************************************************
|
|
//
|
|
// CLocalMTProxy
|
|
//
|
|
// ***********************************************************************
|
|
|
|
CLocalMTProxy::CLocalMTProxy()
|
|
{
|
|
_ulRefs = 1;
|
|
_ulAllRefs = 1;
|
|
|
|
InterlockedIncrement(&g_lObjectCount);
|
|
|
|
Assert(_pTypeInfoInterface == NULL);
|
|
Assert(_pTypeLibDLL == NULL);
|
|
}
|
|
|
|
CLocalMTProxy::~CLocalMTProxy()
|
|
{
|
|
ReleaseInterface(_pTypeInfoInterface);
|
|
ReleaseInterface(_pTypeInfoCM);
|
|
ReleaseInterface(_pTypeLibDLL);
|
|
|
|
InterlockedDecrement(&g_lObjectCount);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::Passivate, public
|
|
//
|
|
// Synopsis: Called when the refcount for CLocalMTProxy goes to zero. This
|
|
// will cause us to let go of all the objects we hold onto, which
|
|
// in turn should cause everyone else to let go of our subobjects.
|
|
// When that happens we can finally delete ourselves.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
CLocalMTProxy::Passivate()
|
|
{
|
|
Disconnect();
|
|
|
|
ClearInterface(&_pDispSink);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::QueryInterface, public
|
|
//
|
|
// Synopsis: Standard IUnknown::QueryInterface
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
if (iid == IID_IRemoteMTScriptProxy || iid == IID_IUnknown || iid == IID_IDispatch)
|
|
{
|
|
*ppvObj = (IRemoteMTScriptProxy *)this;
|
|
}
|
|
else if (iid == IID_IConnectionPointContainer)
|
|
{
|
|
*ppvObj = (IConnectionPointContainer *)this;
|
|
}
|
|
else if (iid == IID_IProvideClassInfo)
|
|
{
|
|
*ppvObj = (IProvideClassInfo *)this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
((IUnknown *)*ppvObj)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::AddRef, public
|
|
//
|
|
// Synopsis: Standard IUnknown::AddRef. Increments the refcount on the
|
|
// CLocalMTProxy object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CLocalMTProxy::AddRef()
|
|
{
|
|
return ++_ulRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::Release, public
|
|
//
|
|
// Synopsis: IUnknown::Release.
|
|
//
|
|
// Notes: If the refcount on CLocalMTProxy goes to zero, we know our
|
|
// owner is done with us and we can clean up. So, we release
|
|
// all our interface pointers and etc. However, someone may still
|
|
// be holding on to our event sink subobject, so we can't
|
|
// delete ourselves yet.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CLocalMTProxy::Release()
|
|
{
|
|
ULONG ulRefs = --_ulRefs;
|
|
|
|
if (ulRefs == 0)
|
|
{
|
|
_ulRefs = ULREF_IN_DESTRUCTOR;
|
|
|
|
Passivate();
|
|
|
|
AssertSz(_ulRefs == ULREF_IN_DESTRUCTOR,
|
|
"NONFATAL: Invalid refcount during passivate!");
|
|
|
|
_ulRefs = 0;
|
|
|
|
SubRelease();
|
|
}
|
|
|
|
return ulRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::SubAddRef, public
|
|
//
|
|
// Synopsis: Called when the event sink gets addref'd. Increments an overall
|
|
// refcount.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CLocalMTProxy::SubAddRef()
|
|
{
|
|
return ++_ulAllRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::SubRelease, public
|
|
//
|
|
// Synopsis: Called when the event sink gets released and when
|
|
// CLocalMTProxy passivates. If the overall refcount is zero,
|
|
// we know no-one is using us and we can go away.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CLocalMTProxy::SubRelease()
|
|
{
|
|
if (--_ulAllRefs == 0)
|
|
{
|
|
_ulAllRefs = ULREF_IN_DESTRUCTOR;
|
|
_ulRefs = ULREF_IN_DESTRUCTOR;
|
|
delete this;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::EnumConnectionPoints, IConnectionPointContainer
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::EnumConnectionPoints(LPENUMCONNECTIONPOINTS *)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::FindConnectionPoint, IConnectionPointContainer
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::FindConnectionPoint(REFIID iid, LPCONNECTIONPOINT* ppCpOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceTag((tagError, "CLocalMTProxy::FindConnectionPoint called."));
|
|
|
|
if (iid == DIID_DRemoteMTScriptEvents || iid == IID_IDispatch)
|
|
{
|
|
TraceTag((tagError, "CLocalMTProxy::FindConnectionPoint: Returning event source."));
|
|
|
|
*ppCpOut = new CLocalProxyCP(this);
|
|
hr = *ppCpOut ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::GetClassInfo, public
|
|
//
|
|
// Synopsis: Implementation of IProvideClassInfo
|
|
//
|
|
// Arguments: [pTI] -- Return type info interface here
|
|
//
|
|
// Notes: This returns the typeinfo for the RemoteMTScriptProxy coclass
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::GetClassInfo(ITypeInfo **pTI)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceTag((tagError, "CLocalMTProxy::GetClassInfo called"));
|
|
|
|
hr = LoadTypeLibs();
|
|
if (hr)
|
|
return hr;
|
|
|
|
hr = _pTypeLibDLL->GetTypeInfoOfGuid(CLSID_RemoteMTScriptProxy, pTI);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::GetTypeInfo, IDispatch
|
|
//
|
|
// Notes: This returns the typeinfo for the IRemoteMTScriptProxy dual
|
|
// interface.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::GetTypeInfo(UINT itinfo, ULONG lcid, ITypeInfo ** pptinfo)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceTag((tagError, "CLocalMTProxy::GetTypeInfo called"));
|
|
|
|
hr = LoadTypeLibs();
|
|
if (hr)
|
|
return hr;
|
|
|
|
*pptinfo = _pTypeInfoInterface;
|
|
(*pptinfo)->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::GetTypeInfoCount, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::GetTypeInfoCount(UINT * pctinfo)
|
|
{
|
|
*pctinfo = 1;
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::GetIDsOfNames, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = LoadTypeLibs();
|
|
if (hr)
|
|
return hr;
|
|
|
|
hr = _pTypeInfoInterface->GetIDsOfNames(rgszNames, cNames, rgdispid);
|
|
|
|
if (hr && _pDispRemote)
|
|
{
|
|
hr = _pTypeInfoCM->GetIDsOfNames(rgszNames, cNames, rgdispid);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::Invoke, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::Invoke(DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS * pdispparams,
|
|
VARIANT * pvarResult,
|
|
EXCEPINFO * pexcepinfo,
|
|
UINT * puArgErr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = LoadTypeLibs();
|
|
if (hr)
|
|
return hr;
|
|
|
|
hr = _pTypeInfoInterface->Invoke((IRemoteMTScriptProxy *)this,
|
|
dispidMember,
|
|
wFlags,
|
|
pdispparams,
|
|
pvarResult,
|
|
pexcepinfo,
|
|
puArgErr);
|
|
//
|
|
// If we're connected to the remote object, then we forward any calls
|
|
// we don't know how to handle on to that object. This is not aggregation,
|
|
// since we have not set up object identity in this relationship.
|
|
//
|
|
if (hr && _pDispRemote)
|
|
{
|
|
hr = _pDispRemote->Invoke(dispidMember,
|
|
riid,
|
|
lcid,
|
|
wFlags,
|
|
pdispparams,
|
|
pvarResult,
|
|
pexcepinfo,
|
|
puArgErr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::LoadTypeLibs, public
|
|
//
|
|
// Synopsis: Ensures that we have loaded our typelibrary
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CLocalMTProxy::LoadTypeLibs()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR achDll[MAX_PATH];
|
|
|
|
if (!_pTypeLibDLL)
|
|
{
|
|
GetModuleFileName(g_hInstDll, achDll, MAX_PATH);
|
|
|
|
hr = THR(LoadTypeLib(achDll, &_pTypeLibDLL));
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!_pTypeInfoInterface)
|
|
{
|
|
hr = THR(_pTypeLibDLL->GetTypeInfoOfGuid(IID_IRemoteMTScriptProxy,
|
|
&_pTypeInfoInterface));
|
|
if (hr)
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!_pTypeInfoCM)
|
|
{
|
|
hr = THR(_pTypeLibDLL->GetTypeInfoOfGuid(IID_IConnectedMachine,
|
|
&_pTypeInfoCM));
|
|
if (hr)
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (hr)
|
|
{
|
|
TraceTag((tagError, "CLocalMTProxy::LoadTypeLibs returning %x", hr));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// *************************************************************************
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::Connect, public
|
|
//
|
|
// Synopsis: Connects to the RemoteMTScript object on the given remote
|
|
// (or local) machine.
|
|
//
|
|
// Arguments: [bstrMachine] -- Machine to connect to. If NULL or empty,
|
|
// use the local machine.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Notes: This also sets up the event sink for handling events.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CLocalMTProxy::Connect(BSTR bstrMachine)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
COSERVERINFO csi = { 0 };
|
|
MULTI_QI mqi[2] = { 0 };
|
|
BOOL fRemote = TRUE;
|
|
|
|
// IConnectionPointContainer *pCPC;
|
|
// IConnectionPoint *pCP;
|
|
|
|
if (!bstrMachine || SysStringLen(bstrMachine) == 0)
|
|
{
|
|
fRemote = FALSE;
|
|
}
|
|
|
|
TraceTag((tagError, "CLocalMTProxy::Connect called. Machine=%ls", (fRemote) ? bstrMachine : L"<local>"));
|
|
|
|
// The following code will remove all security from the connection. This
|
|
// will need to be enabled if the corresponding call to CoInitializeSecurity
|
|
// is turned on in mtscript.exe.
|
|
|
|
// Remove security for the connection.
|
|
|
|
csi.pAuthInfo = NULL;
|
|
|
|
csi.pwszName = bstrMachine;
|
|
|
|
mqi[0].pIID = &IID_IDispatch;
|
|
// mqi[1].pIID = &IID_IConnectionPointContainer;
|
|
|
|
hr = CoCreateInstanceEx(CLSID_RemoteMTScript,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
(fRemote) ? &csi : NULL,
|
|
1,
|
|
mqi);
|
|
if (FAILED(hr))
|
|
{
|
|
TraceTag((tagError, "CLocalMTProxy::Connect: CoCreateInstanceEx returned=%x", hr));
|
|
return hr;
|
|
}
|
|
|
|
if (mqi[0].hr)
|
|
return mqi[0].hr;
|
|
|
|
_pDispRemote = (IDispatch *)mqi[0].pItf;
|
|
|
|
/*
|
|
// Security problems make it difficult to impossible to make a
|
|
// reverse COM event interface connect successfully.
|
|
|
|
if (!mqi[1].hr)
|
|
{
|
|
pCPC = (IConnectionPointContainer *)mqi[1].pItf;
|
|
|
|
|
|
hr = pCPC->FindConnectionPoint(DIID_DRemoteMTScriptEvents, &pCP);
|
|
if (!hr)
|
|
{
|
|
hr = pCP->Advise(&_cesSink, &_dwSinkCookie);
|
|
|
|
ReleaseInterface(pCP);
|
|
}
|
|
|
|
ReleaseInterface(pCPC);
|
|
|
|
#if DBG == 1
|
|
if (hr)
|
|
TraceTag((tagError, "Hookup to event sink returned %x", hr));
|
|
#endif
|
|
|
|
// If the advise failed for some reason, just don't sink events.
|
|
}
|
|
else
|
|
{
|
|
TraceTag((tagError, "CLocalMTProxy::Connect: ICPC QI returned=%x", mqi[1].hr));
|
|
}
|
|
*/
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::Disconnect, public
|
|
//
|
|
// Synopsis: Disconnects from a machine we connected to via Connect().
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CLocalMTProxy::Disconnect()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceTag((tagError, "CLocalMTProxy::Disconnect called"));
|
|
|
|
if (_dwSinkCookie)
|
|
{
|
|
IConnectionPointContainer *pCPC;
|
|
IConnectionPoint *pCP;
|
|
|
|
hr = _pDispRemote->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC);
|
|
if (!hr)
|
|
{
|
|
hr = pCPC->FindConnectionPoint(DIID_DRemoteMTScriptEvents,
|
|
&pCP);
|
|
if (!hr)
|
|
{
|
|
pCP->Unadvise(_dwSinkCookie);
|
|
|
|
ReleaseInterface(pCP);
|
|
}
|
|
|
|
ReleaseInterface(pCPC);
|
|
|
|
#if DBG == 1
|
|
if (hr)
|
|
TraceTag((tagError, "Unadvise from event sink returned %x", hr));
|
|
#endif
|
|
}
|
|
|
|
_dwSinkCookie = 0;
|
|
}
|
|
|
|
ClearInterface(&_pDispRemote);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLocalMTProxy::DownloadFile, public
|
|
//
|
|
// Synopsis: Downloads a file from the given URL and stores it locally.
|
|
//
|
|
// Arguments: [bstrURL] -- URL to download
|
|
// [bstrFile] -- Path of where the file was saved by urlmon
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CLocalMTProxy::DownloadFile(BSTR bstrURL, BSTR *bstrFile)
|
|
{
|
|
HRESULT hr;
|
|
TCHAR achBuf[MAX_PATH * 2];
|
|
|
|
|
|
hr = URLDownloadToCacheFile((IRemoteMTScriptProxy*)this,
|
|
bstrURL,
|
|
achBuf,
|
|
MAX_PATH * 2,
|
|
0,
|
|
NULL);
|
|
if (hr)
|
|
{
|
|
int cChar;
|
|
HINSTANCE hModURLMON = LoadLibraryA("urlmon.dll");
|
|
|
|
cChar = wsprintf(achBuf, L"Error: (%x) ", hr);
|
|
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_FROM_HMODULE |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
hModURLMON,
|
|
hr,
|
|
0,
|
|
achBuf + cChar,
|
|
MAX_PATH * 2 - cChar,
|
|
NULL);
|
|
|
|
FreeLibrary(hModURLMON);
|
|
}
|
|
|
|
*bstrFile = SysAllocString(achBuf);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// *************************************************************************
|
|
//
|
|
// CMTEventSink
|
|
//
|
|
// Class which implements the event sink for the remote object. This just
|
|
// forwards all calls to the event sink registered with us by the web page,
|
|
// if any.
|
|
//
|
|
// *************************************************************************
|
|
|
|
HRESULT
|
|
CMTEventSink::QueryInterface(REFIID iid, void **ppv)
|
|
{
|
|
if (iid == IID_IUnknown || iid == IID_IDispatch)
|
|
{
|
|
*ppv = (IDispatch *)this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMTEventSink::GetTypeInfo, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CMTEventSink::GetTypeInfo(UINT itinfo, ULONG lcid, ITypeInfo ** pptinfo)
|
|
{
|
|
if (Proxy()->_pDispSink)
|
|
{
|
|
return Proxy()->_pDispSink->GetTypeInfo(itinfo, lcid, pptinfo);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMTEventSink::GetTypeInfoCount, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CMTEventSink::GetTypeInfoCount(UINT * pctinfo)
|
|
{
|
|
if (Proxy()->_pDispSink)
|
|
{
|
|
return Proxy()->_pDispSink->GetTypeInfoCount(pctinfo);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMTEventSink::GetIDsOfNames, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CMTEventSink::GetIDsOfNames(REFIID riid,
|
|
LPOLESTR * rgszNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID * rgdispid)
|
|
{
|
|
if (Proxy()->_pDispSink)
|
|
{
|
|
return Proxy()->_pDispSink->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMTEventSink::Invoke, IDispatch
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CMTEventSink::Invoke(DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS * pdispparams,
|
|
VARIANT * pvarResult,
|
|
EXCEPINFO * pexcepinfo,
|
|
UINT * puArgErr)
|
|
{
|
|
TraceTag((tagError, "CMTEventSink::Invoke called"));
|
|
|
|
if (Proxy()->_pDispSink)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = Proxy()->_pDispSink->Invoke(dispidMember,
|
|
riid,
|
|
lcid,
|
|
wFlags,
|
|
pdispparams,
|
|
pvarResult,
|
|
pexcepinfo,
|
|
puArgErr);
|
|
if (hr)
|
|
{
|
|
TraceTag((tagError, "CMTEventSink::Invoke: Sink call returned %x!", hr));
|
|
}
|
|
}
|
|
|
|
TraceTag((tagError, "CMTEventSink::Invoke returning"));
|
|
|
|
return S_OK;
|
|
}
|