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.

565 lines
14 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. profile.cpp
  5. Abstract:
  6. This file implements the CActiveIMMProfiles Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "globals.h"
  13. #include "profile.h"
  14. #include "idebug.h"
  15. UINT WINAPI RawImmGetDescriptionA(HKL hkl, LPSTR lpstr, UINT uBufLen);
  16. //
  17. // Callbacks
  18. //
  19. HRESULT
  20. CAImeProfile::ActiveLanguageProfileNotifySinkCallback(
  21. REFGUID rguid,
  22. REFGUID rguidProfile,
  23. BOOL fActivated,
  24. void *pv
  25. )
  26. {
  27. DebugMsg(TF_FUNC, "ActiveLanguageProfileNotifySinkCallback");
  28. CAImeProfile* _this = (CAImeProfile*)pv;
  29. _this->ResetCache();
  30. return S_OK;
  31. }
  32. //
  33. // Create instance
  34. //
  35. // entry point for msimtf.dll
  36. HRESULT CAImmProfile_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
  37. {
  38. return CAImeProfile::CreateInstance(pUnkOuter, riid, ppvObj);
  39. }
  40. /* static */
  41. HRESULT
  42. CAImeProfile::CreateInstance(
  43. IUnknown *pUnkOuter,
  44. REFIID riid,
  45. void **ppvObj
  46. )
  47. {
  48. IMTLS *ptls;
  49. DebugMsg(TF_FUNC, "CAImeProfile::CreateInstance called.");
  50. *ppvObj = NULL;
  51. if (pUnkOuter != NULL) {
  52. return CLASS_E_NOAGGREGATION;
  53. }
  54. ptls = IMTLS_GetOrAlloc();
  55. if (ptls == NULL)
  56. return E_FAIL;
  57. if (ptls->pAImeProfile != NULL) {
  58. /*
  59. * CAImeProfile instance already have in a thread.
  60. */
  61. return ptls->pAImeProfile->QueryInterface(riid, ppvObj);
  62. }
  63. else {
  64. /*
  65. * Create an new CAImeProfile instance.
  66. */
  67. CAImeProfile* pImeProfile = new CAImeProfile;
  68. if (pImeProfile) {
  69. HRESULT hr = pImeProfile->QueryInterface(riid, ppvObj);
  70. if (SUCCEEDED(hr)) {
  71. hr = pImeProfile->InitProfileInstance();
  72. if (hr != S_OK) {
  73. DebugMsg(TF_ERROR, "CAImeProfile::CreateInstance: Couldn't create tim!");
  74. Assert(0); // couldn't create tim!
  75. }
  76. pImeProfile->Release();
  77. }
  78. Assert(ptls->pAImeProfile == NULL);
  79. ptls->pAImeProfile = pImeProfile; // Set CAImeProfile instance in the TLS data.
  80. ptls->pAImeProfile->AddRef();
  81. return hr;
  82. }
  83. }
  84. return E_OUTOFMEMORY;
  85. }
  86. //
  87. // Initialization, destruction and standard COM stuff
  88. //
  89. CAImeProfile::CAImeProfile(
  90. )
  91. {
  92. DllAddRef();
  93. m_ref = 1;
  94. m_profile = NULL;
  95. m_pActiveLanguageProfileNotifySink = NULL;
  96. m_SavedLangId = LANG_NEUTRAL;
  97. m_fActivateThread = FALSE;
  98. ResetCache();
  99. m_cp = CP_ACP;
  100. m_LangID = LANG_NEUTRAL;
  101. m_hKL = 0;
  102. }
  103. CAImeProfile::~CAImeProfile()
  104. {
  105. if (m_profile) {
  106. if (m_SavedLangId != LANG_NEUTRAL) {
  107. HRESULT hr = m_profile->ChangeCurrentLanguage(m_SavedLangId);
  108. if (FAILED(hr)) {
  109. TraceMsg(TF_ERROR, "CAImeProfile::~CAImeProfile: failed for ChangeCurrentLanguage");
  110. }
  111. }
  112. m_profile->Release();
  113. m_profile = NULL;
  114. }
  115. if (m_pActiveLanguageProfileNotifySink) {
  116. m_pActiveLanguageProfileNotifySink->_Unadvise();
  117. m_pActiveLanguageProfileNotifySink->Release();
  118. m_pActiveLanguageProfileNotifySink = NULL;
  119. }
  120. DllRelease();
  121. }
  122. HRESULT
  123. CAImeProfile::QueryInterface(
  124. REFIID riid,
  125. void **ppvObj
  126. )
  127. {
  128. *ppvObj = NULL;
  129. if (IsEqualIID(riid, IID_IAImeProfile) ||
  130. IsEqualIID(riid, IID_IUnknown)) {
  131. *ppvObj = static_cast<IAImeProfile*>(this);
  132. }
  133. if (*ppvObj) {
  134. AddRef();
  135. return S_OK;
  136. }
  137. return E_NOINTERFACE;
  138. }
  139. ULONG
  140. CAImeProfile::AddRef(
  141. )
  142. {
  143. return InterlockedIncrement(&m_ref);
  144. }
  145. ULONG
  146. CAImeProfile::Release(
  147. )
  148. {
  149. ULONG cr = InterlockedDecrement(&m_ref);
  150. if (cr == 0) {
  151. delete this;
  152. }
  153. return cr;
  154. }
  155. HRESULT
  156. CAImeProfile::InitProfileInstance(
  157. )
  158. {
  159. HRESULT hr;
  160. IMTLS *ptls;
  161. hr = TF_CreateInputProcessorProfiles(&m_profile);
  162. if (FAILED(hr)) {
  163. TraceMsg(TF_ERROR, "CAImeProfile::InitProfileInstance: failed for CoCreate");
  164. }
  165. else if (m_pActiveLanguageProfileNotifySink == NULL) {
  166. m_pActiveLanguageProfileNotifySink = new CActiveLanguageProfileNotifySink(CAImeProfile::ActiveLanguageProfileNotifySinkCallback, this);
  167. if (m_pActiveLanguageProfileNotifySink == NULL) {
  168. DebugMsg(TF_ERROR, "Couldn't create ActiveLanguageProfileNotifySink!");
  169. m_profile->Release();
  170. m_profile = NULL;
  171. return E_FAIL;
  172. }
  173. if ((ptls = IMTLS_GetOrAlloc()) && ptls->tim != NULL)
  174. {
  175. m_pActiveLanguageProfileNotifySink->_Advise(ptls->tim);
  176. }
  177. }
  178. return hr;
  179. }
  180. HRESULT
  181. CAImeProfile::Activate(
  182. void
  183. )
  184. {
  185. m_fActivateThread = TRUE;
  186. ResetCache();
  187. return S_OK;
  188. }
  189. HRESULT
  190. CAImeProfile::Deactivate(
  191. void
  192. )
  193. {
  194. m_fActivateThread = FALSE;
  195. return S_OK;
  196. }
  197. HRESULT
  198. CAImeProfile::ChangeCurrentKeyboardLayout(
  199. HKL hKL
  200. )
  201. {
  202. HRESULT hr;
  203. LANGID CurrentLangId;
  204. hr = m_profile->GetCurrentLanguage(&CurrentLangId);
  205. if (FAILED(hr)) {
  206. TraceMsg(TF_ERROR, "CAImeProfile::ChangeCurrentKeyboardLayout: failed for GetCurrentLanguage");
  207. }
  208. else if (hKL != NULL) {
  209. LANGID LangId = LangIdFromKL(hKL);
  210. if (LangId != CurrentLangId) {
  211. hr = m_profile->ChangeCurrentLanguage(LangId);
  212. if (FAILED(hr)) {
  213. m_SavedLangId = LANG_NEUTRAL;
  214. TraceMsg(TF_ERROR, "CAImeProfile::ChangeCurrentKeyboardLayout: failed for ChangeCurrentLanguage");
  215. }
  216. m_SavedLangId = LangId;
  217. }
  218. }
  219. return hr;
  220. }
  221. HRESULT
  222. CAImeProfile::GetLangId(
  223. LANGID *plid
  224. )
  225. {
  226. if (!m_profile)
  227. return E_FAIL;
  228. if (!plid)
  229. return E_INVALIDARG;
  230. HRESULT hr = S_OK;
  231. if (m_fInitLangID) {
  232. *plid = m_LangID;
  233. }
  234. else {
  235. *plid = LANG_NEUTRAL;
  236. hr = m_profile->GetCurrentLanguage(plid);
  237. if (FAILED(hr)) {
  238. TraceMsg(TF_ERROR, "CAImeProfile::GetLangId: failed for GetCurrentLanguage");
  239. }
  240. else {
  241. m_LangID = *plid;
  242. m_fInitLangID = TRUE;
  243. }
  244. }
  245. return hr;
  246. }
  247. HRESULT
  248. CAImeProfile::GetCodePageA(
  249. UINT *puCodePage
  250. )
  251. {
  252. if (!puCodePage)
  253. return E_INVALIDARG;
  254. if (m_fInitCP) {
  255. *puCodePage = m_cp;
  256. }
  257. else {
  258. *puCodePage = CP_ACP;
  259. LANGID langid;
  260. if (FAILED(GetLangId(&langid)))
  261. return E_FAIL;
  262. CHAR szCodePage[12];
  263. int ret = GetLocaleInfo(MAKELCID(langid, SORT_DEFAULT),
  264. LOCALE_IDEFAULTANSICODEPAGE,
  265. szCodePage,
  266. sizeof(szCodePage));
  267. if (ret) {
  268. szCodePage[ARRAYSIZE(szCodePage)-1] = '\0';
  269. *puCodePage = strtoul(szCodePage, NULL, 10);
  270. m_cp = *puCodePage;
  271. m_fInitCP = TRUE;
  272. }
  273. }
  274. return S_OK;
  275. }
  276. #if 1
  277. //
  278. // TEST CODE
  279. //
  280. #include "osver.h"
  281. extern HINSTANCE hIMM; // temporary: do not call IMM32 for now
  282. BOOL IsIMEHKL(HKL hkl) {
  283. return ((((DWORD)(UINT_PTR)hkl) & 0xf0000000) == 0xe0000000) ? TRUE : FALSE;
  284. }
  285. #endif
  286. HRESULT
  287. CAImeProfile::GetKeyboardLayout(
  288. HKL* phkl
  289. )
  290. {
  291. if (! phkl)
  292. return E_INVALIDARG;
  293. *phkl = NULL;
  294. if (m_fInitHKL) {
  295. *phkl = m_hKL;
  296. }
  297. else if (! m_fActivateThread) {
  298. return E_FAIL;
  299. }
  300. else {
  301. LANGID langid;
  302. GUID guidProfile;
  303. HRESULT hr = m_profile->GetActiveLanguageProfile(GUID_TFCAT_TIP_KEYBOARD,
  304. &langid,
  305. &guidProfile);
  306. if (FAILED(hr))
  307. return hr;
  308. //
  309. // Instead of (!IsEqualGUID(guidProfil, GUID_NULL)), we check
  310. // 2nd, 3r and 4th DWORD of guidProfile. Because
  311. // GetActivelanguageProfile(category guid) may return hKL in
  312. // guidProfile
  313. //
  314. if ((((unsigned long *) &guidProfile)[1] != 0) ||
  315. (((unsigned long *) &guidProfile)[2] != 0) ||
  316. (((unsigned long *) &guidProfile)[3] != 0)) {
  317. /*
  318. * Current keyboard layout is Cicero.
  319. */
  320. m_hKL = (HKL)LongToHandle(langid); // Don't use ::GetKeyboardLayout(0);
  321. // Cicero awre doesn't case hKL.
  322. #if 1
  323. //
  324. // check the dummy hkl
  325. //
  326. HKL fake_hKL = ::GetKeyboardLayout(0);
  327. if (IsIMEHKL(fake_hKL)) {
  328. //
  329. // fake hKL is IME hKL.
  330. //
  331. hIMM = GetSystemModuleHandle("imm32.dll");
  332. if (hIMM != NULL) {
  333. char szDesc[256];
  334. char szDumbDesc[256];
  335. DWORD ret = RawImmGetDescriptionA(fake_hKL, szDesc, sizeof(szDesc));
  336. if (ret != 0) {
  337. wsprintf(szDumbDesc, "hkl%04x", LOWORD((UINT_PTR)fake_hKL));
  338. if (lstrcmp(szDumbDesc, szDesc) != 0) {
  339. //
  340. // fake hKL is regacy IME hKL.
  341. //
  342. if (IsOnNT()) {
  343. char szKLID[256];
  344. wsprintf(szKLID, "%08x", LOWORD((UINT_PTR) m_hKL));
  345. HKL win32_hKL = LoadKeyboardLayout(szKLID, KLF_NOTELLSHELL);
  346. }
  347. else {
  348. }
  349. }
  350. else {
  351. //
  352. // Dummy Cicero hKL for Win9x.
  353. //
  354. UINT n = GetKeyboardLayoutList(0, NULL);
  355. if (n) {
  356. HKL* phKL = new HKL [n];
  357. if (phKL) {
  358. HKL* p = phKL;
  359. GetKeyboardLayoutList(n, phKL);
  360. while (n--) {
  361. if (IsIMEHKL(*p)) {
  362. ret = RawImmGetDescriptionA(*p, szDesc, sizeof(szDesc));
  363. if (ret != 0) {
  364. wsprintf(szDumbDesc, "hkl%04x", LOWORD((UINT_PTR)*p));
  365. if (lstrcmp(szDumbDesc, szDesc) == 0) {
  366. //
  367. // Dummy Cicero hKL for Win9x.
  368. //
  369. char szKLID[256];
  370. wsprintf(szKLID, "%08x", LOWORD((UINT_PTR) *p));
  371. HKL win32_hKL = LoadKeyboardLayout(szKLID, KLF_NOTELLSHELL);
  372. break;
  373. }
  374. }
  375. }
  376. p++;
  377. }
  378. delete [] phKL;
  379. }
  380. }
  381. }
  382. }
  383. FreeLibrary(hIMM);
  384. hIMM = NULL;
  385. }
  386. }
  387. #endif
  388. }
  389. else if (!IsEqualGUID(guidProfile, GUID_NULL)) {
  390. /*
  391. * Current keyboard layout is regacy IME.
  392. */
  393. m_hKL = (HKL)LongToHandle(*(DWORD *)&guidProfile);
  394. }
  395. else {
  396. m_hKL = 0;
  397. }
  398. *phkl = m_hKL;
  399. m_fInitHKL = TRUE;
  400. }
  401. return S_OK;
  402. }
  403. HRESULT
  404. CAImeProfile::IsIME(
  405. HKL hKL
  406. )
  407. {
  408. LANGID LangId = LangIdFromKL(hKL);
  409. Interface<IEnumTfLanguageProfiles> LanguageProfiles;
  410. HRESULT hr = m_profile->EnumLanguageProfiles(LangId,
  411. LanguageProfiles);
  412. if (FAILED(hr))
  413. return S_FALSE;
  414. CEnumrateValue<IEnumTfLanguageProfiles,
  415. TF_LANGUAGEPROFILE,
  416. LANG_PROF_ENUM_ARG> Enumrate(LanguageProfiles,
  417. LanguageProfilesCallback);
  418. ENUM_RET ret = Enumrate.DoEnumrate();
  419. if (ret != ENUM_FIND)
  420. return S_FALSE;
  421. else
  422. return S_OK;
  423. }
  424. HRESULT
  425. CAImeProfile::GetActiveLanguageProfile(
  426. IN HKL hKL,
  427. IN GUID catid,
  428. OUT TF_LANGUAGEPROFILE* pLanguageProfile
  429. )
  430. {
  431. LANGID LangId = LangIdFromKL(hKL);
  432. Interface<IEnumTfLanguageProfiles> LanguageProfiles;
  433. HRESULT hr = m_profile->EnumLanguageProfiles(LangId,
  434. LanguageProfiles);
  435. if (FAILED(hr))
  436. return S_FALSE;
  437. LANG_PROF_ENUM_ARG LangProfEnumArg;
  438. LangProfEnumArg.catid = catid;
  439. CEnumrateValue<IEnumTfLanguageProfiles,
  440. TF_LANGUAGEPROFILE,
  441. LANG_PROF_ENUM_ARG> Enumrate(LanguageProfiles,
  442. LanguageProfilesCallback,
  443. &LangProfEnumArg);
  444. ENUM_RET ret = Enumrate.DoEnumrate();
  445. if (ret != ENUM_FIND || pLanguageProfile == NULL)
  446. return S_FALSE;
  447. else {
  448. *pLanguageProfile = LangProfEnumArg.LanguageProfile;
  449. return S_OK;
  450. }
  451. }
  452. ENUM_RET
  453. CAImeProfile::LanguageProfilesCallback(
  454. TF_LANGUAGEPROFILE LanguageProfile,
  455. LANG_PROF_ENUM_ARG* pLangProfEnumArg
  456. )
  457. {
  458. if (LanguageProfile.fActive &&
  459. ! IsEqualGUID(LanguageProfile.clsid, GUID_NULL)) {
  460. if (pLangProfEnumArg) {
  461. if (! IsEqualGUID(LanguageProfile.catid, pLangProfEnumArg->catid)) {
  462. return ENUM_CONTINUE;
  463. }
  464. pLangProfEnumArg->LanguageProfile = LanguageProfile;
  465. }
  466. return ENUM_FIND;
  467. }
  468. return ENUM_CONTINUE;
  469. }