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

  1. //
  2. // nuimgr.cpp
  3. //
  4. #include "private.h"
  5. #include "tim.h"
  6. #include "nuimgr.h"
  7. #include "nuictrl.h"
  8. #include "marshal.h"
  9. #include "timlist.h"
  10. #include "lbaddin.h"
  11. #include "hotkey.h"
  12. DBG_ID_INSTANCE(CLBarItemSink);
  13. DBG_ID_INSTANCE(CLBarItemSinkProxy);
  14. DBG_ID_INSTANCE(CLangBarItemMgr);
  15. DBG_ID_INSTANCE(CEnumLBItem);
  16. //////////////////////////////////////////////////////////////////////////////
  17. //
  18. // marshalling misc func
  19. //
  20. //////////////////////////////////////////////////////////////////////////////
  21. //+---------------------------------------------------------------------------
  22. //
  23. // FreeStubForThis
  24. //
  25. // this function clean up all marshaling stubs for the LangBarItem.
  26. //
  27. //+---------------------------------------------------------------------------
  28. void FreeMarshaledStubOfItem(SYSTHREAD *psfn, REFGUID rguid)
  29. {
  30. ITfLangBarItem *pItem;
  31. if (!psfn->prgStub)
  32. return;
  33. //
  34. // #489905
  35. //
  36. // we can not call sink anymore after DLL_PROCESS_DETACH.
  37. //
  38. if (DllShutdownInProgress())
  39. return;
  40. int nCnt = psfn->prgStub->Count();
  41. int i = 0;
  42. for (i = 0; i < nCnt; i++)
  43. {
  44. TryThisIdAgain:
  45. CStub *pStub = psfn->prgStub->Get(i);
  46. HRESULT hr;
  47. TF_LANGBARITEMINFO info;
  48. //
  49. // Win98-J and Satori cause exception at the sutdown of notepad.
  50. // we need to make sure this exception handler is not hiding any
  51. // potential problems.
  52. //
  53. _try {
  54. if (FAILED(pStub->_punk->QueryInterface(IID_ITfLangBarItem, (void **)&pItem)))
  55. continue;
  56. }
  57. _except (1) {
  58. continue;
  59. }
  60. hr = pItem->GetInfo(&info);
  61. pItem->Release();
  62. if (SUCCEEDED(hr) && IsEqualGUID(info.guidItem, rguid))
  63. {
  64. pStub->_fNoRemoveInDtor = TRUE;
  65. psfn->prgStub->Remove(i, 1);
  66. delete pStub;
  67. nCnt--;
  68. if (i < nCnt)
  69. goto TryThisIdAgain;
  70. return;
  71. }
  72. }
  73. }
  74. //////////////////////////////////////////////////////////////////////////////
  75. //
  76. // CLangBarItemMgr
  77. //
  78. //////////////////////////////////////////////////////////////////////////////
  79. //+---------------------------------------------------------------------------
  80. //
  81. // ctor
  82. //
  83. //----------------------------------------------------------------------------
  84. CLangBarItemMgr::CLangBarItemMgr(SYSTHREAD *psfn) : CSysThreadRef(psfn)
  85. {
  86. Dbg_MemSetThisNameID(TEXT("CLangBarItemMgr"));
  87. Assert(_GetThis() == NULL);
  88. _SetThis(this);
  89. _dwCurCookie = 0;
  90. _ulInAssemblyChange = 0;
  91. _fHandleOnUpdate = TRUE;
  92. EnsureMarshalWnd();
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // dtor
  97. //
  98. //----------------------------------------------------------------------------
  99. CLangBarItemMgr::~CLangBarItemMgr()
  100. {
  101. g_timlist.ClearFlags(_psfn->dwThreadId, TLF_LBIMGR);
  102. _RemoveSystemItems(_psfn);
  103. CleanUp();
  104. _SetThis(NULL);
  105. }
  106. //+---------------------------------------------------------------------------
  107. //
  108. // IUnknown
  109. //
  110. //----------------------------------------------------------------------------
  111. STDAPI CLangBarItemMgr::QueryInterface(REFIID riid, void **ppvObj)
  112. {
  113. if (ppvObj == NULL)
  114. return E_INVALIDARG;
  115. *ppvObj = NULL;
  116. if (IsEqualIID(riid, IID_ITfLangBarItemMgr) ||
  117. IsEqualIID(riid, IID_IUnknown))
  118. {
  119. *ppvObj = SAFECAST(this, ITfLangBarItemMgr *);
  120. }
  121. if (*ppvObj)
  122. {
  123. AddRef();
  124. return S_OK;
  125. }
  126. return E_NOINTERFACE;
  127. }
  128. STDAPI_(ULONG) CLangBarItemMgr::AddRef()
  129. {
  130. //
  131. // we don't have ref count.
  132. // Keep this class in psfn and delete at the end of thread.
  133. //
  134. return 2;
  135. }
  136. STDAPI_(ULONG) CLangBarItemMgr::Release()
  137. {
  138. //
  139. // we don't have ref count.
  140. // Keep this class in psfn and delete at the end of thread.
  141. //
  142. return 1;
  143. }
  144. //+---------------------------------------------------------------------------
  145. //
  146. // _RemoveSystemItems
  147. //
  148. //----------------------------------------------------------------------------
  149. void CLangBarItemMgr::_RemoveSystemItems(SYSTHREAD *psfn)
  150. {
  151. int i;
  152. CLBarItemDeviceType *plbiDT;
  153. DWORD dwThreadId = GetCurrentThreadId();
  154. if (_plbiCtrl != NULL)
  155. {
  156. RemoveItem(*_plbiCtrl->GetGuidItem());
  157. if (_plbiCtrl->Release() > 0)
  158. {
  159. if (psfn && (psfn->dwThreadId == dwThreadId))
  160. {
  161. // Clean up a pointer that is marshalled to UTB.
  162. delete _plbiCtrl;
  163. }
  164. }
  165. _plbiCtrl = NULL;
  166. }
  167. if (_plbiReconv != NULL)
  168. {
  169. RemoveItem(*_plbiReconv->GetGuidItem());
  170. if (_plbiReconv->Release() > 0)
  171. {
  172. if (psfn && (psfn->dwThreadId == dwThreadId))
  173. {
  174. // Clean up a pointer that is marshalled to UTB.
  175. delete _plbiReconv;
  176. }
  177. }
  178. _plbiReconv = NULL;
  179. }
  180. if (_plbiWin32IME != NULL)
  181. {
  182. RemoveItem(*_plbiWin32IME->GetGuidItem());
  183. if (_plbiWin32IME->Release() > 0)
  184. {
  185. if (psfn && (psfn->dwThreadId == dwThreadId))
  186. {
  187. // Clean up a pointer that is marshalled to UTB.
  188. delete _plbiWin32IME;
  189. }
  190. }
  191. _plbiWin32IME = NULL;
  192. }
  193. if (_plbiHelp != NULL)
  194. {
  195. RemoveItem(*_plbiHelp->GetGuidItem());
  196. if (_plbiHelp->Release() > 0)
  197. {
  198. if (psfn && (psfn->dwThreadId == dwThreadId))
  199. {
  200. // Clean up a pointer that is marshalled to UTB.
  201. delete _plbiHelp;
  202. }
  203. }
  204. _plbiHelp = NULL;
  205. }
  206. for (i = 0; i < _rglbiDeviceType.Count(); i++)
  207. {
  208. plbiDT = _rglbiDeviceType.Get(i);
  209. if (plbiDT)
  210. {
  211. RemoveItem(*plbiDT->GetGuidItem());
  212. if (plbiDT->Release() > 0)
  213. {
  214. if (psfn && (psfn->dwThreadId == dwThreadId))
  215. {
  216. // Clean up a pointer that is marshalled to UTB.
  217. delete plbiDT;
  218. }
  219. }
  220. }
  221. }
  222. _rglbiDeviceType.Clear();
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // CreateInstance
  227. //
  228. //----------------------------------------------------------------------------
  229. /* static */
  230. HRESULT CLangBarItemMgr::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
  231. {
  232. CLangBarItemMgr *plbim;
  233. HRESULT hr;
  234. if (ppvObj == NULL)
  235. return E_INVALIDARG;
  236. *ppvObj = NULL;
  237. if (pUnkOuter != NULL)
  238. return CLASS_E_NOAGGREGATION;
  239. if (plbim = _GetThis())
  240. {
  241. return plbim->QueryInterface(riid, ppvObj);
  242. }
  243. SYSTHREAD *psfn = GetSYSTHREAD();
  244. if (!psfn)
  245. return E_OUTOFMEMORY;
  246. if ((plbim = new CLangBarItemMgr(psfn)) == NULL)
  247. return E_OUTOFMEMORY;
  248. if (!plbim->_Init())
  249. {
  250. plbim->Release();
  251. return E_FAIL;
  252. }
  253. hr = plbim->QueryInterface(riid, ppvObj);
  254. plbim->Release();
  255. #ifdef WINLOGON_LANGBAR
  256. ExecuteLoader();
  257. #endif
  258. return hr;
  259. }
  260. //+---------------------------------------------------------------------------
  261. //
  262. // FindDeviceTypeItem
  263. //
  264. //----------------------------------------------------------------------------
  265. CLBarItemDeviceType *CLangBarItemMgr::FindDeviceTypeItem(REFGUID guid)
  266. {
  267. int i;
  268. CLBarItemDeviceType *plbiDT;
  269. for (i = 0; i < _rglbiDeviceType.Count(); i++)
  270. {
  271. plbiDT = _rglbiDeviceType.Get(i);
  272. if (plbiDT)
  273. {
  274. if (IsEqualGUID(*plbiDT->GetDeviceTypeGUID(), guid))
  275. {
  276. return plbiDT;
  277. }
  278. }
  279. }
  280. return NULL;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // _Init
  285. //
  286. //----------------------------------------------------------------------------
  287. BOOL CLangBarItemMgr::_Init()
  288. {
  289. CLBarItemDeviceType **pplbiDT;
  290. GUID guid;
  291. //
  292. // set TLF_LBIMGR flag for this thread of timlist.
  293. //
  294. if (EnsureTIMList(_psfn))
  295. {
  296. g_timlist.SetFlags(_psfn->dwThreadId, TLF_LBIMGR);
  297. InitLangChangeHotKey();
  298. }
  299. // init the system default ctls
  300. if (!_plbiCtrl && (_plbiCtrl = new CLBarItemCtrl(_psfn)) == NULL)
  301. return FALSE;
  302. AddItem(_plbiCtrl);
  303. //
  304. // I want to hide a help button on Winlogon.
  305. // But IMJP8 causes av, if we don't have Help button...
  306. //
  307. // if (!IsInWinLogOnDesktop())
  308. {
  309. if (!_plbiHelp && (_plbiHelp = new CLBarItemHelp(_psfn)) != NULL)
  310. {
  311. AddItem(_plbiHelp);
  312. }
  313. }
  314. if (CThreadInputMgr::_GetThis())
  315. {
  316. if (!_plbiReconv && (_plbiReconv = new CLBarItemReconv(_psfn)))
  317. {
  318. AddItem(_plbiReconv);
  319. _plbiReconv->ShowOrHide(FALSE);
  320. }
  321. IEnumGUID *pEnum;
  322. if (SUCCEEDED(CCategoryMgr::s_EnumItemsInCategory(
  323. GUID_TFCAT_CATEGORY_OF_TIP,
  324. &pEnum)))
  325. {
  326. while (pEnum->Next(1, &guid, NULL) == S_OK)
  327. {
  328. if (FindDeviceTypeItem(guid))
  329. continue;
  330. pplbiDT = _rglbiDeviceType.Append(1);
  331. if (pplbiDT)
  332. {
  333. *pplbiDT = new CLBarItemDeviceType(_psfn, guid);
  334. if (*pplbiDT)
  335. {
  336. (*pplbiDT)->Init();
  337. AddItem(*pplbiDT);
  338. }
  339. else
  340. {
  341. int nCnt = _rglbiDeviceType.Count();
  342. if (nCnt)
  343. _rglbiDeviceType.Remove(nCnt - 1, 1);
  344. }
  345. }
  346. }
  347. pEnum->Release();
  348. }
  349. }
  350. else
  351. {
  352. if (!FindDeviceTypeItem(GUID_TFCAT_TIP_KEYBOARD))
  353. {
  354. pplbiDT = _rglbiDeviceType.Append(1);
  355. if (pplbiDT)
  356. {
  357. *pplbiDT = new CLBarItemDeviceType(_psfn, GUID_TFCAT_TIP_KEYBOARD);
  358. if (*pplbiDT)
  359. {
  360. (*pplbiDT)->Init();
  361. AddItem(*pplbiDT);
  362. }
  363. else
  364. {
  365. int nCnt = _rglbiDeviceType.Count();
  366. if (nCnt)
  367. _rglbiDeviceType.Remove(nCnt - 1, 1);
  368. }
  369. }
  370. }
  371. }
  372. if (_plbiCtrl)
  373. {
  374. _plbiCtrl->_UpdateLangIcon(NULL, FALSE);
  375. }
  376. UpdateLangBarAddIns();
  377. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  378. return TRUE;
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // CleanUp
  383. //
  384. //----------------------------------------------------------------------------
  385. void CLangBarItemMgr::CleanUp()
  386. {
  387. //
  388. // we can not call COM in PROCESS_DETACH. we just make sure
  389. // if someone forget to call UnRegister.
  390. //
  391. #if 1
  392. // Assert(!_rglbiProxy.Count());
  393. #else
  394. int i;
  395. int nCnt;
  396. nCnt = _rglbiProxy.Count();
  397. for (i = 0; i < nCnt; i++)
  398. {
  399. CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
  400. pProxy->Clear();
  401. pProxy->Release();
  402. }
  403. #endif
  404. _rglbiProxy.Clear();
  405. int i;
  406. int nCnt = _rgSink.Count();
  407. for (i = 0; i < nCnt ; i++)
  408. {
  409. CLBarItemSink *pSink = _rgSink.Get(i);
  410. Assert(pSink);
  411. TraceMsg(TF_GENERAL, "NuiMgr clean up ItemSink - 0x%x08", (UINT_PTR)pSink);
  412. //
  413. // Issue: This is a pointer that is marshalled from UTB.
  414. // If this is called in DllMain(THREAD_DETACH).
  415. // calling Release() cause dead lock....
  416. //
  417. pSink->_pItemSink->Release();
  418. pSink->_pItemSink = NULL;
  419. delete pSink;
  420. }
  421. _rgSink.Clear();
  422. }
  423. //+---------------------------------------------------------------------------
  424. //
  425. // AddItem
  426. //
  427. //----------------------------------------------------------------------------
  428. STDAPI CLangBarItemMgr::AddItem(ITfLangBarItem *pItem)
  429. {
  430. ITfSource *pSource = NULL;
  431. HRESULT hr = E_FAIL;
  432. CLBarItemSinkProxy *pProxy;
  433. TF_LANGBARITEMINFO info;
  434. if (pItem == NULL)
  435. return E_INVALIDARG;
  436. if (FAILED(pItem->QueryInterface(IID_ITfSource, (void **)&pSource)))
  437. {
  438. goto Exit;
  439. }
  440. if (SUCCEEDED(pItem->GetInfo(&info)))
  441. {
  442. int i;
  443. int nCnt = _rglbiProxy.Count();
  444. for (i = 0; i < nCnt; i++)
  445. {
  446. pProxy = _rglbiProxy.Get(i);
  447. if (IsEqualGUID(pProxy->_info.guidItem, info.guidItem))
  448. {
  449. hr = E_INVALIDARG;
  450. goto Exit;
  451. }
  452. }
  453. }
  454. else
  455. {
  456. goto Exit;
  457. }
  458. pProxy = new CLBarItemSinkProxy();
  459. if (!pProxy)
  460. {
  461. hr = E_OUTOFMEMORY;
  462. goto Exit;
  463. }
  464. if (!pProxy->Init(this, pItem, &info))
  465. {
  466. goto Exit;
  467. }
  468. if (FAILED(pSource->AdviseSink(IID_ITfLangBarItemSink,
  469. pProxy, &pProxy->_dwCookie)))
  470. {
  471. pProxy->Clear();
  472. pProxy->Release();
  473. }
  474. else
  475. {
  476. int nCnt = _rglbiProxy.Count();
  477. if (!_rglbiProxy.Insert(nCnt, 1))
  478. {
  479. pSource->UnadviseSink(pProxy->_dwCookie);
  480. pProxy->Clear();
  481. pProxy->Release();
  482. hr = E_OUTOFMEMORY;
  483. goto Exit;
  484. }
  485. _rglbiProxy.Set(nCnt, pProxy);
  486. if (!_ulInAssemblyChange)
  487. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  488. _fItemChanged = TRUE;
  489. hr = S_OK;
  490. }
  491. Exit:
  492. SafeRelease(pSource);
  493. return hr;
  494. }
  495. //+---------------------------------------------------------------------------
  496. //
  497. // RemoveItem
  498. //
  499. //----------------------------------------------------------------------------
  500. STDAPI CLangBarItemMgr::RemoveItem(ITfLangBarItem *pItem)
  501. {
  502. TF_LANGBARITEMINFO info;
  503. if (!pItem)
  504. return E_INVALIDARG;
  505. if (FAILED(pItem->GetInfo(&info)))
  506. return E_FAIL;
  507. return RemoveItem(info.guidItem);
  508. }
  509. //+---------------------------------------------------------------------------
  510. //
  511. // RemoveItem
  512. //
  513. //----------------------------------------------------------------------------
  514. HRESULT CLangBarItemMgr::RemoveItem(REFGUID rguid)
  515. {
  516. int nCnt;
  517. int i;
  518. nCnt = _rglbiProxy.Count();
  519. for (i = 0; i < nCnt; i++)
  520. {
  521. CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
  522. if (IsEqualGUID(pProxy->_info.guidItem, rguid))
  523. {
  524. ITfSource *pSource;
  525. if (SUCCEEDED(pProxy->_plbi->QueryInterface(IID_ITfSource,
  526. (void **)&pSource)))
  527. {
  528. pSource->UnadviseSink(pProxy->_dwCookie);
  529. pSource->Release();
  530. }
  531. _rglbiProxy.Remove(i, 1);
  532. pProxy->Clear();
  533. pProxy->Release();
  534. if (!_ulInAssemblyChange)
  535. {
  536. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  537. }
  538. SYSTHREAD *psfn = FindSYSTHREAD();
  539. if (psfn && (psfn->dwThreadId == _psfn->dwThreadId))
  540. FreeMarshaledStubOfItem(psfn, rguid);
  541. _fItemChanged = TRUE;
  542. break;
  543. }
  544. }
  545. return S_OK;
  546. }
  547. //+---------------------------------------------------------------------------
  548. //
  549. // RegisterItemSink
  550. //
  551. //----------------------------------------------------------------------------
  552. STDAPI CLangBarItemMgr::AdviseItemSink(ITfLangBarItemSink *punk, DWORD *pdwCookie, REFGUID rguidItem)
  553. {
  554. CLBarItemSinkProxy *pProxy;
  555. CLBarItemSink *pSink;
  556. int nCnt;
  557. HRESULT hr;
  558. if (pdwCookie == NULL)
  559. return E_POINTER;
  560. *pdwCookie = 0;
  561. if (punk == NULL)
  562. return E_POINTER;
  563. pProxy = GetItemSinkProxy(rguidItem);
  564. if (!pProxy)
  565. return E_INVALIDARG;
  566. pSink = new CLBarItemSink();
  567. if (!pSink)
  568. {
  569. hr = E_OUTOFMEMORY;
  570. goto Exit;
  571. }
  572. *pdwCookie = _GetCookie();
  573. if (!pSink->Init(punk, &pProxy->_info, *pdwCookie))
  574. {
  575. hr = E_FAIL;
  576. goto Exit;
  577. }
  578. nCnt = _rgSink.Count();
  579. if (!_rgSink.Insert(nCnt, 1))
  580. {
  581. hr = E_OUTOFMEMORY;
  582. goto Exit;
  583. }
  584. _rgSink.Set(nCnt, pSink);
  585. hr = S_OK;
  586. Exit:
  587. return hr;
  588. }
  589. //+---------------------------------------------------------------------------
  590. //
  591. // UnregisterItemSink
  592. //
  593. //----------------------------------------------------------------------------
  594. STDAPI CLangBarItemMgr::UnadviseItemSink(DWORD dwCookie)
  595. {
  596. int i;
  597. int nCnt = _rgSink.Count();
  598. for (i = 0; i < nCnt ; i++)
  599. {
  600. CLBarItemSink *pSink = _rgSink.Get(i);
  601. if (pSink->_dwCookie == dwCookie)
  602. {
  603. #ifdef DEBUG
  604. pSink->_fUnadvised = TRUE;
  605. #endif
  606. _rgSink.Remove(i, 1);
  607. delete pSink;
  608. break;
  609. }
  610. }
  611. return S_OK;
  612. }
  613. //+---------------------------------------------------------------------------
  614. //
  615. // GetItemFloatingRect
  616. //
  617. //----------------------------------------------------------------------------
  618. STDAPI CLangBarItemMgr::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc)
  619. {
  620. if (!prc)
  621. return E_INVALIDARG;
  622. if (!dwThreadId)
  623. dwThreadId = GetCurrentThreadId();
  624. memset(prc, 0, sizeof(*prc));
  625. return ThreadGetItemFloatingRect(dwThreadId, rguid, prc);
  626. }
  627. //+---------------------------------------------------------------------------
  628. //
  629. // GetItemsStatus
  630. //
  631. //----------------------------------------------------------------------------
  632. STDAPI CLangBarItemMgr::GetItemsStatus(ULONG ulCount, const GUID *prgguid, DWORD *pdwStatus)
  633. {
  634. ULONG ul;
  635. for (ul = 0; ul < ulCount; ul++)
  636. {
  637. int i;
  638. BOOL fFound = FALSE;
  639. for (i = 0; i < _rglbiProxy.Count(); i++)
  640. {
  641. CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
  642. if (IsEqualGUID(pProxy->_info.guidItem, *prgguid))
  643. {
  644. if (FAILED(pProxy->_plbi->GetStatus(pdwStatus)))
  645. return E_FAIL;
  646. pdwStatus++;
  647. prgguid++;
  648. fFound = TRUE;
  649. break;
  650. }
  651. }
  652. if (!fFound)
  653. return E_FAIL;
  654. }
  655. return S_OK;
  656. }
  657. //+---------------------------------------------------------------------------
  658. //
  659. // GetItemNum
  660. //
  661. //----------------------------------------------------------------------------
  662. STDAPI CLangBarItemMgr::GetItemNum(ULONG *pulCount)
  663. {
  664. if (!pulCount)
  665. return E_INVALIDARG;
  666. *pulCount = _rglbiProxy.Count();
  667. return S_OK;
  668. }
  669. //+---------------------------------------------------------------------------
  670. //
  671. // GetItems
  672. //
  673. //----------------------------------------------------------------------------
  674. STDAPI CLangBarItemMgr::GetItems(ULONG ulCount, ITfLangBarItem **ppItem, TF_LANGBARITEMINFO *pInfo, DWORD *pdwStatus, ULONG *pcFetched)
  675. {
  676. int i;
  677. ULONG ulFetched = 0;
  678. CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
  679. BOOL fHasFocusDIM;
  680. if (!ulCount)
  681. return S_FALSE;
  682. fHasFocusDIM = (ptim && ptim->_GetFocusDocInputMgr()) ? TRUE : FALSE;
  683. for (i = 0; i < _rglbiProxy.Count(); i++)
  684. {
  685. CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i);
  686. if (!fHasFocusDIM && pProxy->_fCicTip)
  687. continue;
  688. if (FAILED(pProxy->_plbi->GetInfo(pInfo)))
  689. return E_FAIL;
  690. pInfo++;
  691. if (FAILED(pProxy->_plbi->GetStatus(pdwStatus)))
  692. return E_FAIL;
  693. pdwStatus++;
  694. *ppItem = pProxy->_plbi;
  695. pProxy->_plbi->AddRef();
  696. ppItem++;
  697. ulFetched++;
  698. if (ulFetched >= ulCount)
  699. break;
  700. }
  701. if (pcFetched)
  702. *pcFetched = ulFetched;
  703. return (ulFetched == ulCount) ? S_OK : S_FALSE;
  704. }
  705. //+---------------------------------------------------------------------------
  706. //
  707. // AdviseItemsSink
  708. //
  709. //----------------------------------------------------------------------------
  710. STDMETHODIMP CLangBarItemMgr::AdviseItemsSink(ULONG ulCount, ITfLangBarItemSink **ppunk, const GUID *pguidItem, DWORD *pdwCookie)
  711. {
  712. ULONG ul;
  713. for ( ul = 0; ul < ulCount; ul++)
  714. {
  715. if (FAILED(AdviseItemSink(ppunk[ul], &pdwCookie[ul], pguidItem[ul])))
  716. return E_FAIL;
  717. }
  718. return S_OK;
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // UnadviseItemsSink
  723. //
  724. //----------------------------------------------------------------------------
  725. STDMETHODIMP CLangBarItemMgr::UnadviseItemsSink(ULONG ulCount, DWORD *pdwCookie)
  726. {
  727. ULONG ul;
  728. for ( ul = 0; ul < ulCount; ul++)
  729. {
  730. if (FAILED(UnadviseItemSink(pdwCookie[ul])))
  731. return E_FAIL;
  732. }
  733. return S_OK;
  734. }
  735. //+---------------------------------------------------------------------------
  736. //
  737. // EnumLBItem
  738. //
  739. //----------------------------------------------------------------------------
  740. STDAPI CLangBarItemMgr::EnumItems(IEnumTfLangBarItems **ppEnum)
  741. {
  742. CEnumLBItem *pEnum = new CEnumLBItem(_psfn);
  743. *ppEnum = pEnum;
  744. return S_OK;
  745. }
  746. //+---------------------------------------------------------------------------
  747. //
  748. // GetItem
  749. //
  750. //----------------------------------------------------------------------------
  751. STDAPI CLangBarItemMgr::GetItem(REFGUID rguid, ITfLangBarItem **ppItem)
  752. {
  753. if (!ppItem)
  754. return E_INVALIDARG;
  755. *ppItem = NULL;
  756. CLBarItemSinkProxy *pProxy = GetItemSinkProxy(rguid);
  757. if (pProxy)
  758. {
  759. *ppItem = pProxy->_plbi;
  760. (*ppItem)->AddRef();
  761. }
  762. return *ppItem ? S_OK : S_FALSE;
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // _AddWin32IMECtrl
  767. //
  768. //----------------------------------------------------------------------------
  769. void CLangBarItemMgr::_AddWin32IMECtrl(BOOL fNotify)
  770. {
  771. if (_plbiWin32IME != NULL)
  772. return;
  773. if (_plbiWin32IME = new CLBarItemWin32IME)
  774. {
  775. AddItem(_plbiWin32IME);
  776. _plbiWin32IME->ShowInternal(TRUE, fNotify);
  777. }
  778. }
  779. //+---------------------------------------------------------------------------
  780. //
  781. // _RemoveWin32IMECtrl
  782. //
  783. //----------------------------------------------------------------------------
  784. void CLangBarItemMgr::_RemoveWin32IMECtrl()
  785. {
  786. if (_plbiWin32IME == NULL)
  787. return;
  788. RemoveItem(_plbiWin32IME);
  789. }
  790. //+---------------------------------------------------------------------------
  791. //
  792. // GetItemSinkProxy
  793. //
  794. //----------------------------------------------------------------------------
  795. CLBarItemSinkProxy *CLangBarItemMgr::GetItemSinkProxy(REFGUID rguid)
  796. {
  797. CLBarItemSinkProxy *pProxy = NULL;
  798. int nCnt = _rglbiProxy.Count();
  799. int i;
  800. for (i = 0; i < nCnt; i++)
  801. {
  802. CLBarItemSinkProxy *pProxyTemp = _rglbiProxy.Get(i);
  803. if (IsEqualGUID(pProxyTemp->_info.guidItem, rguid))
  804. {
  805. pProxy = pProxyTemp;
  806. break;
  807. }
  808. }
  809. return pProxy;
  810. }
  811. //+---------------------------------------------------------------------------
  812. //
  813. // UpdateIcon
  814. //
  815. //----------------------------------------------------------------------------
  816. HRESULT CLangBarItemMgr::OnUpdate(ITfLangBarItem *plbi, DWORD dwFlags)
  817. {
  818. int i;
  819. int nCnt;
  820. HRESULT hr;
  821. TF_LANGBARITEMINFO info;
  822. BOOL fFound;
  823. //
  824. // Toolbar will be being updated. So no need to handle OnUpdate.
  825. // Toolbar will ask icons, bitmaps no matter what.
  826. //
  827. if (!_fHandleOnUpdate)
  828. return S_OK;
  829. hr = plbi->GetInfo(&info);
  830. if (FAILED(hr))
  831. return hr;
  832. fFound = FALSE;
  833. nCnt = _rgSink.Count();
  834. for (i = 0; i < nCnt ; i++)
  835. {
  836. CLBarItemSink *pSink = _rgSink.Get(i);
  837. #ifdef DEBUG
  838. Assert(!pSink->_fUnadvised);
  839. #endif
  840. if (IsEqualGUID(pSink->_info.guidItem, info.guidItem))
  841. {
  842. pSink->_dwDirtyUpdateFlags |= dwFlags;
  843. fFound = TRUE;
  844. }
  845. }
  846. if (_fDirtyUpdateHandling)
  847. {
  848. //
  849. // #509783
  850. //
  851. // Some apps (Adobe PhotoShop) call PeekMessage() to eat the message
  852. // from queue but it does not call DispatchMessage() sometimes.
  853. // We need a way to restore _fDirtyUpdateHandling flag.
  854. //
  855. if (GetTickCount() - dwDirtyUpdateHandlingTime > 1000)
  856. {
  857. _fDirtyUpdateHandling = 0;
  858. }
  859. }
  860. if (fFound && !_fDirtyUpdateHandling)
  861. {
  862. HWND hwnd = EnsureMarshalWnd();
  863. if (hwnd)
  864. {
  865. PostMessage(hwnd, g_msgNuiMgrDirtyUpdate, 0, 0);
  866. _fDirtyUpdateHandling = TRUE;
  867. dwDirtyUpdateHandlingTime = GetTickCount();
  868. //
  869. // we need to check Kana-Caps status every time the langbar item
  870. // is updated.
  871. //
  872. SYSTHREAD *psfn = FindSYSTHREAD();
  873. if (psfn)
  874. StartKanaCapsUpdateTimer(psfn);
  875. }
  876. }
  877. return S_OK;
  878. }
  879. //+---------------------------------------------------------------------------
  880. //
  881. // OnUpdateHandler
  882. //
  883. //----------------------------------------------------------------------------
  884. HRESULT CLangBarItemMgr::OnUpdateHandler()
  885. {
  886. int i;
  887. int nCnt;
  888. _fDirtyUpdateHandling = FALSE;
  889. _fInOnUpdateHandler = TRUE;
  890. nCnt = _rgSink.Count();
  891. for (i = 0; i < nCnt ; i++)
  892. {
  893. CLBarItemSink *pSink = _rgSink.Get(i);
  894. DWORD dwFlags = pSink->_dwDirtyUpdateFlags;
  895. if (!dwFlags)
  896. continue;
  897. pSink->_dwDirtyUpdateFlags = 0;
  898. pSink->_pItemSink->OnUpdate(dwFlags);
  899. int nCntNew = _rgSink.Count();
  900. if (nCnt > nCntNew)
  901. {
  902. nCnt = nCntNew;
  903. i--;
  904. }
  905. }
  906. _fInOnUpdateHandler = FALSE;
  907. return S_OK;
  908. }
  909. //////////////////////////////////////////////////////////////////////////////
  910. //
  911. // CLBarItemSinkProxy
  912. //
  913. //////////////////////////////////////////////////////////////////////////////
  914. BOOL CLBarItemSinkProxy::Init(CLangBarItemMgr *plbiMgr, ITfLangBarItem *plbi, TF_LANGBARITEMINFO *pinfo)
  915. {
  916. _plbiMgr = plbiMgr; // don't AddRef, because this obj is contained in the mgr's life
  917. // we'd create a circular ref if we did, and we don't need to
  918. _plbi = plbi;
  919. _plbi->AddRef();
  920. _fCicTip = FALSE;
  921. _info = *pinfo;
  922. CTip *ptip;
  923. TfGuidAtom guidatom;
  924. CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
  925. if (ptim && SUCCEEDED(MyRegisterGUID(_info.clsidService, &guidatom)))
  926. {
  927. _fCicTip = ptim->_GetCTipfromGUIDATOM(guidatom, &ptip);
  928. }
  929. return TRUE;
  930. }
  931. //////////////////////////////////////////////////////////////////////////////
  932. //
  933. // CEnumLBItem
  934. //
  935. //////////////////////////////////////////////////////////////////////////////
  936. //+---------------------------------------------------------------------------
  937. //
  938. // ctor
  939. //
  940. //----------------------------------------------------------------------------
  941. CEnumLBItem::CEnumLBItem(SYSTHREAD *psfn) : CSysThreadRef(psfn)
  942. {
  943. Dbg_MemSetThisNameID(TEXT("CEnumLBItem"));
  944. CThreadInputMgr *ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(_psfn);
  945. if (ptim)
  946. _fHasFocusDIM = ptim->_GetFocusDocInputMgr() ? TRUE : FALSE;
  947. _nCur = 0;
  948. }
  949. //+---------------------------------------------------------------------------
  950. //
  951. // dtor
  952. //
  953. //----------------------------------------------------------------------------
  954. CEnumLBItem::~CEnumLBItem()
  955. {
  956. }
  957. //+---------------------------------------------------------------------------
  958. //
  959. // Clone
  960. //
  961. //----------------------------------------------------------------------------
  962. HRESULT CEnumLBItem::Clone(IEnumTfLangBarItems **ppEnum)
  963. {
  964. return E_NOTIMPL;
  965. }
  966. //+---------------------------------------------------------------------------
  967. //
  968. // Next
  969. //
  970. //----------------------------------------------------------------------------
  971. HRESULT CEnumLBItem::Next(ULONG ulCount, ITfLangBarItem **ppLBItem, ULONG *pcFetched)
  972. {
  973. int nCnt;
  974. ULONG cFetched;
  975. CLangBarItemMgr *plbim = _psfn->plbim;
  976. if (!plbim)
  977. return E_FAIL;
  978. nCnt = plbim->_rglbiProxy.Count();
  979. cFetched = 0;
  980. if (!ppLBItem)
  981. return E_INVALIDARG;
  982. *ppLBItem = NULL;
  983. while (cFetched < ulCount)
  984. {
  985. *ppLBItem = NULL;
  986. CLBarItemSinkProxy *pProxy;
  987. if (nCnt <= _nCur)
  988. break;
  989. pProxy = plbim->_rglbiProxy.Get(_nCur);
  990. if (!pProxy)
  991. break;
  992. if (_fHasFocusDIM || !pProxy->_fCicTip)
  993. {
  994. *ppLBItem = pProxy->_plbi;
  995. (*ppLBItem)->AddRef();
  996. ppLBItem++;
  997. cFetched++;
  998. }
  999. _nCur++;
  1000. }
  1001. if (pcFetched)
  1002. *pcFetched = cFetched;
  1003. return (cFetched == ulCount) ? S_OK : S_FALSE;
  1004. }
  1005. //+---------------------------------------------------------------------------
  1006. //
  1007. // Reset
  1008. //
  1009. //----------------------------------------------------------------------------
  1010. HRESULT CEnumLBItem::Reset()
  1011. {
  1012. _nCur = 0;
  1013. return S_OK;
  1014. }
  1015. //+---------------------------------------------------------------------------
  1016. //
  1017. // Skip
  1018. //
  1019. //----------------------------------------------------------------------------
  1020. HRESULT CEnumLBItem::Skip(ULONG ulCount)
  1021. {
  1022. int nCnt;
  1023. CLangBarItemMgr *plbim = _psfn->plbim;
  1024. if (!plbim)
  1025. return E_FAIL;
  1026. nCnt = plbim->_rglbiProxy.Count();
  1027. while (ulCount)
  1028. {
  1029. if (nCnt <= _nCur)
  1030. break;
  1031. _nCur++;
  1032. ulCount--;
  1033. }
  1034. return ulCount ? S_FALSE : S_OK;
  1035. }