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.

1056 lines
31 KiB

  1. //
  2. // focusnfy.cpp
  3. //
  4. #include "private.h"
  5. #include "globals.h"
  6. #include "thdutil.h"
  7. #include "cicmutex.h"
  8. #include "tim.h"
  9. #include "internat.h"
  10. #include "marshal.h"
  11. #include "catmgr.h"
  12. #include "timlist.h"
  13. #include "ithdmshl.h"
  14. #include "marshal.h"
  15. #include "shlapip.h"
  16. const DWORD TF_LBESF_GLOBAL = 0x0001;
  17. const DWORD TF_LBSMI_FILTERCURRENTTHREAD = 0x0001;
  18. LPVOID SharedAlloc(UINT cbSize,DWORD dwProcessId,HANDLE *pProcessHandle);
  19. VOID SharedFree(LPVOID lpv,HANDLE hProcess);
  20. CStructArray<LBAREVENTSINKLOCAL> *g_rglbes = NULL;
  21. extern CCicMutex g_mutexLBES;
  22. void CallFocusNotifySink(ITfLangBarEventSink *pSink, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fLocalSink, DWORD dwSinkCookie);
  23. // --------------------------------------------------------------------------
  24. //
  25. // FindLBES
  26. //
  27. // --------------------------------------------------------------------------
  28. int FindLBES()
  29. {
  30. int nId = -1;
  31. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  32. {
  33. if (!(GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE))
  34. break;
  35. if (!g_timlist.IsThreadId(GetSharedMemory()->lbes[nId].m_dwThreadId))
  36. {
  37. //
  38. // Bug#354475 - Explorer can call deskband(msutb.dll module)
  39. // directly before loading the ctfmon.exe process. In this case,
  40. // explorer tray window thread didn't recognized by g_timlist.
  41. // Since shared block memory didn't create yet. So checking the
  42. // tray window thread and keep up language bar event sink for
  43. // language deskband support.
  44. //
  45. // Bug#370802
  46. // we can not cache the window handle because explorer could
  47. // crash. And we don't have a window to track "TaskbarCreated"
  48. // message. The shell message is boradcasted by SendNotifyMessage()
  49. // with HWMD_BROADCASTR. So the marshal window can not get it.
  50. //
  51. HWND hwndTray;
  52. DWORD dwThreadIdTray = 0;
  53. hwndTray = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
  54. if (hwndTray)
  55. dwThreadIdTray = GetWindowThreadProcessId(hwndTray, NULL);
  56. if (!dwThreadIdTray ||
  57. dwThreadIdTray != GetSharedMemory()->lbes[nId].m_dwThreadId)
  58. break;
  59. }
  60. }
  61. if (nId == MAX_LPES_NUM)
  62. {
  63. nId = -1;
  64. }
  65. return nId;
  66. }
  67. // --------------------------------------------------------------------------
  68. //
  69. // IntrnalRegisterLangBarNotifySink
  70. //
  71. // --------------------------------------------------------------------------
  72. HRESULT RegisterLangBarNotifySink(ITfLangBarEventSink *pSink, HWND hwnd, DWORD dwFlags, DWORD *pdwCookie)
  73. {
  74. HRESULT hr = E_FAIL;
  75. int nId;
  76. //
  77. // Bugbug#376500 - When CPL runs ctfmon.exe with deskband status, ThreadId
  78. // list doesn't include ctfmon thread, so need to make sure thread id list.
  79. //
  80. SYSTHREAD *psfn = GetSYSTHREAD();
  81. if (psfn)
  82. EnsureTIMList(psfn);
  83. if (!(dwFlags & TF_LBESF_GLOBAL))
  84. {
  85. int nCnt;
  86. LBAREVENTSINKLOCAL *plbes;
  87. //
  88. // Local LangBarEventSink
  89. //
  90. CicEnterCriticalSection(g_csInDllMain);
  91. nCnt = g_rglbes->Count();
  92. if (g_rglbes->Insert(nCnt,1))
  93. {
  94. plbes = g_rglbes->GetPtr(nCnt);
  95. plbes->m_pSink = pSink;
  96. pSink->AddRef();
  97. plbes->lb.m_dwThreadId = GetCurrentThreadId();
  98. plbes->lb.m_dwProcessId = GetCurrentProcessId();
  99. plbes->lb.m_dwCookie = GetSharedMemory()->dwlbesCookie++;
  100. plbes->lb.m_dwLangBarFlags = dwFlags;
  101. *pdwCookie = plbes->lb.m_dwCookie;
  102. plbes->lb.m_hWnd = hwnd;
  103. plbes->lb.m_dwFlags = LBESF_INUSE;
  104. hr = S_OK;
  105. }
  106. CicLeaveCriticalSection(g_csInDllMain);
  107. }
  108. else
  109. {
  110. if (psfn)
  111. {
  112. CCicMutexHelper mutexhlp(&g_mutexLBES);
  113. //
  114. // Global LangBarEventSink
  115. //
  116. if (mutexhlp.Enter())
  117. {
  118. if ((nId = FindLBES()) != -1)
  119. {
  120. GetSharedMemory()->lbes[nId].m_dwThreadId = GetCurrentThreadId();
  121. GetSharedMemory()->lbes[nId].m_dwProcessId = GetCurrentProcessId();
  122. GetSharedMemory()->lbes[nId].m_dwCookie = GetSharedMemory()->dwlbesCookie++;
  123. GetSharedMemory()->lbes[nId].m_dwLangBarFlags = dwFlags;
  124. *pdwCookie = GetSharedMemory()->lbes[nId].m_dwCookie;
  125. GetSharedMemory()->lbes[nId].m_hWnd = hwnd;
  126. GetSharedMemory()->lbes[nId].m_dwFlags = LBESF_INUSE;
  127. psfn->_pLangBarEventSink = pSink;
  128. pSink->AddRef();
  129. psfn->_dwLangBarEventCookie = *pdwCookie;
  130. hr = S_OK;
  131. }
  132. mutexhlp.Leave();
  133. }
  134. }
  135. }
  136. return hr;
  137. }
  138. // --------------------------------------------------------------------------
  139. //
  140. // UnregisterLangBarNotifySink
  141. //
  142. // --------------------------------------------------------------------------
  143. HRESULT UnregisterLangBarNotifySink(DWORD dwCookie)
  144. {
  145. DWORD dwThreadId = GetCurrentThreadId();
  146. DWORD dwProcessId = GetCurrentProcessId();
  147. HRESULT hr = E_FAIL;
  148. int nId;
  149. int nCnt;
  150. SYSTHREAD *psfn = GetSYSTHREAD();
  151. CCicMutexHelper mutexhlp(&g_mutexLBES);
  152. BOOL fUnregistereGlobalSink = FALSE;
  153. //
  154. // Local LangBarEventSink
  155. //
  156. CicEnterCriticalSection(g_csInDllMain);
  157. nCnt = g_rglbes->Count();
  158. for (nId = 0; nId < nCnt; nId++)
  159. {
  160. LBAREVENTSINKLOCAL *plbes;
  161. plbes = g_rglbes->GetPtr(nId);
  162. if ((plbes->lb.m_dwCookie == dwCookie) &&
  163. (plbes->lb.m_dwThreadId == dwThreadId) &&
  164. (plbes->lb.m_dwProcessId == dwProcessId))
  165. {
  166. //
  167. // if the process of msutb.dll is killed, pSink is bogus pointer.
  168. // And this is expected in the unusuall case.
  169. //
  170. _try {
  171. plbes->m_pSink->Release();
  172. }
  173. _except(CicExceptionFilter(GetExceptionInformation())) {
  174. // Assert(0);
  175. }
  176. plbes->m_pSink = NULL;
  177. g_rglbes->Remove(nId, 1);
  178. hr = S_OK;
  179. goto ExitCrit;
  180. }
  181. }
  182. ExitCrit:
  183. CicLeaveCriticalSection(g_csInDllMain);
  184. if (SUCCEEDED(hr))
  185. goto Exit;
  186. if (!psfn)
  187. goto Exit;
  188. //
  189. // Global LangBarEventSink
  190. //
  191. if (mutexhlp.Enter())
  192. {
  193. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  194. {
  195. if ((GetSharedMemory()->lbes[nId].m_dwCookie == dwCookie) &&
  196. (GetSharedMemory()->lbes[nId].m_dwThreadId == dwThreadId) &&
  197. (GetSharedMemory()->lbes[nId].m_dwProcessId == dwProcessId) &&
  198. (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie))
  199. {
  200. //
  201. // if the process of msutb.dll is killed, pSink is bogus pointer.
  202. // And this is expected in the unusuall case.
  203. //
  204. _try {
  205. psfn->_pLangBarEventSink->Release();
  206. }
  207. _except(CicExceptionFilter(GetExceptionInformation())) {
  208. // Assert(0);
  209. }
  210. psfn->_pLangBarEventSink=NULL;
  211. psfn->_dwLangBarEventCookie=NULL;
  212. GetSharedMemory()->lbes[nId].m_dwCookie = 0;
  213. GetSharedMemory()->lbes[nId].m_dwThreadId = 0;
  214. GetSharedMemory()->lbes[nId].m_dwProcessId = 0;
  215. GetSharedMemory()->lbes[nId].m_dwFlags = 0;
  216. fUnregistereGlobalSink = TRUE;
  217. hr = S_OK;
  218. goto ExitMutex;
  219. }
  220. }
  221. ExitMutex:
  222. mutexhlp.Leave();
  223. }
  224. //
  225. // clean up all amrshaling stubs.
  226. //
  227. if (fUnregistereGlobalSink)
  228. FreeMarshaledStubs(psfn);
  229. Exit:
  230. return hr;
  231. }
  232. // -------------------------------------------------------------------------
  233. //
  234. // TLFlagFromMsg
  235. //
  236. // -------------------------------------------------------------------------
  237. DWORD TLFlagFromMsg(UINT uMsg)
  238. {
  239. if (uMsg == g_msgSetFocus)
  240. return LBESF_SETFOCUSINQUEUE;
  241. return 0;
  242. }
  243. // --------------------------------------------------------------------------
  244. //
  245. // MakeSetFocusNotify
  246. //
  247. // --------------------------------------------------------------------------
  248. void MakeSetFocusNotify(UINT uMsg, WPARAM wParam, LPARAM lParam)
  249. {
  250. int nId;
  251. DWORD dwCurThreadId = GetCurrentThreadId();
  252. int nCnt;
  253. DWORD dwPostThread[MAX_LPES_NUM];
  254. CCicMutexHelper mutexhlp(&g_mutexLBES);
  255. DWORD dwMsgMaskFlag = TLFlagFromMsg(uMsg);
  256. if (uMsg == g_msgSetFocus)
  257. {
  258. SYSTHREAD *psfn = GetSYSTHREAD();
  259. TF_InitMlngInfo();
  260. CCategoryMgr::InitGlobal();
  261. EnsureAssemblyList(psfn);
  262. EnsureMarshalWnd();
  263. //EnsureLangBarItemMgr(psfn);
  264. EnsureTIMList(psfn);
  265. //
  266. // I think this is a bogus assert, but it is better to catch the case
  267. // to find another case this happen rather than OLE embedded apps.
  268. //
  269. // Assert(dwCurThreadId == GetSharedMemory()->dwFocusThread);
  270. TraceMsg(TF_GENERAL, "Make SetFocus notify %x", dwCurThreadId);
  271. }
  272. //
  273. // Local LangBarEventSink
  274. //
  275. CicEnterCriticalSection(g_csInDllMain);
  276. nCnt = g_rglbes->Count();
  277. for (nId = 0; nId < nCnt; nId++)
  278. {
  279. LBAREVENTSINKLOCAL *plbes;
  280. DWORD dwThreadId;
  281. plbes = g_rglbes->GetPtr(nId);
  282. Assert(!(plbes->lb.m_dwLangBarFlags & TF_LBESF_GLOBAL));
  283. dwThreadId = plbes->lb.m_dwThreadId;
  284. if (dwThreadId != dwCurThreadId)
  285. continue;
  286. Assert(plbes->lb.m_dwFlags & LBESF_INUSE);
  287. if (!(plbes->lb.m_dwFlags & dwMsgMaskFlag))
  288. {
  289. PostThreadMessage(dwThreadId, uMsg, 0, lParam);
  290. //
  291. // set message mask.
  292. //
  293. plbes->lb.m_dwFlags |= dwMsgMaskFlag;
  294. }
  295. }
  296. CicLeaveCriticalSection(g_csInDllMain);
  297. //
  298. // Global LangBarEventSink
  299. //
  300. BOOL fInDllMain = ISINDLLMAIN();
  301. if (fInDllMain || mutexhlp.Enter())
  302. {
  303. BOOL fPost = FALSE;
  304. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  305. {
  306. DWORD dwFlags = GetSharedMemory()->lbes[nId].m_dwFlags;
  307. // init array.
  308. dwPostThread[nId] = 0;
  309. if (!(dwFlags & LBESF_INUSE))
  310. continue;
  311. DWORD dwTargetProcessId = g_timlist.GetProcessId(GetSharedMemory()->lbes[nId].m_dwThreadId);
  312. if (dwTargetProcessId && (GetSharedMemory()->lbes[nId].m_dwProcessId != dwTargetProcessId))
  313. {
  314. //
  315. // thread on the process is gone without cleaninglbes.
  316. //
  317. Assert(0);
  318. GetSharedMemory()->lbes[nId].m_dwFlags &= ~LBESF_INUSE;
  319. continue;
  320. }
  321. Assert(GetSharedMemory()->lbes[nId].m_dwLangBarFlags & TF_LBESF_GLOBAL);
  322. //
  323. // Check the msg mask bit so there won't be duplicated messages.
  324. //
  325. if (dwFlags & dwMsgMaskFlag)
  326. continue;
  327. //
  328. // avoid from posting exactly same messages into the queue.
  329. //
  330. if ((GetSharedMemory()->lbes[nId].m_lastmsg.uMsg == uMsg) &&
  331. (GetSharedMemory()->lbes[nId].m_lastmsg.wParam == wParam) &&
  332. (GetSharedMemory()->lbes[nId].m_lastmsg.lParam == lParam))
  333. continue;
  334. fPost = TRUE;
  335. dwPostThread[nId] = GetSharedMemory()->lbes[nId].m_dwThreadId;
  336. //
  337. // set message mask.
  338. //
  339. GetSharedMemory()->lbes[nId].m_dwFlags |= dwMsgMaskFlag;
  340. //
  341. // update last posted message.
  342. //
  343. GetSharedMemory()->lbes[nId].m_lastmsg.uMsg = uMsg;
  344. GetSharedMemory()->lbes[nId].m_lastmsg.wParam = wParam;
  345. GetSharedMemory()->lbes[nId].m_lastmsg.lParam = lParam;
  346. }
  347. if (fPost)
  348. {
  349. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  350. {
  351. if (dwPostThread[nId])
  352. PostThreadMessage(dwPostThread[nId], uMsg, wParam, lParam);
  353. }
  354. }
  355. if (!fInDllMain)
  356. mutexhlp.Leave();
  357. }
  358. }
  359. //+---------------------------------------------------------------------------
  360. //
  361. // GetThreadInputIdle()
  362. //
  363. //----------------------------------------------------------------------------
  364. DWORD GetThreadInputIdle(DWORD dwProcessId, DWORD dwThreadId)
  365. {
  366. DWORD dwRet = 0;
  367. HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
  368. FALSE, dwProcessId);
  369. if (hProcess)
  370. {
  371. dwRet = WaitForInputIdle(hProcess, 0);
  372. CloseHandle(hProcess);
  373. }
  374. return dwRet;
  375. }
  376. // --------------------------------------------------------------------------
  377. //
  378. // NotifyTryAgain
  379. //
  380. // --------------------------------------------------------------------------
  381. BOOL NotifyTryAgain(DWORD dwProcessId, DWORD dwThreadId)
  382. {
  383. if (IsOnNT())
  384. {
  385. if (!CicIs16bitTask(dwProcessId, dwThreadId))
  386. {
  387. DWORD dwRet = GetThreadInputIdle(dwProcessId, dwThreadId);
  388. if (dwRet && (dwRet != WAIT_FAILED))
  389. return TRUE;
  390. }
  391. }
  392. else
  393. {
  394. DWORD dwThreadFlags = 0;
  395. if (TF_GetThreadFlags(dwThreadId, &dwThreadFlags, NULL, NULL))
  396. {
  397. if (dwThreadFlags & TLF_NOWAITFORINPUTIDLEONWIN9X)
  398. return FALSE;
  399. }
  400. DWORD dwRet = GetThreadInputIdle(dwProcessId, dwThreadId);
  401. if (dwRet && (dwRet != WAIT_FAILED))
  402. return TRUE;
  403. }
  404. return FALSE;
  405. }
  406. // --------------------------------------------------------------------------
  407. //
  408. // SetFocusNotifyHandler
  409. //
  410. // --------------------------------------------------------------------------
  411. void SetFocusNotifyHandler(UINT uMsg, WPARAM wParam, LPARAM lParam)
  412. {
  413. int nId;
  414. DWORD dwCurThreadId = GetCurrentThreadId();
  415. DWORD dwCurProcessId = GetCurrentProcessId();
  416. int nCnt;
  417. ITfLangBarEventSink *pSinkLocal = NULL;
  418. ITfLangBarEventSink *pSinkGlobal = NULL;
  419. DWORD dwSinkCookie = 0;
  420. DWORD dwMsgMaskFlag = TLFlagFromMsg(uMsg);
  421. MSG msg;
  422. SYSTHREAD *psfn = GetSYSTHREAD();
  423. if (PeekMessage(&msg, NULL, uMsg, uMsg, PM_NOREMOVE | PM_NOYIELD))
  424. {
  425. if ((msg.message == uMsg) &&
  426. (msg.wParam == wParam) &&
  427. (msg.lParam == lParam))
  428. return;
  429. }
  430. if ((uMsg == g_msgThreadTerminate) && psfn)
  431. {
  432. FreeMarshaledStubsForThread(psfn, (DWORD)lParam);
  433. }
  434. //
  435. // Local LangBarEventSink
  436. //
  437. CicEnterCriticalSection(g_csInDllMain);
  438. nCnt = g_rglbes->Count();
  439. for (nId = 0; nId < nCnt; nId++)
  440. {
  441. LBAREVENTSINKLOCAL *plbes = g_rglbes->GetPtr(nId);
  442. Assert(!(plbes->lb.m_dwLangBarFlags & TF_LBESF_GLOBAL));
  443. if (plbes->lb.m_dwThreadId == dwCurThreadId)
  444. {
  445. pSinkLocal = plbes->m_pSink;
  446. dwSinkCookie = plbes->lb.m_dwCookie;
  447. //
  448. // clear message mask.
  449. //
  450. plbes->lb.m_dwFlags &= ~dwMsgMaskFlag;
  451. break;
  452. }
  453. }
  454. CicLeaveCriticalSection(g_csInDllMain);
  455. if (psfn)
  456. {
  457. CCicMutexHelper mutexhlp(&g_mutexLBES);
  458. //
  459. // Global LangBarEventSink
  460. //
  461. if (mutexhlp.Enter())
  462. {
  463. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  464. {
  465. if ((GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE) &&
  466. (GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) &&
  467. (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) &&
  468. (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie))
  469. {
  470. pSinkGlobal = psfn->_pLangBarEventSink;
  471. dwSinkCookie = GetSharedMemory()->lbes[nId].m_dwCookie;
  472. //
  473. // clear message mask.
  474. //
  475. GetSharedMemory()->lbes[nId].m_dwFlags &= ~dwMsgMaskFlag;
  476. //
  477. // clear last posted message.
  478. //
  479. GetSharedMemory()->lbes[nId].m_lastmsg.uMsg = 0;
  480. GetSharedMemory()->lbes[nId].m_lastmsg.wParam = 0;
  481. GetSharedMemory()->lbes[nId].m_lastmsg.lParam = 0;
  482. break;
  483. }
  484. }
  485. mutexhlp.Leave();
  486. }
  487. }
  488. if (pSinkLocal)
  489. CallFocusNotifySink(pSinkLocal, uMsg, wParam, lParam, TRUE, dwSinkCookie);
  490. if (pSinkGlobal)
  491. CallFocusNotifySink(pSinkGlobal, uMsg, wParam, lParam, FALSE, dwSinkCookie);
  492. }
  493. // --------------------------------------------------------------------------
  494. //
  495. // CallFocusNotifySink
  496. //
  497. // --------------------------------------------------------------------------
  498. void CallFocusNotifySink(ITfLangBarEventSink *pSink, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fLocalSink, DWORD dwSinkCookie)
  499. {
  500. DWORD dwCurThreadId = GetCurrentThreadId();
  501. DWORD dwCurProcessId = GetCurrentProcessId();
  502. SYSTHREAD *psfn;
  503. if (uMsg == g_msgSetFocus)
  504. {
  505. DWORD dwActiveThreadId;
  506. dwActiveThreadId = GetSharedMemory()->dwFocusThread;
  507. if (g_timlist.IsThreadId(dwActiveThreadId))
  508. {
  509. DWORD dwProcessId = GetSharedMemory()->dwFocusProcess;
  510. if (dwProcessId != dwCurProcessId)
  511. {
  512. #if 0
  513. if (NotifyTryAgain(dwProcessId, dwActiveThreadId))
  514. {
  515. HWND hwndMarshal;
  516. if (hwndMarshal = EnsureMarshalWnd())
  517. {
  518. KillTimer(hwndMarshal, MARSHALWND_TIMER_WAITFORINPUTIDLEFORSETFOCUS);
  519. SetTimer(hwndMarshal,
  520. MARSHALWND_TIMER_WAITFORINPUTIDLEFORSETFOCUS,
  521. 100, NULL);
  522. }
  523. goto Exit;
  524. }
  525. #endif
  526. }
  527. if ((!fLocalSink || dwActiveThreadId == dwCurThreadId) &&
  528. (psfn = GetSYSTHREAD()))
  529. {
  530. psfn->fInmsgSetFocus = TRUE;
  531. _try {
  532. pSink->OnSetFocus(dwActiveThreadId);
  533. }
  534. _except(CicExceptionFilter(GetExceptionInformation())) {
  535. //
  536. // On NT5, if we get an exception in MsgHookProc,
  537. // it is unhooked by system. To keep the hook,
  538. // we handle any excpeiton here.
  539. //
  540. Assert(0);
  541. //
  542. // Then we enregister the Sink. Don't use it any more.
  543. //
  544. // UnregisterLangBarNotifySink(dwSinkCookie);
  545. }
  546. psfn->fInmsgSetFocus = FALSE;
  547. }
  548. }
  549. }
  550. else if (uMsg == g_msgThreadTerminate)
  551. {
  552. if (!fLocalSink && // skip this call for local sinks, they should already be unadvised
  553. (psfn = GetSYSTHREAD()))
  554. {
  555. psfn->fInmsgThreadTerminate = TRUE;
  556. _try {
  557. pSink->OnThreadTerminate((DWORD)lParam);
  558. }
  559. _except(CicExceptionFilter(GetExceptionInformation())) {
  560. //
  561. // On NT5, if we get an exception in MsgHookProc,
  562. // it is unhooked by system. To keep the hook,
  563. // we handle any excpeiton here.
  564. //
  565. Assert(0);
  566. //
  567. // Then we enregister the Sink. Don't use it any more.
  568. //
  569. // UnregisterLangBarNotifySink(dwSinkCookie);
  570. }
  571. psfn->fInmsgThreadTerminate = FALSE;
  572. }
  573. }
  574. else if (uMsg == g_msgThreadItemChange)
  575. {
  576. if (g_timlist.IsThreadId((DWORD)lParam) &&
  577. (psfn = GetSYSTHREAD()))
  578. {
  579. DWORD dwProcessId;
  580. if (psfn->fInmsgThreadItemChange)
  581. goto Exit;
  582. if ((DWORD)lParam == GetSharedMemory()->dwFocusThread)
  583. dwProcessId = GetSharedMemory()->dwFocusProcess;
  584. else
  585. dwProcessId = g_timlist.GetProcessId((DWORD)lParam);
  586. #if 0
  587. if (dwProcessId != dwCurProcessId)
  588. {
  589. if (NotifyTryAgain(dwProcessId, (DWORD)lParam))
  590. {
  591. PostThreadMessage(dwCurThreadId,uMsg, 0, lParam);
  592. goto Exit;
  593. }
  594. }
  595. #endif
  596. psfn->fInmsgThreadItemChange = TRUE;
  597. _try {
  598. pSink->OnThreadItemChange((DWORD)lParam);
  599. }
  600. _except(CicExceptionFilter(GetExceptionInformation())) {
  601. //
  602. // On NT5, if we get an exception in MsgHookProc,
  603. // it is unhooked by system. To keep the hook,
  604. // we handle any excpeiton here.
  605. //
  606. Assert(0);
  607. //
  608. // Then we enregister the Sink. Don't use it any more.
  609. //
  610. // UnregisterLangBarNotifySink(dwSinkCookie);
  611. }
  612. psfn->fInmsgThreadItemChange = FALSE;
  613. }
  614. }
  615. else if (uMsg == g_msgShowFloating)
  616. {
  617. _try {
  618. pSink->ShowFloating((DWORD)lParam);
  619. }
  620. _except(CicExceptionFilter(GetExceptionInformation())) {
  621. //
  622. // On NT5, if we get an exception in MsgHookProc,
  623. // it is unhooked by system. To keep the hook,
  624. // we handle any excpeiton here.
  625. //
  626. Assert(0);
  627. //
  628. // Then we enregister the Sink. Don't use it any more.
  629. //
  630. // UnregisterLangBarNotifySink(dwSinkCookie);
  631. }
  632. }
  633. else if (uMsg == g_msgLBUpdate)
  634. {
  635. _try {
  636. ITfLangBarEventSink_P *pSinkP;
  637. if (SUCCEEDED(pSink->QueryInterface(IID_ITfLangBarEventSink_P, (void **)&pSinkP)) && pSinkP)
  638. {
  639. pSinkP->OnLangBarUpdate((DWORD)wParam, lParam);
  640. pSinkP->Release();
  641. }
  642. }
  643. _except(CicExceptionFilter(GetExceptionInformation())) {
  644. //
  645. // On NT5, if we get an exception in MsgHookProc,
  646. // it is unhooked by system. To keep the hook,
  647. // we handle any excpeiton here.
  648. //
  649. Assert(0);
  650. //
  651. // Then we enregister the Sink. Don't use it any more.
  652. //
  653. // UnregisterLangBarNotifySink(dwSinkCookie);
  654. }
  655. }
  656. Exit:
  657. return;
  658. }
  659. // --------------------------------------------------------------------------
  660. //
  661. // SetModalLBarSink
  662. //
  663. // --------------------------------------------------------------------------
  664. void SetModalLBarSink(DWORD dwTargetThreadId, BOOL fSet, DWORD dwFlags)
  665. {
  666. int nId;
  667. CCicMutexHelper mutexhlp(&g_mutexLBES);
  668. Assert(!(0xffff0000 & dwFlags));
  669. //
  670. // Global LangBarEventSink
  671. //
  672. if (mutexhlp.Enter())
  673. {
  674. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  675. {
  676. if (GetSharedMemory()->lbes[nId].m_dwThreadId == GetCurrentThreadId())
  677. {
  678. LPARAM lParam = (LPARAM)((nId << 16) + (dwFlags & 0xffff));
  679. PostThreadMessage(dwTargetThreadId,
  680. g_msgPrivate,
  681. fSet ? TFPRIV_SETMODALLBAR : TFPRIV_RELEASEMODALLBAR,
  682. (LPARAM)lParam);
  683. break;
  684. }
  685. }
  686. mutexhlp.Leave();
  687. }
  688. }
  689. // --------------------------------------------------------------------------
  690. //
  691. // SetModalLBarId
  692. //
  693. // --------------------------------------------------------------------------
  694. void SetModalLBarId(int nId, DWORD dwFlags)
  695. {
  696. SYSTHREAD *psfn;
  697. if (psfn = GetSYSTHREAD())
  698. {
  699. psfn->nModalLangBarId = nId;
  700. psfn->dwModalLangBarFlags = dwFlags;
  701. }
  702. }
  703. // --------------------------------------------------------------------------
  704. //
  705. // HandlModalLBar
  706. //
  707. // --------------------------------------------------------------------------
  708. BOOL HandleModalLBar(UINT uMsg, WPARAM wParam, LPARAM lParam)
  709. {
  710. SYSTHREAD *psfn = GetSYSTHREAD();
  711. DWORD dwThreadId = 0;
  712. if (psfn == NULL)
  713. return FALSE;
  714. if (psfn->nModalLangBarId == -1)
  715. return FALSE;
  716. if ((((uMsg >= WM_NCMOUSEMOVE) && (uMsg <= WM_NCMBUTTONDBLCLK)) ||
  717. ((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST))) &&
  718. (psfn->dwModalLangBarFlags & TF_LBSMI_FILTERCURRENTTHREAD))
  719. {
  720. POINT pt = {LOWORD((DWORD)lParam), HIWORD((DWORD)lParam)};
  721. HWND hwnd = WindowFromPoint(pt);
  722. if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd, NULL))
  723. return FALSE;
  724. }
  725. CCicMutexHelper mutexhlp(&g_mutexLBES);
  726. //
  727. // Global LangBarEventSink
  728. //
  729. if (mutexhlp.Enter())
  730. {
  731. if (GetSharedMemory()->lbes[psfn->nModalLangBarId].m_dwFlags & LBESF_INUSE)
  732. dwThreadId = GetSharedMemory()->lbes[psfn->nModalLangBarId].m_dwThreadId;
  733. mutexhlp.Leave();
  734. }
  735. if (!dwThreadId)
  736. {
  737. psfn->nModalLangBarId = -1;
  738. return FALSE;
  739. }
  740. Assert(g_timlist.IsThreadId(dwThreadId));
  741. //
  742. // Here, we will lost HIWORD(uMsg) and HIWORD(wParam).
  743. //
  744. // if we need scan code for WM_KEYxxx, message. we need to put it
  745. // HIBYTE(LOWORD(wParam))
  746. //
  747. PostThreadMessage(dwThreadId,
  748. g_msgLBarModal,
  749. (WPARAM)((LOWORD(uMsg) << 16) | LOWORD(wParam)),
  750. lParam);
  751. return TRUE;
  752. }
  753. // --------------------------------------------------------------------------
  754. //
  755. // DispatchModalLBar
  756. //
  757. // --------------------------------------------------------------------------
  758. BOOL DispatchModalLBar(WPARAM wParam, LPARAM lParam)
  759. {
  760. int nId;
  761. SYSTHREAD *psfn = GetSYSTHREAD();
  762. if (!psfn)
  763. return FALSE;
  764. DWORD dwCurThreadId = GetCurrentThreadId();
  765. DWORD dwCurProcessId = GetCurrentProcessId();
  766. ITfLangBarEventSink *pSink = NULL;
  767. //
  768. // we don't need to check Local LangBarEventSink
  769. //
  770. CCicMutexHelper mutexhlp(&g_mutexLBES);
  771. //
  772. // Global LangBarEventSink
  773. //
  774. if (mutexhlp.Enter())
  775. {
  776. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  777. {
  778. if ((GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE) &&
  779. (GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) &&
  780. (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) &&
  781. (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie))
  782. {
  783. pSink = psfn->_pLangBarEventSink;
  784. break;
  785. }
  786. }
  787. mutexhlp.Leave();
  788. }
  789. if (pSink)
  790. {
  791. //
  792. // restore uMsg and wParam from posted wParam.
  793. //
  794. _try {
  795. pSink->OnModalInput(GetSharedMemory()->dwFocusThread,
  796. (UINT)HIWORD(wParam),
  797. (WPARAM)LOWORD(wParam),
  798. lParam);
  799. }
  800. _except(CicExceptionFilter(GetExceptionInformation())) {
  801. Assert(0);
  802. }
  803. }
  804. return TRUE;
  805. }
  806. // --------------------------------------------------------------------------
  807. //
  808. // ThreadGetItemFloatingRect
  809. //
  810. // --------------------------------------------------------------------------
  811. HRESULT ThreadGetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
  812. {
  813. SYSTHREAD *psfn = GetSYSTHREAD();
  814. if (!psfn)
  815. return E_FAIL;
  816. DWORD dwCurThreadId = GetCurrentThreadId();
  817. DWORD dwCurProcessId = GetCurrentProcessId();
  818. ITfLangBarEventSink *pSink = NULL;
  819. DWORD dwThreadIdSink = 0;
  820. int nId;
  821. CCicMutexHelper mutexhlp(&g_mutexLBES);
  822. //
  823. // Global LangBarEventSink
  824. //
  825. if (mutexhlp.Enter())
  826. {
  827. for (nId = 0; nId < MAX_LPES_NUM; nId++)
  828. {
  829. if (GetSharedMemory()->lbes[nId].m_dwFlags & LBESF_INUSE)
  830. {
  831. if (!dwThreadIdSink)
  832. dwThreadIdSink = GetSharedMemory()->lbes[nId].m_dwThreadId;
  833. if ((GetSharedMemory()->lbes[nId].m_dwThreadId == dwCurThreadId) &&
  834. (GetSharedMemory()->lbes[nId].m_dwProcessId == dwCurProcessId) &&
  835. (GetSharedMemory()->lbes[nId].m_dwCookie == psfn->_dwLangBarEventCookie))
  836. {
  837. pSink = psfn->_pLangBarEventSink;
  838. break;
  839. }
  840. }
  841. }
  842. mutexhlp.Leave();
  843. }
  844. if (pSink)
  845. return pSink->GetItemFloatingRect(dwThreadId, rguid, prc);
  846. HRESULT hrRet = E_FAIL;
  847. if (dwThreadIdSink)
  848. {
  849. ITfLangBarItemMgr *plbim;
  850. if ((GetThreadUIManager(dwThreadIdSink, &plbim, NULL) == S_OK) && plbim)
  851. {
  852. hrRet = plbim->GetItemFloatingRect(dwThreadId, rguid, prc);
  853. plbim->Release();
  854. }
  855. }
  856. return hrRet;
  857. }
  858. // --------------------------------------------------------------------------
  859. //
  860. // IsCTFMONBusy
  861. //
  862. // --------------------------------------------------------------------------
  863. const TCHAR c_szLoaderWndClass[] = TEXT("CicLoaderWndClass");
  864. BOOL IsCTFMONBusy()
  865. {
  866. HWND hwndLoader = NULL;
  867. DWORD dwProcessId;
  868. DWORD dwThreadId;
  869. hwndLoader = FindWindow(c_szLoaderWndClass, NULL);
  870. if (!hwndLoader)
  871. return FALSE;
  872. dwThreadId = GetWindowThreadProcessId(hwndLoader, &dwProcessId);
  873. if (!dwThreadId)
  874. return FALSE;
  875. return NotifyTryAgain(dwProcessId, dwThreadId);
  876. }
  877. // --------------------------------------------------------------------------
  878. //
  879. // IsInPopupMenuMode
  880. //
  881. // --------------------------------------------------------------------------
  882. BOOL IsInPopupMenuMode()
  883. {
  884. //
  885. // bug: 399755
  886. //
  887. // when the popup menu is being shown, the OLE RPC and Cicero marshalling
  888. // get blocked the thread. We should postpone plbim->OnUpdateHandler().
  889. //
  890. DWORD dwThreadId = GetCurrentThreadId();
  891. GUITHREADINFO gti;
  892. gti.cbSize = sizeof(GUITHREADINFO);
  893. if (!GetGUIThreadInfo(dwThreadId, &gti))
  894. return FALSE;
  895. return (gti.flags & GUI_POPUPMENUMODE) ? TRUE : FALSE;
  896. }