PageRenderTime 27ms CodeModel.GetById 15ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2008/CppOfficeManagedCOMAddInShim/ConnectProxy.cpp

#
C++ | 139 lines | 93 code | 18 blank | 28 comment | 10 complexity | 9951c5f1bec095d9a36f130a81d93880 MD5 | raw file
  1// ConnectProxy.cpp 
  2#include "stdafx.h"
  3#include "CLRLoader.h"
  4#include "ConnectProxy.h"
  5
  6// These strings are specific to the managed assembly that this shim will load.
  7static LPCWSTR szAddInAssemblyName = 
  8	L"CSOfficeSharedAddIn, PublicKeyToken=0617bb81948569c1";
  9static LPCWSTR szConnectClassName = 
 10	L"CSOfficeSharedAddIn.Connect";
 11static LPCWSTR szAssemblyConfigName =
 12	L"CSOfficeSharedAddIn.dll.config";
 13
 14CConnectProxy::CConnectProxy() 
 15    : m_pConnect(NULL), m_pCLRLoader(NULL), m_pUnknownInner(NULL)
 16{
 17}
 18
 19HRESULT CConnectProxy::FinalConstruct()
 20{
 21    HRESULT hr = S_OK;
 22    IUnknown* pUnkThis = NULL;
 23
 24    // Instantiate the CLR-loader object.
 25    m_pCLRLoader = new (std::nothrow) CCLRLoader();
 26    IfNullGo( m_pCLRLoader );
 27
 28    IfFailGo( this->QueryInterface(IID_IUnknown, (LPVOID*)&pUnkThis) );
 29
 30    // Load the CLR, create an AppDomain, and instantiate the target add-in
 31    // and the inner aggregated object of the shim.
 32    IfFailGo( m_pCLRLoader->CreateAggregatedAddIn(
 33        pUnkThis,
 34        szAddInAssemblyName, szConnectClassName, szAssemblyConfigName) );
 35
 36    // Extract the IDTExtensibility2 interface pointer from the target add-in.
 37    IfFailGo( m_pUnknownInner->QueryInterface(
 38        __uuidof(IDTExtensibility2), (LPVOID*)&this->m_pConnect) );
 39
 40Error:
 41    if (pUnkThis != NULL)
 42        pUnkThis->Release();
 43
 44    return hr;
 45}
 46
 47// Cache the pointer to the aggregated innner object, and make sure
 48// we increment the refcount on it.
 49HRESULT __stdcall CConnectProxy::SetInnerPointer(IUnknown* pUnkInner)
 50{
 51    if (pUnkInner == NULL)
 52    {
 53        return E_POINTER;
 54    }
 55    if (m_pUnknownInner != NULL)
 56    {
 57        return E_UNEXPECTED;
 58    }
 59    
 60    m_pUnknownInner = pUnkInner;
 61    m_pUnknownInner->AddRef();
 62    return S_OK;
 63}
 64
 65// IDTExtensibility2 implementation: OnConnection, OnAddInsUpdate and
 66// OnStartupComplete are simple pass-throughs to the proxied managed
 67// add-in. We only need to wrap IDTExtensibility2 because we need to
 68// add behavior to the OnBeginShutdown and OnDisconnection methods.
 69HRESULT __stdcall CConnectProxy::OnConnection(
 70    IDispatch * Application, ext_ConnectMode ConnectMode, 
 71    IDispatch *AddInInst, SAFEARRAY **custom)
 72{
 73    return m_pConnect->OnConnection(
 74        Application, ConnectMode, AddInInst, custom);
 75}
 76
 77HRESULT __stdcall CConnectProxy::OnAddInsUpdate(SAFEARRAY **custom)
 78{
 79    return m_pConnect->OnAddInsUpdate(custom);
 80}
 81
 82HRESULT __stdcall CConnectProxy::OnStartupComplete(SAFEARRAY **custom)
 83{
 84    return m_pConnect->OnStartupComplete(custom);
 85}
 86
 87// When the host application shuts down, it calls OnBeginShutdown, 
 88// and then OnDisconnection. We must be careful to test that the add-in
 89// pointer is not null, to allow for the case where the add-in was
 90// previously disconnected prior to app shutdown.
 91HRESULT __stdcall CConnectProxy::OnBeginShutdown(SAFEARRAY **custom)
 92{
 93    HRESULT hr = S_OK;
 94    if (m_pConnect)
 95    {
 96        hr = m_pConnect->OnBeginShutdown(custom);
 97    }
 98    return hr;
 99}
100
101// OnDisconnection is called if the user disconnects the add-in via the COM
102// add-ins dialog. We wrap this so that we can make sure we can clean up
103// the reference we're holding to the inner object. We must also allow for 
104// the possibility that the user has disconnected the add-in via the COM 
105// add-ins dialog or programmatically: in this scenario, OnDisconnection is
106// called first, and this add-in never gets the OnBeginShutdown call
107// (because it has already been disconnected by then).
108HRESULT __stdcall CConnectProxy::OnDisconnection(
109    ext_DisconnectMode RemoveMode, SAFEARRAY **custom)
110{
111    HRESULT hr = S_OK;
112    hr =  m_pConnect->OnDisconnection(RemoveMode, custom);
113    if (SUCCEEDED(hr))
114    {
115        m_pConnect->Release();
116        m_pConnect = NULL;
117    }
118    return hr;
119}
120
121// Make sure we unload the AppDomain, and clean up our references. 
122// FinalRelease will be the last thing called in the shim/add-in, after
123// OnBeginShutdown and OnDisconnection.
124void CConnectProxy::FinalRelease() 
125{
126    // Release the aggregated inner object.
127    if (m_pUnknownInner)
128    {
129        m_pUnknownInner->Release();
130    }
131
132    // Unload the AppDomain, and clean up.
133    if (m_pCLRLoader)
134    {
135        m_pCLRLoader->Unload();
136        delete m_pCLRLoader;
137        m_pCLRLoader = NULL;
138    }
139}