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.

392 lines
9.8 KiB

  1. //
  2. // imecls.cpp
  3. //
  4. #include "private.h"
  5. #include "imecls.h"
  6. DBG_ID_INSTANCE(CSysImeClassWnd);
  7. DBG_ID_INSTANCE(CSysImeClassWndArray);
  8. #define IMECLASSNAME TEXT("ime")
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // misc func
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. //+---------------------------------------------------------------------------
  15. //
  16. // CheckExistingImeClassWnd
  17. //
  18. //----------------------------------------------------------------------------
  19. BOOL CheckExistingImeClassWnd(SYSTHREAD *psfn)
  20. {
  21. #ifdef USE_IMECLASS_SUBCLASS
  22. if (!psfn->prgImeClassWnd)
  23. {
  24. HWND hwnd = NULL;
  25. DWORD dwCurThreadId = GetCurrentThreadId();
  26. while (hwnd = FindWindowEx(NULL, hwnd, IMECLASSNAME, NULL))
  27. {
  28. DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
  29. if (dwThreadId != dwCurThreadId)
  30. continue;
  31. CSysImeClassWnd *picw = new CSysImeClassWnd();
  32. picw->Init(hwnd);
  33. }
  34. }
  35. if (!psfn->prgImeClassWnd)
  36. return TRUE;
  37. if (GetFocus())
  38. psfn->prgImeClassWnd->StartSubclass();
  39. #endif
  40. return TRUE;
  41. }
  42. //+---------------------------------------------------------------------------
  43. //
  44. // UninitImeClassWndOnProcess
  45. //
  46. //----------------------------------------------------------------------------
  47. BOOL UninitImeClassWndOnProcess()
  48. {
  49. HWND hwnd = NULL;
  50. DWORD dwCurProcessId = GetCurrentProcessId();
  51. while (hwnd = FindWindowEx(NULL, hwnd, IMECLASSNAME, NULL))
  52. {
  53. DWORD dwProcessId;
  54. DWORD dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
  55. if (dwProcessId != dwCurProcessId)
  56. continue;
  57. //
  58. // Set the wndproc pointer back to original WndProc.
  59. //
  60. // some other subclass window may keep my WndProc pointer.
  61. // but msctf.dll may be unloaded from memory so we don't want to
  62. // call him to set the wndproc pointer back to our Wndproc pointer.
  63. // The pointer will be bogus.
  64. //
  65. WNDPROC pfn = (WNDPROC)GetClassLongPtr(hwnd, GCLP_WNDPROC);
  66. if (pfn != (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC))
  67. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)pfn);
  68. }
  69. return TRUE;
  70. }
  71. //////////////////////////////////////////////////////////////////////////////
  72. //
  73. // CSysImeClassWnd
  74. //
  75. //////////////////////////////////////////////////////////////////////////////
  76. //+---------------------------------------------------------------------------
  77. //
  78. // ctor
  79. //
  80. //----------------------------------------------------------------------------
  81. CSysImeClassWnd::CSysImeClassWnd()
  82. {
  83. Dbg_MemSetThisNameID(TEXT("CSysImeClassWnd"));
  84. }
  85. //+---------------------------------------------------------------------------
  86. //
  87. // dtor
  88. //
  89. //----------------------------------------------------------------------------
  90. CSysImeClassWnd::~CSysImeClassWnd()
  91. {
  92. if (IsWindow(_hwnd))
  93. {
  94. Stop();
  95. if (_pfn)
  96. {
  97. //
  98. // Set the wndproc pointer back to original WndProc.
  99. //
  100. // some other subclass window may keep my WndProc pointer.
  101. // but msctf.dll may be unloaded from memory so we don't want to
  102. // call him to set the wndproc pointer back to our Wndproc pointer.
  103. // The pointer will be bogus.
  104. //
  105. WNDPROC pfnOrgImeWndProc;
  106. pfnOrgImeWndProc = (WNDPROC)GetClassLongPtr(_hwnd, GCLP_WNDPROC);
  107. SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)pfnOrgImeWndProc);
  108. _pfn = NULL;
  109. }
  110. }
  111. }
  112. //+---------------------------------------------------------------------------
  113. //
  114. // IsImeClassWnd
  115. //
  116. //----------------------------------------------------------------------------
  117. BOOL CSysImeClassWnd::IsImeClassWnd(HWND hwnd)
  118. {
  119. char szCls[6];
  120. if (!GetClassName(hwnd, szCls, sizeof(szCls)))
  121. return FALSE;
  122. return lstrcmpi(szCls, IMECLASSNAME) ? FALSE : TRUE;
  123. }
  124. //+---------------------------------------------------------------------------
  125. //
  126. // Init
  127. //
  128. //----------------------------------------------------------------------------
  129. BOOL CSysImeClassWnd::Init(HWND hwnd)
  130. {
  131. SYSTHREAD *psfn = GetSYSTHREAD();
  132. if (psfn == NULL)
  133. return FALSE;
  134. if (!psfn->prgImeClassWnd)
  135. {
  136. psfn->prgImeClassWnd = new CSysImeClassWndArray();
  137. if (!psfn->prgImeClassWnd)
  138. return FALSE;
  139. }
  140. CSysImeClassWnd **ppicw = psfn->prgImeClassWnd->Append(1);
  141. if (!ppicw)
  142. return FALSE;
  143. *ppicw = this;
  144. _hwnd = hwnd;
  145. _pfn = NULL;
  146. return TRUE;
  147. }
  148. //+---------------------------------------------------------------------------
  149. //
  150. // Start
  151. //
  152. //----------------------------------------------------------------------------
  153. void CSysImeClassWnd::Start()
  154. {
  155. Assert(IsWindow(_hwnd));
  156. if (_pfn)
  157. return;
  158. _pfn = (WNDPROC)SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc);
  159. }
  160. //+---------------------------------------------------------------------------
  161. //
  162. // Stop
  163. //
  164. //----------------------------------------------------------------------------
  165. void CSysImeClassWnd::Stop()
  166. {
  167. Assert(IsWindow(_hwnd));
  168. WNDPROC pfnCur;
  169. if (!_pfn)
  170. return;
  171. //
  172. // unfortunately, we can not restore the wndproc pointer always.
  173. // someone else subclassed it after we did.
  174. //
  175. pfnCur = (WNDPROC)GetWindowLongPtr(_hwnd, GWLP_WNDPROC);
  176. if (pfnCur == WndProc)
  177. {
  178. SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)_pfn);
  179. _pfn = NULL;
  180. }
  181. }
  182. //+---------------------------------------------------------------------------
  183. //
  184. // WndProc
  185. //
  186. //----------------------------------------------------------------------------
  187. LRESULT CSysImeClassWnd::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  188. {
  189. LRESULT lRet;
  190. SYSTHREAD *psfn = GetSYSTHREAD();
  191. if (!psfn || !psfn->prgImeClassWnd)
  192. {
  193. Assert(0);
  194. return 0;
  195. }
  196. CSysImeClassWnd *_this = psfn->prgImeClassWnd->Find(hwnd);
  197. if (!_this)
  198. {
  199. #ifdef DEBUG
  200. if ((uMsg != WM_DESTROY) && (uMsg != WM_NCDESTROY))
  201. {
  202. Assert(0);
  203. }
  204. #endif
  205. return 0;
  206. }
  207. WNDPROC pfn = _this->_pfn;
  208. if (!pfn)
  209. {
  210. Assert(0);
  211. return 0;
  212. }
  213. switch (uMsg)
  214. {
  215. #if 0
  216. //
  217. // we have a fall back logic to set the original window proc back
  218. // if we can not restore the window proc correctly.
  219. // so we don't have to do paranoid subclassing here.
  220. //
  221. case WM_IME_SELECT:
  222. case WM_IME_SETCONTEXT:
  223. _this->Stop();
  224. lRet = CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
  225. _this->Start();
  226. return lRet;
  227. #endif
  228. case WM_IME_NOTIFY:
  229. if ((wParam == IMN_SETOPENSTATUS) ||
  230. (wParam == IMN_SETCONVERSIONMODE))
  231. OnIMENotify();
  232. break;
  233. case WM_DESTROY:
  234. lRet = CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
  235. psfn->prgImeClassWnd->Remove(_this);
  236. return lRet;
  237. }
  238. return CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
  239. }
  240. //////////////////////////////////////////////////////////////////////////////
  241. //
  242. // CSysImeClassWndArray
  243. //
  244. //////////////////////////////////////////////////////////////////////////////
  245. //+---------------------------------------------------------------------------
  246. //
  247. // ctor
  248. //
  249. //----------------------------------------------------------------------------
  250. CSysImeClassWndArray::CSysImeClassWndArray()
  251. {
  252. Dbg_MemSetThisNameID(TEXT("CSysImeClassWndArray"));
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // StartSubClass
  257. //
  258. //----------------------------------------------------------------------------
  259. BOOL CSysImeClassWndArray::StartSubclass()
  260. {
  261. for (int i = 0; i < Count(); i++)
  262. {
  263. CSysImeClassWnd *picw = Get(i);
  264. picw->Start();
  265. }
  266. return TRUE;
  267. }
  268. //+---------------------------------------------------------------------------
  269. //
  270. // StopSubClass
  271. //
  272. //----------------------------------------------------------------------------
  273. BOOL CSysImeClassWndArray::StopSubclass()
  274. {
  275. for (int i = 0; i < Count(); i++)
  276. {
  277. CSysImeClassWnd *picw = Get(i);
  278. picw->Stop();
  279. }
  280. return TRUE;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Find
  285. //
  286. //----------------------------------------------------------------------------
  287. CSysImeClassWnd *CSysImeClassWndArray::Find(HWND hwnd)
  288. {
  289. for (int i = 0; i < Count(); i++)
  290. {
  291. CSysImeClassWnd *picw = Get(i);
  292. if (picw->GetWnd() == hwnd)
  293. return picw;
  294. }
  295. return NULL;
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Remove
  300. //
  301. //----------------------------------------------------------------------------
  302. void CSysImeClassWndArray::Remove(CSysImeClassWnd *picw)
  303. {
  304. for (int i = 0; i < Count(); i++)
  305. {
  306. if (picw == Get(i))
  307. {
  308. CPtrArray<CSysImeClassWnd>::Remove(i, 1);
  309. delete picw;
  310. break;
  311. }
  312. }
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // RemoveAll
  317. //
  318. //----------------------------------------------------------------------------
  319. void CSysImeClassWndArray::RemoveAll()
  320. {
  321. for (int i = 0; i < Count(); i++)
  322. {
  323. CSysImeClassWnd *picw = Get(i);
  324. delete picw;
  325. }
  326. Clear();
  327. }