Leaked source code of windows server 2003
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.

215 lines
6.6 KiB

  1. //
  2. // compart.cpp
  3. //
  4. // Compartment example.
  5. //
  6. #include "globals.h"
  7. #include "mark.h"
  8. //+---------------------------------------------------------------------------
  9. //
  10. // _InitCompartment
  11. //
  12. // Initialize a compartment on a particular context.
  13. //
  14. // The Mark sample doesn't really do any with its context compartment, this
  15. // code is purely for demonstration purposes.
  16. //----------------------------------------------------------------------------
  17. BOOL CMarkTextService::_InitContextCompartment(ITfContext *pContext)
  18. {
  19. ITfCompartmentMgr *pCompartmentMgr;
  20. ITfCompartment *pCompartment;
  21. VARIANT varValue;
  22. HRESULT hr;
  23. // we want the mgr associated with pContext
  24. if (pContext->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr) != S_OK)
  25. return FALSE;
  26. hr = E_FAIL;
  27. if (pCompartmentMgr->GetCompartment(c_guidMarkContextCompartment, &pCompartment) != S_OK)
  28. goto Exit;
  29. // if we don't initialize the value, it will be VT_EMPTY
  30. // but let's initialize it to 0
  31. // NB: to keep things simple, we use a VT_I4
  32. // but you could use VT_UNKNOWN and store a pointer to anything
  33. varValue.vt = VT_I4;
  34. varValue.lVal = 0; // arbitrary value
  35. hr = pCompartment->SetValue(_tfClientId, &varValue);
  36. pCompartment->Release();
  37. Exit:
  38. pCompartmentMgr->Release();
  39. return (hr == S_OK);
  40. }
  41. //+---------------------------------------------------------------------------
  42. //
  43. // _UninitCompartment
  44. //
  45. // Uninitialize a compartment on a particular context.
  46. //
  47. // The Mark sample doesn't really do any with its context compartment, this
  48. // code is purely for demonstration purposes.
  49. //----------------------------------------------------------------------------
  50. void CMarkTextService::_UninitCompartment(ITfContext *pContext)
  51. {
  52. ITfCompartmentMgr *pCompartmentMgr;
  53. // we want the mgr associated with pContext
  54. if (pContext->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr) != S_OK)
  55. return;
  56. pCompartmentMgr->ClearCompartment(_tfClientId, c_guidMarkContextCompartment);
  57. pCompartmentMgr->Release();
  58. }
  59. //+---------------------------------------------------------------------------
  60. //
  61. // _Menu_OnSetGlobalCompartment
  62. //
  63. // Callback for the "Set Global Compartment" menu item.
  64. // Set the value of our global compartment. This will trigger a callback
  65. // on our compartment change sinks in every thread/instance of this service.
  66. //----------------------------------------------------------------------------
  67. /* static */
  68. void CMarkTextService::_Menu_OnSetGlobalCompartment(CMarkTextService *_this)
  69. {
  70. ITfCompartmentMgr *pCompartmentMgr;
  71. ITfCompartment *pCompartment;
  72. VARIANT varValue;
  73. // we want the global mgr
  74. if (_this->_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK)
  75. return;
  76. if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) != S_OK)
  77. {
  78. pCompartment = NULL;
  79. goto Exit;
  80. }
  81. // let's toggle the value
  82. // notice that global compartments are persisted, unlike all others
  83. if (FAILED(pCompartment->GetValue(&varValue))) // will return S_FALSE if varValue.vt == VT_EMPTY
  84. goto Exit;
  85. if (varValue.vt == VT_EMPTY)
  86. {
  87. // if we get here, the compartment has never been initialized
  88. varValue.vt = VT_I4;
  89. varValue.lVal = 0;
  90. }
  91. // toggle value
  92. varValue.lVal = ~varValue.lVal;
  93. pCompartment->SetValue(_this->_tfClientId, &varValue);
  94. Exit:
  95. SafeRelease(pCompartment);
  96. pCompartmentMgr->Release();
  97. }
  98. //+---------------------------------------------------------------------------
  99. //
  100. // _InitGlobalCompartment
  101. //
  102. // Ininit a change sink on our global compartment. The system will call us
  103. // back anytime the compartment is modified from any thread in the desktop.
  104. //
  105. // NB: ITfCompartmentEventSink's attached to thread local compartments will
  106. // only get callbacks to changes that occur within a single thread. Global
  107. // compartments are different.
  108. //----------------------------------------------------------------------------
  109. BOOL CMarkTextService::_InitGlobalCompartment()
  110. {
  111. ITfCompartmentMgr *pCompartmentMgr;
  112. ITfCompartment *pCompartment;
  113. BOOL fRet;
  114. // we want the global mgr
  115. if (_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK)
  116. return FALSE;
  117. fRet = FALSE;
  118. if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) != S_OK)
  119. goto Exit;
  120. fRet = AdviseSink(pCompartment, (ITfCompartmentEventSink *)this,
  121. IID_ITfCompartmentEventSink, &_dwGlobalCompartmentEventSinkCookie);
  122. pCompartment->Release();
  123. if (!fRet)
  124. {
  125. // don't try to unadvise a bogus cookie later
  126. _dwGlobalCompartmentEventSinkCookie = TF_INVALID_COOKIE;
  127. }
  128. Exit:
  129. pCompartmentMgr->Release();
  130. return fRet;
  131. }
  132. //+---------------------------------------------------------------------------
  133. //
  134. // _UninitCompartment
  135. //
  136. // Unitialize the global compartment if we have previously accessed it.
  137. // This method only frees resources the system has allocated in this thread.
  138. // Other threads can still access the global compartment, and the value (which
  139. // is persisted across the desktop) does not change.
  140. //
  141. // Also, uninit the change sink we attached to the compartment.
  142. //----------------------------------------------------------------------------
  143. void CMarkTextService::_UninitGlobalCompartment()
  144. {
  145. ITfCompartmentMgr *pCompartmentMgr;
  146. ITfCompartment *pCompartment;
  147. // we want the global mgr
  148. if (_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK)
  149. return;
  150. // unadvise our event sink
  151. if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) == S_OK)
  152. {
  153. UnadviseSink(pCompartment, &_dwGlobalCompartmentEventSinkCookie);
  154. pCompartment->Release();
  155. }
  156. // let the system free resources associated with the compartment on this
  157. // thread
  158. pCompartmentMgr->ClearCompartment(_tfClientId, c_guidMarkGlobalCompartment);
  159. pCompartmentMgr->Release();
  160. }
  161. //+---------------------------------------------------------------------------
  162. //
  163. // ITfCompartmentEventSink::OnChange
  164. //
  165. // TSF calls this method anytime our private global compartment is modified,
  166. // even from other threads/processes.
  167. //----------------------------------------------------------------------------
  168. STDAPI CMarkTextService::OnChange(REFGUID rguidCompartment)
  169. {
  170. // nothing to do in this sample
  171. return S_OK;
  172. }