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