Source code of Windows XP (NT5)
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.

262 lines
6.4 KiB

  1. // MSAAAdapter.cpp : Implementation of CAccServerDocMgr
  2. #include "stdafx.h"
  3. #include "MSAAText.h"
  4. #include "MSAAAdapter.h"
  5. #define INITGUID
  6. #include <msctfx.h>
  7. #include "MSAAStore.h"
  8. // - in AnchorWrap.cpp
  9. HRESULT WrapACPToAnchor( ITextStoreACP * pDocAcp, ITextStoreAnchor ** ppDocAnchor );
  10. CAccServerDocMgr::CAccServerDocMgr()
  11. : m_pAccStore( NULL )
  12. {
  13. IMETHOD( CAccServerDocMgr );
  14. }
  15. CAccServerDocMgr::~CAccServerDocMgr()
  16. {
  17. IMETHOD( ~CAccServerDocMgr );
  18. if( m_pAccStore )
  19. {
  20. m_pAccStore->Release();
  21. }
  22. }
  23. BOOL CheckForWrapper( ITextStoreAnchor ** ppDoc )
  24. {
  25. // Is this a cloneable wrapper? If not, need to wrap it...
  26. IClonableWrapper * pClonableWrapper = NULL;
  27. HRESULT hr = (*ppDoc)->QueryInterface( IID_IClonableWrapper, (void **) & pClonableWrapper );
  28. if( hr == S_OK && pClonableWrapper )
  29. {
  30. // It already supports IClonableWrapper - nothing else to do...
  31. pClonableWrapper->Release();
  32. return TRUE;
  33. }
  34. // Need to use doc wrapper to get clonable (multi-client) support
  35. IDocWrap * pDocWrap = NULL;
  36. hr = CoCreateInstance( CLSID_DocWrap, NULL, CLSCTX_SERVER, IID_IDocWrap, (void **) & pDocWrap );
  37. if( hr != S_OK || ! pDocWrap )
  38. return FALSE;
  39. hr = pDocWrap->SetDoc( IID_ITextStoreAnchor, *ppDoc );
  40. if( hr != S_OK )
  41. {
  42. pDocWrap->Release();
  43. return FALSE;
  44. }
  45. ITextStoreAnchor * pNewDoc = NULL;
  46. hr = pDocWrap->GetWrappedDoc( IID_ITextStoreAnchor, (IUnknown **) & pNewDoc );
  47. pDocWrap->Release();
  48. if( hr != S_OK || ! pNewDoc )
  49. return FALSE;
  50. // This time round, QI should work (since we're talking to a wrapper)...
  51. pClonableWrapper = NULL;
  52. hr = pNewDoc->QueryInterface( IID_IClonableWrapper, (void **) & pClonableWrapper );
  53. if( hr != S_OK || ! pClonableWrapper )
  54. {
  55. pNewDoc->Release();
  56. return FALSE;
  57. }
  58. // Yup, it worked - replace the input doc with the new wrapped doc...
  59. pClonableWrapper->Release();
  60. (*ppDoc)->Release();
  61. *ppDoc = pNewDoc;
  62. return TRUE;
  63. }
  64. HRESULT STDMETHODCALLTYPE CAccServerDocMgr::NewDocument (
  65. REFIID riid,
  66. IUnknown * punk
  67. )
  68. {
  69. IMETHOD( NewDocument );
  70. // Check for known IIDs...
  71. CComPtr<ITextStoreAnchor> pDoc;
  72. if( riid == IID_ITextStoreAnchor || riid == IID_ITfTextStoreAnchor )
  73. {
  74. pDoc = (ITextStoreAnchor *) punk;
  75. }
  76. else if( riid == IID_ITextStoreACP || riid == IID_ITfTextStoreACP )
  77. {
  78. TraceParam( TEXT("Got ACP doc, but ACP->Anchor wrapping not currently supported") );
  79. return E_NOTIMPL;
  80. /*
  81. // We don't currently support ACP- interfaces directly - cicero always gives us
  82. // Anchor interfaces, wrapping ACPs if necesary.
  83. HRESULT hr = WrapACPToAnchor( static_cast<ITextStoreACP *>( punk ), & pDoc );
  84. if( hr != S_OK )
  85. return hr;
  86. */
  87. }
  88. else
  89. {
  90. TraceParam( TEXT("Got unknown interface - wasn't ITextStoreAnchor/ITfTextStoreAnchor") );
  91. return E_NOINTERFACE;
  92. }
  93. // Wrap the doc if necessary, to get multi-client support (via IClonableWrapper)...
  94. if( ! CheckForWrapper( & pDoc.p ) )
  95. {
  96. return E_FAIL;
  97. }
  98. if( ! m_pAccStore )
  99. {
  100. m_pAccStore = NULL;
  101. HRESULT hr = CoCreateInstance( CLSID_AccStore, NULL, CLSCTX_LOCAL_SERVER, IID_IAccStore, (void **) & m_pAccStore );
  102. if( ! m_pAccStore )
  103. {
  104. TraceErrorHR( hr, TEXT("CoCreate(AccStore)") );
  105. return hr;
  106. }
  107. }
  108. // TODO - what IID here?
  109. HRESULT hr = m_pAccStore->Register( IID_ITextStoreAnchor, pDoc.p );
  110. if( hr != S_OK )
  111. {
  112. TraceErrorHR( hr, TEXT("m_pAccStore->Register()") );
  113. return hr;
  114. }
  115. IUnknown * pCanonicalUnk = NULL;
  116. hr = punk->QueryInterface( IID_IUnknown, (void **) & pCanonicalUnk );
  117. if( hr == S_OK && pCanonicalUnk != NULL )
  118. {
  119. DocAssoc * pDocAssoc = new DocAssoc;
  120. if ( !pDocAssoc )
  121. {
  122. return E_OUTOFMEMORY;
  123. }
  124. pDocAssoc->m_pdocAnchor = pDoc;
  125. pDocAssoc->m_pdocOrig = pCanonicalUnk;
  126. m_Docs.AddToHead( pDocAssoc );
  127. }
  128. else
  129. {
  130. AssertMsg( FALSE, TEXT("QI(IUnknown) failed") );
  131. return hr;
  132. }
  133. pDoc.p->AddRef();
  134. return S_OK;
  135. }
  136. HRESULT STDMETHODCALLTYPE CAccServerDocMgr::RevokeDocument (
  137. IUnknown * punk
  138. )
  139. {
  140. IMETHOD( RevokeDocument );
  141. if ( !punk )
  142. return E_INVALIDARG;
  143. // Get the canonical IUnknown for comparison purposes...
  144. IUnknown * pCanonicalUnk = NULL;
  145. if( punk->QueryInterface( IID_IUnknown, (void **) & pCanonicalUnk ) != S_OK || pCanonicalUnk == NULL )
  146. {
  147. return E_FAIL;
  148. }
  149. // Do we recognise this doc?
  150. DocAssoc * pDocAssoc = NULL;
  151. for( Iter_dl< DocAssoc > i ( m_Docs ) ; ! i.AtEnd() ; i++ )
  152. {
  153. if( i->m_pdocOrig == pCanonicalUnk )
  154. {
  155. pDocAssoc = i;
  156. break;
  157. }
  158. }
  159. pCanonicalUnk->Release();
  160. if( ! pDocAssoc )
  161. {
  162. // Not found
  163. return E_INVALIDARG;
  164. }
  165. // Unregister with the store...
  166. HRESULT hr = m_pAccStore->Unregister( pDocAssoc->m_pdocAnchor );
  167. if( hr != S_OK )
  168. {
  169. TraceErrorHR( hr, TEXT("m_pAccStore->Unregister()") );
  170. }
  171. // Try calling IInternalDocWrap::NotifyRevoke() to tell the DocWrapper that the doc is
  172. // going away. (It will forward this to any interested clients.)
  173. IInternalDocWrap * pInternalDocWrap = NULL;
  174. hr = pDocAssoc->m_pdocAnchor->QueryInterface( IID_IInternalDocWrap, (void **) & pInternalDocWrap );
  175. if( hr == S_OK && pInternalDocWrap )
  176. {
  177. pInternalDocWrap->NotifyRevoke();
  178. pInternalDocWrap->Release();
  179. }
  180. else
  181. {
  182. TraceErrorHR( hr, TEXT("pdocAnchor didn't support IInternalDocWrap - was it wrapped properly?") );
  183. }
  184. // Remove from internal list...
  185. m_Docs.remove( pDocAssoc );
  186. pDocAssoc->m_pdocOrig->Release();
  187. pDocAssoc->m_pdocAnchor->Release();
  188. delete pDocAssoc;
  189. // Done.
  190. return hr;
  191. }
  192. HRESULT STDMETHODCALLTYPE CAccServerDocMgr::OnDocumentFocus (
  193. IUnknown * punk
  194. )
  195. {
  196. IMETHOD( OnDocumentFocus );
  197. if( ! m_pAccStore )
  198. {
  199. m_pAccStore = NULL;
  200. HRESULT hr = CoCreateInstance( CLSID_AccStore, NULL, CLSCTX_LOCAL_SERVER, IID_IAccStore, (void **) & m_pAccStore );
  201. if( ! m_pAccStore )
  202. {
  203. TraceErrorHR( hr, TEXT("CoCreate(AccStore)") );
  204. return hr;
  205. }
  206. }
  207. return m_pAccStore->OnDocumentFocus( punk );
  208. }