text: /**************************************************************************
     THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
     ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
     PARTICULAR PURPOSE.
  
     Copyright 2001 Microsoft Corporation. All Rights Reserved.
  **************************************************************************/
  
  /**************************************************************************
  
     File:          Monitor.cpp
  
     Description:   
  
  **************************************************************************/
  
  /**************************************************************************
  	#include statements
  **************************************************************************/
  
  #include "Monitor.h"
  
  /**************************************************************************
  	global variables and definitions
  **************************************************************************/
  
  /**************************************************************************
  
  	CCompartmentMonitor::CCompartmentMonitor()
  
  **************************************************************************/
  
  CCompartmentMonitor::CCompartmentMonitor(void)
  {
      m_dwRef = 1;
      m_dwCookie = 0;
      m_pCompartment = NULL;
      m_guidCompartment = GUID_NULL;
      m_pCallback = NULL;
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::~CCompartmentMonitor()
  
  **************************************************************************/
  
  CCompartmentMonitor::~CCompartmentMonitor()
  {
      Uninitialize();
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::Initialize()
  
  **************************************************************************/
  
  HRESULT CCompartmentMonitor::Initialize(    const GUID *pguidCompartment,
                                              PCOMPARTMENTMONITORPROC pCallback, 
                                              LPARAM lParam)
  {
      if(!IsEqualGUID(m_guidCompartment, GUID_NULL))
      {
          //Initialize() has already been called
          return E_UNEXPECTED;
      }
  
      m_guidCompartment = *pguidCompartment;
      m_pCallback = pCallback;
      m_lParam = lParam;
      
      HRESULT         hr;
      ITfThreadMgr    *pThreadMgr;
      
      //create a thread manager object
      hr = CoCreateInstance(CLSID_TF_ThreadMgr, 
          NULL, 
          CLSCTX_INPROC_SERVER, 
          IID_ITfThreadMgr, 
          (void**)&pThreadMgr);
      
      if(SUCCEEDED(hr))
      {
          ITfCompartmentMgr   *pCompMgr;
  
          //get the global compartment manager
          hr = pThreadMgr->GetGlobalCompartment(&pCompMgr);
          if(SUCCEEDED(hr))
          {
              //get the Speech UI compartment 
              hr = pCompMgr->GetCompartment(m_guidCompartment, 
                  &m_pCompartment);
              if(SUCCEEDED(hr))
              {
                  ITfSource   *pSource;
                  
                  //install the advise sink
                  hr = m_pCompartment->QueryInterface(IID_ITfSource, 
                      (LPVOID*)&pSource);
                  if(SUCCEEDED(hr))
                  {
                      hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, 
                          (ITfCompartmentEventSink*)this,
                          &m_dwCookie);
                  }
                  
                  //if something went wrong, release the member interface
                  if(FAILED(hr))
                  {
                      m_pCompartment->Release();
                      m_pCompartment = NULL;
                  }
              }
              
              //release the compartment manager
              pCompMgr->Release();
          }
          
          //release the thread manager
          pThreadMgr->Release();
      }
  
      return hr;
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::Uninitialize()
  
  **************************************************************************/
  
  HRESULT CCompartmentMonitor::Uninitialize(void)
  {
      HRESULT     hr = S_OK;
  
      if(m_pCompartment)
      {
          ITfSource   *pSource;
  
          hr = m_pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
  
          if(SUCCEEDED(hr))
          {
              hr = pSource->UnadviseSink(m_dwCookie);
  
              pSource->Release();
          }
      
          m_pCompartment->Release();
          m_pCompartment = NULL;
      }
  
      m_guidCompartment = GUID_NULL;
      
      return hr;
  }
  
  //
  // IUnknown
  //
  
  /**************************************************************************
  
  	CCompartmentMonitor::QueryInterface()
  
  **************************************************************************/
  
  STDAPI CCompartmentMonitor::QueryInterface(REFIID riid, void **ppvObj)
  {
      *ppvObj = NULL;
  
      if (IsEqualIID(riid, IID_IUnknown) ||
          IsEqualIID(riid, IID_ITfCompartmentEventSink))
      {
          *ppvObj = (ITfCompartmentEventSink*)this;
      }
  
      if (*ppvObj)
      {
          AddRef();
          return S_OK;
      }
  
      return E_NOINTERFACE;
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::AddRef()
  
  **************************************************************************/
  
  STDAPI_(ULONG) CCompartmentMonitor::AddRef()
  {
      return ++m_dwRef;
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::Release()
  
  **************************************************************************/
  
  STDAPI_(ULONG) CCompartmentMonitor::Release()
  {
      m_dwRef--;
  
      if(0 == m_dwRef)
      {
          delete this;
          return 0;
      }
  
      return m_dwRef;
  }
  
  //
  // ITfCompartmentEventSink
  //
  
  /**************************************************************************
  
  	CCompartmentMonitor::OnChange()
  
  **************************************************************************/
  
  STDAPI CCompartmentMonitor::OnChange(REFGUID rguid)
  {
      HRESULT hr = S_OK;
  
      if(IsEqualGUID(rguid, m_guidCompartment))
      {
          GUID guid = m_guidCompartment;
          BOOL fStatus;
  
          GetStatus(&fStatus);
  
          //notify the status of this compartment has changed
          hr = (*m_pCallback)(&guid, fStatus, m_lParam);
      }
  
      return hr;
  }
  
  /**************************************************************************
  
  	CCompartmentMonitor::GetStatus()
  
  **************************************************************************/
  
  HRESULT CCompartmentMonitor::GetStatus(BOOL *pfEnabled)
  {
      if(NULL == pfEnabled)
      {
          return E_INVALIDARG;
      }
  
      if(!m_pCompartment)
      {
          return E_UNEXPECTED;
      }
  
      HRESULT hr;
      VARIANT var;
  
      VariantInit(&var);
      hr = m_pCompartment->GetValue(&var);
      if(S_OK == hr)
      {
          switch(var.vt)
          {
          case VT_I4:
              *pfEnabled = var.lVal;
              break;
          }
  
          VariantClear(&var);
      }
      else
      {
          //this usually means the text service is not installed
          return E_UNEXPECTED;
      }
      
      
      return S_OK;
  }
  