ExternalConnectionImpl.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #ifndef __ExternalConnectionImpl_h__
  2. #define __ExternalConnectionImpl_h__
  3. /////////////////////////////////////////////////////////////////////////////
  4. // ExternalConnectionImpl.h | Declaration of the IExternalConnectionImpl
  5. // template class.
  6. //
  7. #include <TCLib.h>
  8. #include <comdef.h>
  9. /////////////////////////////////////////////////////////////////////////////
  10. // Interface Map Entries
  11. #define COM_INTERFACE_ENTRIES_IExternalConnectionImpl() \
  12. COM_INTERFACE_ENTRY_FUNC(IID_IExternalConnection, 0, \
  13. QI_IExternalConnectionImpl)
  14. /////////////////////////////////////////////////////////////////////////////
  15. // IExternalConnectionImpl
  16. template <class T>
  17. class ATL_NO_VTABLE IExternalConnectionImpl : public IExternalConnection
  18. {
  19. // Construction
  20. public:
  21. IExternalConnectionImpl();
  22. // Overrides
  23. public:
  24. void DoLastReleaseClosing();
  25. // Diagnostics
  26. protected:
  27. void DumpConnection(int nDirection, DWORD extconn, DWORD reserved,
  28. BOOL fLastReleaseCloses = FALSE);
  29. // Implementation
  30. protected:
  31. static HRESULT WINAPI QI_IExternalConnectionImpl(void* pvThis, REFIID,
  32. LPVOID* ppv, DWORD);
  33. // IExternalConnection Interface Methods
  34. public:
  35. STDMETHOD_(DWORD, AddConnection)(DWORD extconn, DWORD reserved);
  36. STDMETHOD_(DWORD, ReleaseConnection)(DWORD extconn, DWORD reserved,
  37. BOOL fLastReleaseCloses);
  38. // Data Members
  39. protected:
  40. DWORD m_dwStrong;
  41. };
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Inline Construction
  44. template <class T>
  45. IExternalConnectionImpl<T>::IExternalConnectionImpl()
  46. : m_dwStrong(0)
  47. {
  48. }
  49. /////////////////////////////////////////////////////////////////////////////
  50. // Overrides
  51. template <class T>
  52. void IExternalConnectionImpl<T>::DoLastReleaseClosing()
  53. {
  54. BOOL bNoDisconnect = FALSE;
  55. #ifdef _DEBUG
  56. // Format the derived class name string
  57. const LPCSTR pszClass = TCTypeName(T);
  58. // Read the registry value
  59. CRegKey key;
  60. LPCTSTR pszKey = TEXT("Software\\MultiMedia Access");
  61. LONG lResult = key.Open(HKEY_LOCAL_MACHINE, pszKey);
  62. if (ERROR_SUCCESS == lResult)
  63. {
  64. DWORD dwValue = 0;
  65. LPCTSTR pszValue = TEXT("DisableLastReleaseClosing");
  66. if (ERROR_SUCCESS == (lResult = key.QueryValue(dwValue, pszValue)))
  67. if (dwValue)
  68. bNoDisconnect = TRUE;
  69. }
  70. #endif // _DEBUG
  71. // Get the derived class pointer
  72. T* pThis = static_cast<T*>(this);
  73. // Get the object's IUnknown pointer (without AddRef'ing it)
  74. IUnknown* punk = NULL;
  75. {
  76. TCObjectLock<T> lock(pThis);
  77. punk = pThis->GetUnknown();
  78. // Report the object reference count upon entering
  79. #ifdef _DEBUG
  80. ATLTRACE1("IExternalConnectionImpl<%hs>::", pszClass);
  81. ATLTRACE0("DoLastReleaseClosing(): Entering, ");
  82. ATLTRACE1("m_dwRef = %d\n", pThis->m_dwRef);
  83. #endif // _DEBUG
  84. }
  85. // Disconnect all external connections to the object
  86. if (bNoDisconnect)
  87. {
  88. #ifdef _DEBUG
  89. ATLTRACE1("\tIExternalConnectionImpl<%hs>::", pszClass);
  90. ATLTRACE0("DoLastReleaseClosing(): Skipping CoDisconnectObject ");
  91. ATLTRACE0("due to registry value\n");
  92. #endif // _DEBUG
  93. }
  94. else
  95. {
  96. #ifdef _DEBUG
  97. ATLTRACE1("\tIExternalConnectionImpl<%hs>::", pszClass);
  98. ATLTRACE0("DoLastReleaseClosing(): Prior to CoDisconnectObject\n");
  99. #endif // _DEBUG
  100. // Disconnect the object
  101. HRESULT hr = CoDisconnectObject(punk, 0);
  102. #ifdef _DEBUG
  103. ATLTRACE1("\tIExternalConnectionImpl<%hs>::", pszClass);
  104. ATLTRACE0("DoLastReleaseClosing(): CoDisconnectObject ");
  105. ATLTRACE1("returned 0x%08X\n", hr);
  106. #endif // _DEBUG
  107. }
  108. // Report the object reference count upon exiting
  109. #ifdef _DEBUG
  110. {
  111. TCObjectLock<T> lock(pThis);
  112. ATLTRACE1("IExternalConnectionImpl<%hs>::", TCTypeName(T));
  113. ATLTRACE0("DoLastReleaseClosing(): Exiting, ");
  114. ATLTRACE1("m_dwRef = %d\n", pThis->m_dwRef);
  115. }
  116. #endif
  117. }
  118. /////////////////////////////////////////////////////////////////////////////
  119. // Diagnostics
  120. template <class T>
  121. void IExternalConnectionImpl<T>::DumpConnection(int nDirection,
  122. DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses)
  123. {
  124. #ifdef _DEBUG
  125. {
  126. // Lock the object to get the connection count
  127. TCObjectLock<T> lock(static_cast<T*>(this));
  128. int nStrong = (int)m_dwStrong;
  129. // Determine if the extconn parameter specifies a strong connection
  130. bool bStrong = (extconn & EXTCONN_STRONG);
  131. // Format the derived class name string
  132. const LPCSTR pszClass = TCTypeName(T);
  133. // Format the method name string
  134. assert(1 == nDirection || -1 == nDirection);
  135. const LPCSTR pszMethod =
  136. (nDirection > 0) ? "AddConnection" : "ReleaseConnection";
  137. // Dump the method name
  138. ATLTRACE2("IExternalConnectionImpl<%hs>::%hs(): ", pszClass, pszMethod);
  139. // Dump the strong connection count
  140. ATLTRACE1("m_dwStrong= %d", nStrong + (bStrong ? nDirection : 0));
  141. // Dump the method parameters
  142. if (nDirection < 0)
  143. ATLTRACE1(" fLastReleaseCloses= %hs",
  144. fLastReleaseCloses ? "TRUE" : "FALSE");
  145. if (!bStrong)
  146. ATLTRACE1(" extconn= 0x%08X (!=EXTCONN_STRONG)", extconn);
  147. // Finish with a line-end character
  148. ATLTRACE0("\n");
  149. }
  150. #endif // _DEBUG
  151. }
  152. /////////////////////////////////////////////////////////////////////////////
  153. // Implementation
  154. template <class T>
  155. HRESULT WINAPI IExternalConnectionImpl<T>::QI_IExternalConnectionImpl(
  156. void* pvThis, REFIID, LPVOID* ppv, DWORD)
  157. {
  158. static DWORD dwDisableIExternalConnection = -1;
  159. if (-1 == dwDisableIExternalConnection)
  160. {
  161. // Initialize the value
  162. dwDisableIExternalConnection = 0;
  163. #ifdef _DEBUG
  164. // Read the registry value
  165. CRegKey key;
  166. const LPCTSTR pszKey = TEXT("Software\\MultiMedia Access");
  167. LONG lResult = key.Open(HKEY_LOCAL_MACHINE, pszKey);
  168. if (ERROR_SUCCESS == lResult)
  169. {
  170. const LPCTSTR pszValue = TEXT("DisableIExternalConnection");
  171. lResult = key.QueryValue(dwDisableIExternalConnection, pszValue);
  172. }
  173. #endif // _DEBUG
  174. }
  175. // Clear the specified [out] parameter
  176. CLEAROUT(ppv, (void*)NULL);
  177. // Do not support the interface if disabled in the registry
  178. if (dwDisableIExternalConnection)
  179. return E_NOINTERFACE;
  180. // Cast to the IExternalConnection interface
  181. T* pThis = static_cast<T*>(pvThis);
  182. IExternalConnection* pec = static_cast<IExternalConnection*>(pThis);
  183. if (!pec)
  184. return E_NOINTERFACE;
  185. // Copy the interface pointer to the [out] parameter
  186. CLEAROUT(ppv, (void*)pec);
  187. pec->AddRef();
  188. // Indicate success
  189. return S_OK;
  190. }
  191. /////////////////////////////////////////////////////////////////////////////
  192. // IExternalConnection Interface Methods
  193. template <class T>
  194. STDMETHODIMP_(DWORD) IExternalConnectionImpl<T>::AddConnection(DWORD extconn,
  195. DWORD reserved)
  196. {
  197. TCObjectLock<T> lock(static_cast<T*>(this));
  198. DumpConnection(1, extconn, reserved);
  199. return (extconn & EXTCONN_STRONG) ? ++m_dwStrong : 0;
  200. }
  201. template <class T>
  202. STDMETHODIMP_(DWORD) IExternalConnectionImpl<T>::ReleaseConnection(
  203. DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses)
  204. {
  205. TCObjectLock<T> lock(static_cast<T*>(this));
  206. DumpConnection(-1, extconn, reserved, fLastReleaseCloses);
  207. if (extconn & EXTCONN_STRONG)
  208. {
  209. DWORD nStrong = --m_dwStrong;
  210. lock.Unlock();
  211. if (0 == nStrong && fLastReleaseCloses)
  212. static_cast<T*>(this)->DoLastReleaseClosing();
  213. return nStrong;
  214. }
  215. else
  216. return 0;
  217. }
  218. /////////////////////////////////////////////////////////////////////////////
  219. #endif // !__ExternalConnectionImpl_h__