|
|
//
// focusnfy.cpp
//
#include "private.h"
#include "globals.h"
#include "thdutil.h"
#include "cicmutex.h"
#include "tim.h"
#include "internat.h"
#include "marshal.h"
#include "catmgr.h"
#include "timlist.h"
#include "ithdmshl.h"
#include "marshal.h"
#include "shlapip.h"
const DWORD TF_LBESF_GLOBAL = 0x0001; const DWORD TF_LBSMI_FILTERCURRENTTHREAD = 0x0001;
LPVOID SharedAlloc(UINT cbSize,DWORD dwProcessId,HANDLE *pProcessHandle); VOID SharedFree(LPVOID lpv,HANDLE hProcess);
CStructArray<LBAREVENTSINKLOCAL> *g_rglbes = NULL; extern CCicMutex g_mutexLBES;
void CallFocusNotifySink(ITfLangBarEventSink *pSink, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fLocalSink, DWORD dwSinkCookie);
// --------------------------------------------------------------------------
//
// FindLBES
//
// --------------------------------------------------------------------------
int FindLBES() { int nId = -1;
for (nId = 0; nId < MAX_LPES_NUM; nId++) { if (!(GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE)) break;
if (!g_timlist.IsThreadId(GetSharedMemory()->lbes[nId].m_dwThreadId)) { //
// Bug#354475 - Explorer can call deskband(msutb.dll module)
// directly before loading the ctfmon.exe process. In this case,
// explorer tray window thread didn't recognized by g_timlist.
// Since shared block memory didn't create yet. So checking the
// tray window thread and keep up language bar event sink for
// language deskband support.
//
// Bug#370802
// we can not cache the window handle because explorer could
// crash. And we don't have a window to track "TaskbarCreated"
// message. The shell message is boradcasted by SendNotifyMessage()
// with HWMD_BROADCASTR. So the marshal window can not get it.
//
HWND hwndTray; DWORD dwThreadIdTray = 0;
hwndTray = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
if (hwndTray) dwThreadIdTray = GetWindowThreadProcessId(hwndTray, NULL);
if (!dwThreadIdTray || dwThreadIdTray != GetSharedMemory()->lbes[nId].m_dwThreadId) break; } }
if (nId == MAX_LPES_NUM) { nId = -1; }
return nId; }
// --------------------------------------------------------------------------
//
// IntrnalRegisterLangBarNotifySink
//
// --------------------------------------------------------------------------
HRESULT RegisterLangBarNotifySink(ITfLangBarEventSink *pSink, HWND hwnd, DWORD dwFlags, DWORD *pdwCookie) { HRESULT hr = E_FAIL; int nId;
//
// Bugbug#376500 - When CPL runs ctfmon.exe with deskband status, ThreadId
// list doesn't include ctfmon thread, so need to make sure thread id list.
//
SYSTHREAD *psfn = GetSYSTHREAD(); if (psfn) EnsureTIMList(psfn);
if (!(dwFlags & TF_LBESF_GLOBAL)) { int nCnt; LBAREVENTSINKLOCAL *plbes;
//
// Local LangBarEventSink
//
CicEnterCriticalSection(g_csInDllMain);
nCnt = g_rglbes->Count(); if (g_rglbes->Insert(nCnt,1)) { plbes = g_rglbes->GetPtr(nCnt);
plbes->m_pSink = pSink; pSink->AddRef();
plbes->lb.m_dwThreadId = GetCurrentThreadId(); plbes->lb.m_dwProcessId = GetCurrentProcessId(); plbes->lb.m_dwCookie = GetSharedMemory()->dwlbesCookie++; plbes->lb.m_dwLangBarFlags = dwFlags; *pdwCookie = plbes->lb.m_dwCookie; plbes->lb.m_hWnd = hwnd; plbes->lb.m_dwFlags = LBESF_INUSE; hr = S_OK; }
CicLeaveCriticalSection(g_csInDllMain); } else { if (psfn) { CCicMutexHelper mutexhlp(&g_mutexLBES); //
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { if ((nId = FindLBES()) != -1) { GetSharedMemory()->lbes[nId].m_dwThreadId = GetCurrentThreadId(); GetSharedMemory()->lbes[nId].m_dwProcessId = GetCurrentProcessId(); GetSharedMemory()->lbes[nId].m_dwCookie = GetSharedMemory()->dwlbesCookie++; GetSharedMemory()->lbes[nId].m_dwLangBarFlags = dwFlags; *pdwCookie = GetSharedMemory()->lbes[nId].m_dwCookie; GetSharedMemory()->lbes[nId].m_hWnd = hwnd; GetSharedMemory()->lbes[nId].m_dwFlags = LBESF_INUSE;
psfn->_pLangBarEventSink = pSink; pSink->AddRef(); psfn->_dwLangBarEventCookie = *pdwCookie;
hr = S_OK; } mutexhlp.Leave(); } } }
return hr; }
// --------------------------------------------------------------------------
//
// UnregisterLangBarNotifySink
//
// --------------------------------------------------------------------------
HRESULT UnregisterLangBarNotifySink(DWORD dwCookie) { DWORD dwThreadId = GetCurrentThreadId(); DWORD dwProcessId = GetCurrentProcessId(); HRESULT hr = E_FAIL; int nId; int nCnt; SYSTHREAD *psfn = GetSYSTHREAD(); CCicMutexHelper mutexhlp(&g_mutexLBES); BOOL fUnregistereGlobalSink = FALSE;
//
// Local LangBarEventSink
//
CicEnterCriticalSection(g_csInDllMain);
nCnt = g_rglbes->Count(); for (nId = 0; nId < nCnt; nId++) { LBAREVENTSINKLOCAL *plbes; plbes = g_rglbes->GetPtr(nId);
if ((plbes->lb.m_dwCookie == dwCookie) && (plbes->lb.m_dwThreadId == dwThreadId) && (plbes->lb.m_dwProcessId == dwProcessId)) { //
// if the process of msutb.dll is killed, pSink is bogus pointer.
// And this is expected in the unusuall case.
//
_try { plbes->m_pSink->Release(); } _except(CicExceptionFilter(GetExceptionInformation())) { // Assert(0);
} plbes->m_pSink = NULL; g_rglbes->Remove(nId, 1); hr = S_OK; goto ExitCrit; } }
ExitCrit: CicLeaveCriticalSection(g_csInDllMain);
if (SUCCEEDED(hr)) goto Exit;
if (!psfn) goto Exit;
//
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if ((GetSharedMemory()->lbes[nId].m_dwCookie == dwCookie) && (GetSharedMemory()->lbes[nId].m_dwThreadId == dwThreadId) && (GetSharedMemory()->lbes[nId].m_dwProcessId == dwProcessId) && (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie)) { //
// if the process of msutb.dll is killed, pSink is bogus pointer.
// And this is expected in the unusuall case.
//
_try { psfn->_pLangBarEventSink->Release(); } _except(CicExceptionFilter(GetExceptionInformation())) { // Assert(0);
}
psfn->_pLangBarEventSink=NULL; psfn->_dwLangBarEventCookie=NULL;
GetSharedMemory()->lbes[nId].m_dwCookie = 0; GetSharedMemory()->lbes[nId].m_dwThreadId = 0; GetSharedMemory()->lbes[nId].m_dwProcessId = 0; GetSharedMemory()->lbes[nId].m_dwFlags = 0; fUnregistereGlobalSink = TRUE; hr = S_OK; goto ExitMutex; } } ExitMutex: mutexhlp.Leave(); }
//
// clean up all amrshaling stubs.
//
if (fUnregistereGlobalSink) FreeMarshaledStubs(psfn);
Exit: return hr; }
// -------------------------------------------------------------------------
//
// TLFlagFromMsg
//
// -------------------------------------------------------------------------
DWORD TLFlagFromMsg(UINT uMsg) { if (uMsg == g_msgSetFocus) return LBESF_SETFOCUSINQUEUE;
return 0; }
// --------------------------------------------------------------------------
//
// MakeSetFocusNotify
//
// --------------------------------------------------------------------------
void MakeSetFocusNotify(UINT uMsg, WPARAM wParam, LPARAM lParam) { int nId; DWORD dwCurThreadId = GetCurrentThreadId(); int nCnt; DWORD dwPostThread[MAX_LPES_NUM]; CCicMutexHelper mutexhlp(&g_mutexLBES); DWORD dwMsgMaskFlag = TLFlagFromMsg(uMsg);
if (uMsg == g_msgSetFocus) { SYSTHREAD *psfn = GetSYSTHREAD(); TF_InitMlngInfo(); CCategoryMgr::InitGlobal(); EnsureAssemblyList(psfn); EnsureMarshalWnd(); //EnsureLangBarItemMgr(psfn);
EnsureTIMList(psfn);
//
// I think this is a bogus assert, but it is better to catch the case
// to find another case this happen rather than OLE embedded apps.
//
// Assert(dwCurThreadId == GetSharedMemory()->dwFocusThread);
TraceMsg(TF_GENERAL, "Make SetFocus notify %x", dwCurThreadId); }
//
// Local LangBarEventSink
//
CicEnterCriticalSection(g_csInDllMain);
nCnt = g_rglbes->Count(); for (nId = 0; nId < nCnt; nId++) { LBAREVENTSINKLOCAL *plbes; DWORD dwThreadId;
plbes = g_rglbes->GetPtr(nId); Assert(!(plbes->lb.m_dwLangBarFlags & TF_LBESF_GLOBAL)); dwThreadId = plbes->lb.m_dwThreadId;
if (dwThreadId != dwCurThreadId) continue;
Assert(plbes->lb.m_dwFlags & LBESF_INUSE);
if (!(plbes->lb.m_dwFlags & dwMsgMaskFlag)) { PostThreadMessage(dwThreadId, uMsg, 0, lParam);
//
// set message mask.
//
plbes->lb.m_dwFlags |= dwMsgMaskFlag; } }
CicLeaveCriticalSection(g_csInDllMain);
//
// Global LangBarEventSink
//
BOOL fInDllMain = ISINDLLMAIN(); if (fInDllMain || mutexhlp.Enter()) { BOOL fPost = FALSE;
for (nId = 0; nId < MAX_LPES_NUM; nId++) { DWORD dwFlags = GetSharedMemory()->lbes[nId].m_dwFlags;
// init array.
dwPostThread[nId] = 0;
if (!(dwFlags & LBESF_INUSE)) continue;
DWORD dwTargetProcessId = g_timlist.GetProcessId(GetSharedMemory()->lbes[nId].m_dwThreadId); if (dwTargetProcessId && (GetSharedMemory()->lbes[nId].m_dwProcessId != dwTargetProcessId)) { //
// thread on the process is gone without cleaninglbes.
//
Assert(0); GetSharedMemory()->lbes[nId].m_dwFlags &= ~LBESF_INUSE; continue; }
Assert(GetSharedMemory()->lbes[nId].m_dwLangBarFlags & TF_LBESF_GLOBAL);
//
// Check the msg mask bit so there won't be duplicated messages.
//
if (dwFlags & dwMsgMaskFlag) continue;
//
// avoid from posting exactly same messages into the queue.
//
if ((GetSharedMemory()->lbes[nId].m_lastmsg.uMsg == uMsg) && (GetSharedMemory()->lbes[nId].m_lastmsg.wParam == wParam) && (GetSharedMemory()->lbes[nId].m_lastmsg.lParam == lParam)) continue;
fPost = TRUE; dwPostThread[nId] = GetSharedMemory()->lbes[nId].m_dwThreadId;
//
// set message mask.
//
GetSharedMemory()->lbes[nId].m_dwFlags |= dwMsgMaskFlag;
//
// update last posted message.
//
GetSharedMemory()->lbes[nId].m_lastmsg.uMsg = uMsg; GetSharedMemory()->lbes[nId].m_lastmsg.wParam = wParam; GetSharedMemory()->lbes[nId].m_lastmsg.lParam = lParam; }
if (fPost) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if (dwPostThread[nId]) PostThreadMessage(dwPostThread[nId], uMsg, wParam, lParam); } }
if (!fInDllMain) mutexhlp.Leave(); } }
//+---------------------------------------------------------------------------
//
// GetThreadInputIdle()
//
//----------------------------------------------------------------------------
DWORD GetThreadInputIdle(DWORD dwProcessId, DWORD dwThreadId) { DWORD dwRet = 0;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess) { dwRet = WaitForInputIdle(hProcess, 0); CloseHandle(hProcess); }
return dwRet; }
// --------------------------------------------------------------------------
//
// NotifyTryAgain
//
// --------------------------------------------------------------------------
BOOL NotifyTryAgain(DWORD dwProcessId, DWORD dwThreadId) { if (IsOnNT()) { if (!CicIs16bitTask(dwProcessId, dwThreadId)) { DWORD dwRet = GetThreadInputIdle(dwProcessId, dwThreadId); if (dwRet && (dwRet != WAIT_FAILED)) return TRUE; } } else { DWORD dwThreadFlags = 0; if (TF_GetThreadFlags(dwThreadId, &dwThreadFlags, NULL, NULL)) { if (dwThreadFlags & TLF_NOWAITFORINPUTIDLEONWIN9X) return FALSE; }
DWORD dwRet = GetThreadInputIdle(dwProcessId, dwThreadId); if (dwRet && (dwRet != WAIT_FAILED)) return TRUE; } return FALSE; }
// --------------------------------------------------------------------------
//
// SetFocusNotifyHandler
//
// --------------------------------------------------------------------------
void SetFocusNotifyHandler(UINT uMsg, WPARAM wParam, LPARAM lParam) { int nId; DWORD dwCurThreadId = GetCurrentThreadId(); DWORD dwCurProcessId = GetCurrentProcessId(); int nCnt; ITfLangBarEventSink *pSinkLocal = NULL; ITfLangBarEventSink *pSinkGlobal = NULL; DWORD dwSinkCookie = 0; DWORD dwMsgMaskFlag = TLFlagFromMsg(uMsg); MSG msg; SYSTHREAD *psfn = GetSYSTHREAD();
if (PeekMessage(&msg, NULL, uMsg, uMsg, PM_NOREMOVE | PM_NOYIELD)) { if ((msg.message == uMsg) && (msg.wParam == wParam) && (msg.lParam == lParam)) return; }
if ((uMsg == g_msgThreadTerminate) && psfn) { FreeMarshaledStubsForThread(psfn, (DWORD)lParam); }
//
// Local LangBarEventSink
//
CicEnterCriticalSection(g_csInDllMain);
nCnt = g_rglbes->Count(); for (nId = 0; nId < nCnt; nId++) { LBAREVENTSINKLOCAL *plbes = g_rglbes->GetPtr(nId);
Assert(!(plbes->lb.m_dwLangBarFlags & TF_LBESF_GLOBAL));
if (plbes->lb.m_dwThreadId == dwCurThreadId) { pSinkLocal = plbes->m_pSink;
dwSinkCookie = plbes->lb.m_dwCookie;
//
// clear message mask.
//
plbes->lb.m_dwFlags &= ~dwMsgMaskFlag;
break; } } CicLeaveCriticalSection(g_csInDllMain);
if (psfn) { CCicMutexHelper mutexhlp(&g_mutexLBES); //
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if ((GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE) && (GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) && (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) && (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie)) { pSinkGlobal = psfn->_pLangBarEventSink;
dwSinkCookie = GetSharedMemory()->lbes[nId].m_dwCookie;
//
// clear message mask.
//
GetSharedMemory()->lbes[nId].m_dwFlags &= ~dwMsgMaskFlag;
//
// clear last posted message.
//
GetSharedMemory()->lbes[nId].m_lastmsg.uMsg = 0; GetSharedMemory()->lbes[nId].m_lastmsg.wParam = 0; GetSharedMemory()->lbes[nId].m_lastmsg.lParam = 0; break; } } mutexhlp.Leave(); } }
if (pSinkLocal) CallFocusNotifySink(pSinkLocal, uMsg, wParam, lParam, TRUE, dwSinkCookie);
if (pSinkGlobal) CallFocusNotifySink(pSinkGlobal, uMsg, wParam, lParam, FALSE, dwSinkCookie); }
// --------------------------------------------------------------------------
//
// CallFocusNotifySink
//
// --------------------------------------------------------------------------
void CallFocusNotifySink(ITfLangBarEventSink *pSink, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fLocalSink, DWORD dwSinkCookie) { DWORD dwCurThreadId = GetCurrentThreadId(); DWORD dwCurProcessId = GetCurrentProcessId(); SYSTHREAD *psfn; if (uMsg == g_msgSetFocus) { DWORD dwActiveThreadId; dwActiveThreadId = GetSharedMemory()->dwFocusThread; if (g_timlist.IsThreadId(dwActiveThreadId)) { DWORD dwProcessId = GetSharedMemory()->dwFocusProcess; if (dwProcessId != dwCurProcessId) { #if 0
if (NotifyTryAgain(dwProcessId, dwActiveThreadId)) { HWND hwndMarshal; if (hwndMarshal = EnsureMarshalWnd()) { KillTimer(hwndMarshal, MARSHALWND_TIMER_WAITFORINPUTIDLEFORSETFOCUS); SetTimer(hwndMarshal, MARSHALWND_TIMER_WAITFORINPUTIDLEFORSETFOCUS, 100, NULL); } goto Exit; } #endif
} if ((!fLocalSink || dwActiveThreadId == dwCurThreadId) && (psfn = GetSYSTHREAD())) { psfn->fInmsgSetFocus = TRUE; _try { pSink->OnSetFocus(dwActiveThreadId); } _except(CicExceptionFilter(GetExceptionInformation())) { //
// On NT5, if we get an exception in MsgHookProc,
// it is unhooked by system. To keep the hook,
// we handle any excpeiton here.
//
Assert(0);
//
// Then we enregister the Sink. Don't use it any more.
//
// UnregisterLangBarNotifySink(dwSinkCookie);
} psfn->fInmsgSetFocus = FALSE; } } } else if (uMsg == g_msgThreadTerminate) { if (!fLocalSink && // skip this call for local sinks, they should already be unadvised
(psfn = GetSYSTHREAD())) { psfn->fInmsgThreadTerminate = TRUE; _try { pSink->OnThreadTerminate((DWORD)lParam); } _except(CicExceptionFilter(GetExceptionInformation())) { //
// On NT5, if we get an exception in MsgHookProc,
// it is unhooked by system. To keep the hook,
// we handle any excpeiton here.
//
Assert(0);
//
// Then we enregister the Sink. Don't use it any more.
//
// UnregisterLangBarNotifySink(dwSinkCookie);
} psfn->fInmsgThreadTerminate = FALSE; } } else if (uMsg == g_msgThreadItemChange) { if (g_timlist.IsThreadId((DWORD)lParam) && (psfn = GetSYSTHREAD())) { DWORD dwProcessId;
if (psfn->fInmsgThreadItemChange) goto Exit;
if ((DWORD)lParam == GetSharedMemory()->dwFocusThread) dwProcessId = GetSharedMemory()->dwFocusProcess; else dwProcessId = g_timlist.GetProcessId((DWORD)lParam);
#if 0
if (dwProcessId != dwCurProcessId) { if (NotifyTryAgain(dwProcessId, (DWORD)lParam)) { PostThreadMessage(dwCurThreadId,uMsg, 0, lParam); goto Exit; } } #endif
psfn->fInmsgThreadItemChange = TRUE; _try { pSink->OnThreadItemChange((DWORD)lParam); } _except(CicExceptionFilter(GetExceptionInformation())) { //
// On NT5, if we get an exception in MsgHookProc,
// it is unhooked by system. To keep the hook,
// we handle any excpeiton here.
//
Assert(0);
//
// Then we enregister the Sink. Don't use it any more.
//
// UnregisterLangBarNotifySink(dwSinkCookie);
} psfn->fInmsgThreadItemChange = FALSE; } } else if (uMsg == g_msgShowFloating) { _try { pSink->ShowFloating((DWORD)lParam); } _except(CicExceptionFilter(GetExceptionInformation())) { //
// On NT5, if we get an exception in MsgHookProc,
// it is unhooked by system. To keep the hook,
// we handle any excpeiton here.
//
Assert(0);
//
// Then we enregister the Sink. Don't use it any more.
//
// UnregisterLangBarNotifySink(dwSinkCookie);
} } else if (uMsg == g_msgLBUpdate) { _try { ITfLangBarEventSink_P *pSinkP; if (SUCCEEDED(pSink->QueryInterface(IID_ITfLangBarEventSink_P, (void **)&pSinkP)) && pSinkP) { pSinkP->OnLangBarUpdate((DWORD)wParam, lParam); pSinkP->Release(); } } _except(CicExceptionFilter(GetExceptionInformation())) { //
// On NT5, if we get an exception in MsgHookProc,
// it is unhooked by system. To keep the hook,
// we handle any excpeiton here.
//
Assert(0);
//
// Then we enregister the Sink. Don't use it any more.
//
// UnregisterLangBarNotifySink(dwSinkCookie);
} }
Exit: return; }
// --------------------------------------------------------------------------
//
// SetModalLBarSink
//
// --------------------------------------------------------------------------
void SetModalLBarSink(DWORD dwTargetThreadId, BOOL fSet, DWORD dwFlags) { int nId; CCicMutexHelper mutexhlp(&g_mutexLBES);
Assert(!(0xffff0000 & dwFlags));
//
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if (GetSharedMemory()->lbes[nId].m_dwThreadId == GetCurrentThreadId()) { LPARAM lParam = (LPARAM)((nId << 16) + (dwFlags & 0xffff)); PostThreadMessage(dwTargetThreadId, g_msgPrivate, fSet ? TFPRIV_SETMODALLBAR : TFPRIV_RELEASEMODALLBAR, (LPARAM)lParam); break; } } mutexhlp.Leave(); } }
// --------------------------------------------------------------------------
//
// SetModalLBarId
//
// --------------------------------------------------------------------------
void SetModalLBarId(int nId, DWORD dwFlags) { SYSTHREAD *psfn;
if (psfn = GetSYSTHREAD()) { psfn->nModalLangBarId = nId; psfn->dwModalLangBarFlags = dwFlags; } }
// --------------------------------------------------------------------------
//
// HandlModalLBar
//
// --------------------------------------------------------------------------
BOOL HandleModalLBar(UINT uMsg, WPARAM wParam, LPARAM lParam) { SYSTHREAD *psfn = GetSYSTHREAD(); DWORD dwThreadId = 0;
if (psfn == NULL) return FALSE;
if (psfn->nModalLangBarId == -1) return FALSE;
if ((((uMsg >= WM_NCMOUSEMOVE) && (uMsg <= WM_NCMBUTTONDBLCLK)) || ((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST))) && (psfn->dwModalLangBarFlags & TF_LBSMI_FILTERCURRENTTHREAD)) { POINT pt = {LOWORD((DWORD)lParam), HIWORD((DWORD)lParam)}; HWND hwnd = WindowFromPoint(pt); if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd, NULL)) return FALSE; }
CCicMutexHelper mutexhlp(&g_mutexLBES); //
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { if (GetSharedMemory()->lbes[psfn->nModalLangBarId].m_dwFlags & LBESF_INUSE) dwThreadId = GetSharedMemory()->lbes[psfn->nModalLangBarId].m_dwThreadId;
mutexhlp.Leave(); }
if (!dwThreadId) { psfn->nModalLangBarId = -1; return FALSE; } Assert(g_timlist.IsThreadId(dwThreadId));
//
// Here, we will lost HIWORD(uMsg) and HIWORD(wParam).
//
// if we need scan code for WM_KEYxxx, message. we need to put it
// HIBYTE(LOWORD(wParam))
//
PostThreadMessage(dwThreadId, g_msgLBarModal, (WPARAM)((LOWORD(uMsg) << 16) | LOWORD(wParam)), lParam); return TRUE; }
// --------------------------------------------------------------------------
//
// DispatchModalLBar
//
// --------------------------------------------------------------------------
BOOL DispatchModalLBar(WPARAM wParam, LPARAM lParam) { int nId;
SYSTHREAD *psfn = GetSYSTHREAD(); if (!psfn) return FALSE;
DWORD dwCurThreadId = GetCurrentThreadId(); DWORD dwCurProcessId = GetCurrentProcessId(); ITfLangBarEventSink *pSink = NULL;
//
// we don't need to check Local LangBarEventSink
//
CCicMutexHelper mutexhlp(&g_mutexLBES); //
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if ((GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE) && (GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) && (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) && (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie)) { pSink = psfn->_pLangBarEventSink; break; } } mutexhlp.Leave(); } if (pSink) { //
// restore uMsg and wParam from posted wParam.
//
_try { pSink->OnModalInput(GetSharedMemory()->dwFocusThread, (UINT)HIWORD(wParam), (WPARAM)LOWORD(wParam), lParam); } _except(CicExceptionFilter(GetExceptionInformation())) { Assert(0); } } return TRUE; }
// --------------------------------------------------------------------------
//
// ThreadGetItemFloatingRect
//
// --------------------------------------------------------------------------
HRESULT ThreadGetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc) { SYSTHREAD *psfn = GetSYSTHREAD(); if (!psfn) return E_FAIL;
DWORD dwCurThreadId = GetCurrentThreadId(); DWORD dwCurProcessId = GetCurrentProcessId(); ITfLangBarEventSink *pSink = NULL; DWORD dwThreadIdSink = 0; int nId;
CCicMutexHelper mutexhlp(&g_mutexLBES); //
// Global LangBarEventSink
//
if (mutexhlp.Enter()) { for (nId = 0; nId < MAX_LPES_NUM; nId++) { if (GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE) { if (!dwThreadIdSink) dwThreadIdSink = GetSharedMemory()->lbes[nId].m_dwThreadId;
if ((GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) && (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) && (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie)) { pSink = psfn->_pLangBarEventSink; break; } } } mutexhlp.Leave(); }
if (pSink) return pSink->GetItemFloatingRect(dwThreadId, rguid, prc);
HRESULT hrRet = E_FAIL; if (dwThreadIdSink) { ITfLangBarItemMgr *plbim;
if ((GetThreadUIManager(dwThreadIdSink, &plbim, NULL) == S_OK) && plbim) { hrRet = plbim->GetItemFloatingRect(dwThreadId, rguid, prc); plbim->Release(); } }
return hrRet; }
// --------------------------------------------------------------------------
//
// IsCTFMONBusy
//
// --------------------------------------------------------------------------
const TCHAR c_szLoaderWndClass[] = TEXT("CicLoaderWndClass");
BOOL IsCTFMONBusy() { HWND hwndLoader = NULL; DWORD dwProcessId; DWORD dwThreadId;
hwndLoader = FindWindow(c_szLoaderWndClass, NULL);
if (!hwndLoader) return FALSE;
dwThreadId = GetWindowThreadProcessId(hwndLoader, &dwProcessId);
if (!dwThreadId) return FALSE;
return NotifyTryAgain(dwProcessId, dwThreadId); }
// --------------------------------------------------------------------------
//
// IsInPopupMenuMode
//
// --------------------------------------------------------------------------
BOOL IsInPopupMenuMode() { //
// bug: 399755
//
// when the popup menu is being shown, the OLE RPC and Cicero marshalling
// get blocked the thread. We should postpone plbim->OnUpdateHandler().
//
DWORD dwThreadId = GetCurrentThreadId(); GUITHREADINFO gti; gti.cbSize = sizeof(GUITHREADINFO);
if (!GetGUIThreadInfo(dwThreadId, >i)) return FALSE;
return (gti.flags & GUI_POPUPMENUMODE) ? TRUE : FALSE; }
|