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.
 
 
 
 
 
 

1272 lines
30 KiB

//
// nuimgr.cpp
//
#include "private.h"
#include "tim.h"
#include "nuimgr.h"
#include "nuictrl.h"
#include "marshal.h"
#include "timlist.h"
#include "lbaddin.h"
#include "hotkey.h"
DBG_ID_INSTANCE(CLBarItemSink);
DBG_ID_INSTANCE(CLBarItemSinkProxy);
DBG_ID_INSTANCE(CLangBarItemMgr);
DBG_ID_INSTANCE(CEnumLBItem);
//////////////////////////////////////////////////////////////////////////////
//
// marshalling misc func
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// FreeStubForThis
//
// this function clean up all marshaling stubs for the LangBarItem.
//
//+---------------------------------------------------------------------------
void FreeMarshaledStubOfItem(SYSTHREAD *psfn, REFGUID rguid)
{
ITfLangBarItem *pItem;
if (!psfn->prgStub)
return;
//
// #489905
//
// we can not call sink anymore after DLL_PROCESS_DETACH.
//
if (DllShutdownInProgress())
return;
int nCnt = psfn->prgStub->Count();
int i = 0;
for (i = 0; i < nCnt; i++)
{
TryThisIdAgain:
CStub *pStub = psfn->prgStub->Get(i);
HRESULT hr;
TF_LANGBARITEMINFO info;
//
// Win98-J and Satori cause exception at the sutdown of notepad.
// we need to make sure this exception handler is not hiding any
// potential problems.
//
_try {
if (FAILED(pStub->_punk->QueryInterface(IID_ITfLangBarItem, (void **)&pItem)))
continue;
}
_except (1) {
continue;
}
hr = pItem->GetInfo(&info);
pItem->Release();
if (SUCCEEDED(hr) && IsEqualGUID(info.guidItem, rguid))
{
pStub->_fNoRemoveInDtor = TRUE;
psfn->prgStub->Remove(i, 1);
delete pStub;
nCnt--;
if (i < nCnt)
goto TryThisIdAgain;
return;
}
}
}
//////////////////////////////////////////////////////////////////////////////
//
// CLangBarItemMgr
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CLangBarItemMgr::CLangBarItemMgr(SYSTHREAD *psfn) : CSysThreadRef(psfn)
{
Dbg_MemSetThisNameID(TEXT("CLangBarItemMgr"));
Assert(_GetThis() == NULL);
_SetThis(this);
_dwCurCookie = 0;
_ulInAssemblyChange = 0;
_fHandleOnUpdate = TRUE;
EnsureMarshalWnd();
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CLangBarItemMgr::~CLangBarItemMgr()
{
g_timlist.ClearFlags(_psfn->dwThreadId, TLF_LBIMGR);
_RemoveSystemItems(_psfn);
CleanUp();
_SetThis(NULL);
}
//+---------------------------------------------------------------------------
//
// IUnknown
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::QueryInterface(REFIID riid, void **ppvObj)
{
if (ppvObj == NULL)
return E_INVALIDARG;
*ppvObj = NULL;
if (IsEqualIID(riid, IID_ITfLangBarItemMgr) ||
IsEqualIID(riid, IID_IUnknown))
{
*ppvObj = SAFECAST(this, ITfLangBarItemMgr *);
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDAPI_(ULONG) CLangBarItemMgr::AddRef()
{
//
// we don't have ref count.
// Keep this class in psfn and delete at the end of thread.
//
return 2;
}
STDAPI_(ULONG) CLangBarItemMgr::Release()
{
//
// we don't have ref count.
// Keep this class in psfn and delete at the end of thread.
//
return 1;
}
//+---------------------------------------------------------------------------
//
// _RemoveSystemItems
//
//----------------------------------------------------------------------------
void CLangBarItemMgr::_RemoveSystemItems(SYSTHREAD *psfn)
{
int i;
CLBarItemDeviceType *plbiDT;
DWORD dwThreadId = GetCurrentThreadId();
if (_plbiCtrl != NULL)
{
RemoveItem(*_plbiCtrl->GetGuidItem());
if (_plbiCtrl->Release() > 0)
{
if (psfn && (psfn->dwThreadId == dwThreadId))
{
// Clean up a pointer that is marshalled to UTB.
delete _plbiCtrl;
}
}
_plbiCtrl = NULL;
}
if (_plbiReconv != NULL)
{
RemoveItem(*_plbiReconv->GetGuidItem());
if (_plbiReconv->Release() > 0)
{
if (psfn && (psfn->dwThreadId == dwThreadId))
{
// Clean up a pointer that is marshalled to UTB.
delete _plbiReconv;
}
}
_plbiReconv = NULL;
}
if (_plbiWin32IME != NULL)
{
RemoveItem(*_plbiWin32IME->GetGuidItem());
if (_plbiWin32IME->Release() > 0)
{
if (psfn && (psfn->dwThreadId == dwThreadId))
{
// Clean up a pointer that is marshalled to UTB.
delete _plbiWin32IME;
}
}
_plbiWin32IME = NULL;
}
if (_plbiHelp != NULL)
{
RemoveItem(*_plbiHelp->GetGuidItem());
if (_plbiHelp->Release() > 0)
{
if (psfn && (psfn->dwThreadId == dwThreadId))
{
// Clean up a pointer that is marshalled to UTB.
delete _plbiHelp;
}
}
_plbiHelp = NULL;
}
for (i = 0; i < _rglbiDeviceType.Count(); i++)
{
plbiDT = _rglbiDeviceType.Get(i);
if (plbiDT)
{
RemoveItem(*plbiDT->GetGuidItem());
if (plbiDT->Release() > 0)
{
if (psfn && (psfn->dwThreadId == dwThreadId))
{
// Clean up a pointer that is marshalled to UTB.
delete plbiDT;
}
}
}
}
_rglbiDeviceType.Clear();
}
//+---------------------------------------------------------------------------
//
// CreateInstance
//
//----------------------------------------------------------------------------
/* static */
HRESULT CLangBarItemMgr::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
{
CLangBarItemMgr *plbim;
HRESULT hr;
if (ppvObj == NULL)
return E_INVALIDARG;
*ppvObj = NULL;
if (pUnkOuter != NULL)
return CLASS_E_NOAGGREGATION;
if (plbim = _GetThis())
{
return plbim->QueryInterface(riid, ppvObj);
}
SYSTHREAD *psfn = GetSYSTHREAD();
if (!psfn)
return E_OUTOFMEMORY;
if ((plbim = new CLangBarItemMgr(psfn)) == NULL)
return E_OUTOFMEMORY;
if (!plbim->_Init())
{
plbim->Release();
return E_FAIL;
}
hr = plbim->QueryInterface(riid, ppvObj);
plbim->Release();
#ifdef WINLOGON_LANGBAR
ExecuteLoader();
#endif
return hr;
}
//+---------------------------------------------------------------------------
//
// FindDeviceTypeItem
//
//----------------------------------------------------------------------------
CLBarItemDeviceType *CLangBarItemMgr::FindDeviceTypeItem(REFGUID guid)
{
int i;
CLBarItemDeviceType *plbiDT;
for (i = 0; i < _rglbiDeviceType.Count(); i++)
{
plbiDT = _rglbiDeviceType.Get(i);
if (plbiDT)
{
if (IsEqualGUID(*plbiDT->GetDeviceTypeGUID(), guid))
{
return plbiDT;
}
}
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// _Init
//
//----------------------------------------------------------------------------
BOOL CLangBarItemMgr::_Init()
{
CLBarItemDeviceType **pplbiDT;
GUID guid;
//
// set TLF_LBIMGR flag for this thread of timlist.
//
if (EnsureTIMList(_psfn))
{
g_timlist.SetFlags(_psfn->dwThreadId, TLF_LBIMGR);
InitLangChangeHotKey();
}
// init the system default ctls
if (!_plbiCtrl && (_plbiCtrl = new CLBarItemCtrl(_psfn)) == NULL)
return FALSE;
AddItem(_plbiCtrl);
//
// I want to hide a help button on Winlogon.
// But IMJP8 causes av, if we don't have Help button...
//
// if (!IsInWinLogOnDesktop())
{
if (!_plbiHelp && (_plbiHelp = new CLBarItemHelp(_psfn)) != NULL)
{
AddItem(_plbiHelp);
}
}
if (CThreadInputMgr::_GetThis())
{
if (!_plbiReconv && (_plbiReconv = new CLBarItemReconv(_psfn)))
{
AddItem(_plbiReconv);
_plbiReconv->ShowOrHide(FALSE);
}
IEnumGUID *pEnum;
if (SUCCEEDED(CCategoryMgr::s_EnumItemsInCategory(
GUID_TFCAT_CATEGORY_OF_TIP,
&pEnum)))
{
while (pEnum->Next(1, &guid, NULL) == S_OK)
{
if (FindDeviceTypeItem(guid))
continue;
pplbiDT = _rglbiDeviceType.Append(1);
if (pplbiDT)
{
*pplbiDT = new CLBarItemDeviceType(_psfn, guid);
if (*pplbiDT)
{
(*pplbiDT)->Init();
AddItem(*pplbiDT);
}
else
{
int nCnt = _rglbiDeviceType.Count();
if (nCnt)
_rglbiDeviceType.Remove(nCnt - 1, 1);
}
}
}
pEnum->Release();
}
}
else
{
if (!FindDeviceTypeItem(GUID_TFCAT_TIP_KEYBOARD))
{
pplbiDT = _rglbiDeviceType.Append(1);
if (pplbiDT)
{
*pplbiDT = new CLBarItemDeviceType(_psfn, GUID_TFCAT_TIP_KEYBOARD);
if (*pplbiDT)
{
(*pplbiDT)->Init();
AddItem(*pplbiDT);
}
else
{
int nCnt = _rglbiDeviceType.Count();
if (nCnt)
_rglbiDeviceType.Remove(nCnt - 1, 1);
}
}
}
}
if (_plbiCtrl)
{
_plbiCtrl->_UpdateLangIcon(NULL, FALSE);
}
UpdateLangBarAddIns();
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
return TRUE;
}
//+---------------------------------------------------------------------------
//
// CleanUp
//
//----------------------------------------------------------------------------
void CLangBarItemMgr::CleanUp()
{
//
// we can not call COM in PROCESS_DETACH. we just make sure
// if someone forget to call UnRegister.
//
#if 1
// Assert(!_rglbiProxy.Count());
#else
int i;
int nCnt;
nCnt = _rglbiProxy.Count();
for (i = 0; i < nCnt; i++)
{
CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
pProxy->Clear();
pProxy->Release();
}
#endif
_rglbiProxy.Clear();
int i;
int nCnt = _rgSink.Count();
for (i = 0; i < nCnt ; i++)
{
CLBarItemSink *pSink = _rgSink.Get(i);
Assert(pSink);
TraceMsg(TF_GENERAL, "NuiMgr clean up ItemSink - 0x%x08", (UINT_PTR)pSink);
//
// Issue: This is a pointer that is marshalled from UTB.
// If this is called in DllMain(THREAD_DETACH).
// calling Release() cause dead lock....
//
pSink->_pItemSink->Release();
pSink->_pItemSink = NULL;
delete pSink;
}
_rgSink.Clear();
}
//+---------------------------------------------------------------------------
//
// AddItem
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::AddItem(ITfLangBarItem *pItem)
{
ITfSource *pSource = NULL;
HRESULT hr = E_FAIL;
CLBarItemSinkProxy *pProxy;
TF_LANGBARITEMINFO info;
if (pItem == NULL)
return E_INVALIDARG;
if (FAILED(pItem->QueryInterface(IID_ITfSource, (void **)&pSource)))
{
goto Exit;
}
if (SUCCEEDED(pItem->GetInfo(&info)))
{
int i;
int nCnt = _rglbiProxy.Count();
for (i = 0; i < nCnt; i++)
{
pProxy = _rglbiProxy.Get(i);
if (IsEqualGUID(pProxy->_info.guidItem, info.guidItem))
{
hr = E_INVALIDARG;
goto Exit;
}
}
}
else
{
goto Exit;
}
pProxy = new CLBarItemSinkProxy();
if (!pProxy)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
if (!pProxy->Init(this, pItem, &info))
{
goto Exit;
}
if (FAILED(pSource->AdviseSink(IID_ITfLangBarItemSink,
pProxy, &pProxy->_dwCookie)))
{
pProxy->Clear();
pProxy->Release();
}
else
{
int nCnt = _rglbiProxy.Count();
if (!_rglbiProxy.Insert(nCnt, 1))
{
pSource->UnadviseSink(pProxy->_dwCookie);
pProxy->Clear();
pProxy->Release();
hr = E_OUTOFMEMORY;
goto Exit;
}
_rglbiProxy.Set(nCnt, pProxy);
if (!_ulInAssemblyChange)
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
_fItemChanged = TRUE;
hr = S_OK;
}
Exit:
SafeRelease(pSource);
return hr;
}
//+---------------------------------------------------------------------------
//
// RemoveItem
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::RemoveItem(ITfLangBarItem *pItem)
{
TF_LANGBARITEMINFO info;
if (!pItem)
return E_INVALIDARG;
if (FAILED(pItem->GetInfo(&info)))
return E_FAIL;
return RemoveItem(info.guidItem);
}
//+---------------------------------------------------------------------------
//
// RemoveItem
//
//----------------------------------------------------------------------------
HRESULT CLangBarItemMgr::RemoveItem(REFGUID rguid)
{
int nCnt;
int i;
nCnt = _rglbiProxy.Count();
for (i = 0; i < nCnt; i++)
{
CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
if (IsEqualGUID(pProxy->_info.guidItem, rguid))
{
ITfSource *pSource;
if (SUCCEEDED(pProxy->_plbi->QueryInterface(IID_ITfSource,
(void **)&pSource)))
{
pSource->UnadviseSink(pProxy->_dwCookie);
pSource->Release();
}
_rglbiProxy.Remove(i, 1);
pProxy->Clear();
pProxy->Release();
if (!_ulInAssemblyChange)
{
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
}
SYSTHREAD *psfn = FindSYSTHREAD();
if (psfn && (psfn->dwThreadId == _psfn->dwThreadId))
FreeMarshaledStubOfItem(psfn, rguid);
_fItemChanged = TRUE;
break;
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// RegisterItemSink
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::AdviseItemSink(ITfLangBarItemSink *punk, DWORD *pdwCookie, REFGUID rguidItem)
{
CLBarItemSinkProxy *pProxy;
CLBarItemSink *pSink;
int nCnt;
HRESULT hr;
if (pdwCookie == NULL)
return E_POINTER;
*pdwCookie = 0;
if (punk == NULL)
return E_POINTER;
pProxy = GetItemSinkProxy(rguidItem);
if (!pProxy)
return E_INVALIDARG;
pSink = new CLBarItemSink();
if (!pSink)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
*pdwCookie = _GetCookie();
if (!pSink->Init(punk, &pProxy->_info, *pdwCookie))
{
hr = E_FAIL;
goto Exit;
}
nCnt = _rgSink.Count();
if (!_rgSink.Insert(nCnt, 1))
{
hr = E_OUTOFMEMORY;
goto Exit;
}
_rgSink.Set(nCnt, pSink);
hr = S_OK;
Exit:
return hr;
}
//+---------------------------------------------------------------------------
//
// UnregisterItemSink
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::UnadviseItemSink(DWORD dwCookie)
{
int i;
int nCnt = _rgSink.Count();
for (i = 0; i < nCnt ; i++)
{
CLBarItemSink *pSink = _rgSink.Get(i);
if (pSink->_dwCookie == dwCookie)
{
#ifdef DEBUG
pSink->_fUnadvised = TRUE;
#endif
_rgSink.Remove(i, 1);
delete pSink;
break;
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetItemFloatingRect
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
{
if (!prc)
return E_INVALIDARG;
if (!dwThreadId)
dwThreadId = GetCurrentThreadId();
memset(prc, 0, sizeof(*prc));
return ThreadGetItemFloatingRect(dwThreadId, rguid, prc);
}
//+---------------------------------------------------------------------------
//
// GetItemsStatus
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::GetItemsStatus(ULONG ulCount, const GUID *prgguid, DWORD *pdwStatus)
{
ULONG ul;
for (ul = 0; ul < ulCount; ul++)
{
int i;
BOOL fFound = FALSE;
for (i = 0; i < _rglbiProxy.Count(); i++)
{
CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
if (IsEqualGUID(pProxy->_info.guidItem, *prgguid))
{
if (FAILED(pProxy->_plbi->GetStatus(pdwStatus)))
return E_FAIL;
pdwStatus++;
prgguid++;
fFound = TRUE;
break;
}
}
if (!fFound)
return E_FAIL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetItemNum
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::GetItemNum(ULONG *pulCount)
{
if (!pulCount)
return E_INVALIDARG;
*pulCount = _rglbiProxy.Count();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetItems
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::GetItems(ULONG ulCount, ITfLangBarItem **ppItem, TF_LANGBARITEMINFO *pInfo, DWORD *pdwStatus, ULONG *pcFetched)
{
int i;
ULONG ulFetched = 0;
CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
BOOL fHasFocusDIM;
if (!ulCount)
return S_FALSE;
fHasFocusDIM = (ptim && ptim->_GetFocusDocInputMgr()) ? TRUE : FALSE;
for (i = 0; i < _rglbiProxy.Count(); i++)
{
CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
if (!fHasFocusDIM && pProxy->_fCicTip)
continue;
if (FAILED(pProxy->_plbi->GetInfo(pInfo)))
return E_FAIL;
pInfo++;
if (FAILED(pProxy->_plbi->GetStatus(pdwStatus)))
return E_FAIL;
pdwStatus++;
*ppItem = pProxy->_plbi;
pProxy->_plbi->AddRef();
ppItem++;
ulFetched++;
if (ulFetched >= ulCount)
break;
}
if (pcFetched)
*pcFetched = ulFetched;
return (ulFetched == ulCount) ? S_OK : S_FALSE;
}
//+---------------------------------------------------------------------------
//
// AdviseItemsSink
//
//----------------------------------------------------------------------------
STDMETHODIMP CLangBarItemMgr::AdviseItemsSink(ULONG ulCount, ITfLangBarItemSink **ppunk, const GUID *pguidItem, DWORD *pdwCookie)
{
ULONG ul;
for ( ul = 0; ul < ulCount; ul++)
{
if (FAILED(AdviseItemSink(ppunk[ul], &pdwCookie[ul], pguidItem[ul])))
return E_FAIL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// UnadviseItemsSink
//
//----------------------------------------------------------------------------
STDMETHODIMP CLangBarItemMgr::UnadviseItemsSink(ULONG ulCount, DWORD *pdwCookie)
{
ULONG ul;
for ( ul = 0; ul < ulCount; ul++)
{
if (FAILED(UnadviseItemSink(pdwCookie[ul])))
return E_FAIL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// EnumLBItem
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::EnumItems(IEnumTfLangBarItems **ppEnum)
{
CEnumLBItem *pEnum = new CEnumLBItem(_psfn);
*ppEnum = pEnum;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetItem
//
//----------------------------------------------------------------------------
STDAPI CLangBarItemMgr::GetItem(REFGUID rguid, ITfLangBarItem **ppItem)
{
if (!ppItem)
return E_INVALIDARG;
*ppItem = NULL;
CLBarItemSinkProxy *pProxy = GetItemSinkProxy(rguid);
if (pProxy)
{
*ppItem = pProxy->_plbi;
(*ppItem)->AddRef();
}
return *ppItem ? S_OK : S_FALSE;
}
//+---------------------------------------------------------------------------
//
// _AddWin32IMECtrl
//
//----------------------------------------------------------------------------
void CLangBarItemMgr::_AddWin32IMECtrl(BOOL fNotify)
{
if (_plbiWin32IME != NULL)
return;
if (_plbiWin32IME = new CLBarItemWin32IME)
{
AddItem(_plbiWin32IME);
_plbiWin32IME->ShowInternal(TRUE, fNotify);
}
}
//+---------------------------------------------------------------------------
//
// _RemoveWin32IMECtrl
//
//----------------------------------------------------------------------------
void CLangBarItemMgr::_RemoveWin32IMECtrl()
{
if (_plbiWin32IME == NULL)
return;
RemoveItem(_plbiWin32IME);
}
//+---------------------------------------------------------------------------
//
// GetItemSinkProxy
//
//----------------------------------------------------------------------------
CLBarItemSinkProxy *CLangBarItemMgr::GetItemSinkProxy(REFGUID rguid)
{
CLBarItemSinkProxy *pProxy = NULL;
int nCnt = _rglbiProxy.Count();
int i;
for (i = 0; i < nCnt; i++)
{
CLBarItemSinkProxy *pProxyTemp = _rglbiProxy.Get(i);
if (IsEqualGUID(pProxyTemp->_info.guidItem, rguid))
{
pProxy = pProxyTemp;
break;
}
}
return pProxy;
}
//+---------------------------------------------------------------------------
//
// UpdateIcon
//
//----------------------------------------------------------------------------
HRESULT CLangBarItemMgr::OnUpdate(ITfLangBarItem *plbi, DWORD dwFlags)
{
int i;
int nCnt;
HRESULT hr;
TF_LANGBARITEMINFO info;
BOOL fFound;
//
// Toolbar will be being updated. So no need to handle OnUpdate.
// Toolbar will ask icons, bitmaps no matter what.
//
if (!_fHandleOnUpdate)
return S_OK;
hr = plbi->GetInfo(&info);
if (FAILED(hr))
return hr;
fFound = FALSE;
nCnt = _rgSink.Count();
for (i = 0; i < nCnt ; i++)
{
CLBarItemSink *pSink = _rgSink.Get(i);
#ifdef DEBUG
Assert(!pSink->_fUnadvised);
#endif
if (IsEqualGUID(pSink->_info.guidItem, info.guidItem))
{
pSink->_dwDirtyUpdateFlags |= dwFlags;
fFound = TRUE;
}
}
if (_fDirtyUpdateHandling)
{
//
// #509783
//
// Some apps (Adobe PhotoShop) call PeekMessage() to eat the message
// from queue but it does not call DispatchMessage() sometimes.
// We need a way to restore _fDirtyUpdateHandling flag.
//
if (GetTickCount() - dwDirtyUpdateHandlingTime > 1000)
{
_fDirtyUpdateHandling = 0;
}
}
if (fFound && !_fDirtyUpdateHandling)
{
HWND hwnd = EnsureMarshalWnd();
if (hwnd)
{
PostMessage(hwnd, g_msgNuiMgrDirtyUpdate, 0, 0);
_fDirtyUpdateHandling = TRUE;
dwDirtyUpdateHandlingTime = GetTickCount();
//
// we need to check Kana-Caps status every time the langbar item
// is updated.
//
SYSTHREAD *psfn = FindSYSTHREAD();
if (psfn)
StartKanaCapsUpdateTimer(psfn);
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnUpdateHandler
//
//----------------------------------------------------------------------------
HRESULT CLangBarItemMgr::OnUpdateHandler()
{
int i;
int nCnt;
_fDirtyUpdateHandling = FALSE;
_fInOnUpdateHandler = TRUE;
nCnt = _rgSink.Count();
for (i = 0; i < nCnt ; i++)
{
CLBarItemSink *pSink = _rgSink.Get(i);
DWORD dwFlags = pSink->_dwDirtyUpdateFlags;
if (!dwFlags)
continue;
pSink->_dwDirtyUpdateFlags = 0;
pSink->_pItemSink->OnUpdate(dwFlags);
int nCntNew = _rgSink.Count();
if (nCnt > nCntNew)
{
nCnt = nCntNew;
i--;
}
}
_fInOnUpdateHandler = FALSE;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//
// CLBarItemSinkProxy
//
//////////////////////////////////////////////////////////////////////////////
BOOL CLBarItemSinkProxy::Init(CLangBarItemMgr *plbiMgr, ITfLangBarItem *plbi, TF_LANGBARITEMINFO *pinfo)
{
_plbiMgr = plbiMgr; // don't AddRef, because this obj is contained in the mgr's life
// we'd create a circular ref if we did, and we don't need to
_plbi = plbi;
_plbi->AddRef();
_fCicTip = FALSE;
_info = *pinfo;
CTip *ptip;
TfGuidAtom guidatom;
CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
if (ptim && SUCCEEDED(MyRegisterGUID(_info.clsidService, &guidatom)))
{
_fCicTip = ptim->_GetCTipfromGUIDATOM(guidatom, &ptip);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//
// CEnumLBItem
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CEnumLBItem::CEnumLBItem(SYSTHREAD *psfn) : CSysThreadRef(psfn)
{
Dbg_MemSetThisNameID(TEXT("CEnumLBItem"));
CThreadInputMgr *ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(_psfn);
if (ptim)
_fHasFocusDIM = ptim->_GetFocusDocInputMgr() ? TRUE : FALSE;
_nCur = 0;
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CEnumLBItem::~CEnumLBItem()
{
}
//+---------------------------------------------------------------------------
//
// Clone
//
//----------------------------------------------------------------------------
HRESULT CEnumLBItem::Clone(IEnumTfLangBarItems **ppEnum)
{
return E_NOTIMPL;
}
//+---------------------------------------------------------------------------
//
// Next
//
//----------------------------------------------------------------------------
HRESULT CEnumLBItem::Next(ULONG ulCount, ITfLangBarItem **ppLBItem, ULONG *pcFetched)
{
int nCnt;
ULONG cFetched;
CLangBarItemMgr *plbim = _psfn->plbim;
if (!plbim)
return E_FAIL;
nCnt = plbim->_rglbiProxy.Count();
cFetched = 0;
if (!ppLBItem)
return E_INVALIDARG;
*ppLBItem = NULL;
while (cFetched < ulCount)
{
*ppLBItem = NULL;
CLBarItemSinkProxy *pProxy;
if (nCnt <= _nCur)
break;
pProxy = plbim->_rglbiProxy.Get(_nCur);
if (!pProxy)
break;
if (_fHasFocusDIM || !pProxy->_fCicTip)
{
*ppLBItem = pProxy->_plbi;
(*ppLBItem)->AddRef();
ppLBItem++;
cFetched++;
}
_nCur++;
}
if (pcFetched)
*pcFetched = cFetched;
return (cFetched == ulCount) ? S_OK : S_FALSE;
}
//+---------------------------------------------------------------------------
//
// Reset
//
//----------------------------------------------------------------------------
HRESULT CEnumLBItem::Reset()
{
_nCur = 0;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Skip
//
//----------------------------------------------------------------------------
HRESULT CEnumLBItem::Skip(ULONG ulCount)
{
int nCnt;
CLangBarItemMgr *plbim = _psfn->plbim;
if (!plbim)
return E_FAIL;
nCnt = plbim->_rglbiProxy.Count();
while (ulCount)
{
if (nCnt <= _nCur)
break;
_nCur++;
ulCount--;
}
return ulCount ? S_FALSE : S_OK;
}