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.

1332 lines
36 KiB

  1. #include "private.h"
  2. #include "immxutil.h"
  3. #include "helpers.h"
  4. #include "regsvr.h"
  5. //+---------------------------------------------------------------------------
  6. //
  7. // GetTextExtInActiveView
  8. //
  9. // Get a range text extent from the active view of a document mgr.
  10. //----------------------------------------------------------------------------
  11. HRESULT GetTextExtInActiveView(TfEditCookie ec, ITfRange *pRange, RECT *prc, BOOL *pfClipped)
  12. {
  13. ITfContext *pic;
  14. ITfContextView *pView;
  15. HRESULT hr;
  16. // do the deref: range->ic->defView->GetTextExt()
  17. if (pRange->GetContext(&pic) != S_OK)
  18. return E_FAIL;
  19. hr = pic->GetActiveView(&pView);
  20. pic->Release();
  21. if (hr != S_OK)
  22. return E_FAIL;
  23. hr = pView->GetTextExt(ec, pRange, prc, pfClipped);
  24. pView->Release();
  25. return hr;
  26. }
  27. //+---------------------------------------------------------------------------
  28. //
  29. // IsActiveView
  30. //
  31. // Returns TRUE iff pView is the active view in the specified context.
  32. //----------------------------------------------------------------------------
  33. BOOL IsActiveView(ITfContext *pic, ITfContextView *pView)
  34. {
  35. ITfContextView *pActiveView;
  36. BOOL fRet;
  37. if (pic->GetActiveView(&pActiveView) != S_OK)
  38. return FALSE;
  39. fRet = IdentityCompare(pActiveView, pView);
  40. pActiveView->Release();
  41. return fRet;
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // ShiftToOrClone
  46. //
  47. //----------------------------------------------------------------------------
  48. BOOL ShiftToOrClone(IAnchor **ppaDst, IAnchor *paSrc)
  49. {
  50. if (*ppaDst == paSrc)
  51. return TRUE;
  52. if (*ppaDst == NULL)
  53. {
  54. paSrc->Clone(ppaDst);
  55. }
  56. else
  57. {
  58. (*ppaDst)->ShiftTo(paSrc);
  59. }
  60. return (*ppaDst != NULL);
  61. }
  62. //+---------------------------------------------------------------------------
  63. //
  64. // AsciiToNum
  65. //
  66. //----------------------------------------------------------------------------
  67. DWORD AsciiToNum( char *pszAscii)
  68. {
  69. DWORD dwNum = 0;
  70. for (; *pszAscii; pszAscii++) {
  71. if (*pszAscii >= '0' && *pszAscii <= '9') {
  72. dwNum = (dwNum << 4) | (*pszAscii - '0');
  73. } else if (*pszAscii >= 'A' && *pszAscii <= 'F') {
  74. dwNum = (dwNum << 4) | (*pszAscii - 'A' + 0x000A);
  75. } else if (*pszAscii >= 'a' && *pszAscii <= 'f') {
  76. dwNum = (dwNum << 4) | (*pszAscii - 'a' + 0x000A);
  77. } else {
  78. return (0);
  79. }
  80. }
  81. return (dwNum);
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // AsciiToNumDec
  86. //
  87. //----------------------------------------------------------------------------
  88. BOOL AsciiToNumDec(char *pszAscii, DWORD *pdw)
  89. {
  90. *pdw = 0;
  91. for (; *pszAscii; pszAscii++)
  92. {
  93. if (*pszAscii >= '0' && *pszAscii <= '9')
  94. {
  95. *pdw *= 10;
  96. *pdw += (*pszAscii - '0');
  97. }
  98. else
  99. {
  100. *pdw = 0;
  101. return FALSE;
  102. }
  103. }
  104. return TRUE;
  105. }
  106. //+---------------------------------------------------------------------------
  107. //
  108. // NumToA
  109. //
  110. //----------------------------------------------------------------------------
  111. void NumToA(DWORD dw, char *psz)
  112. {
  113. int n = 7;
  114. while (n >= 0)
  115. {
  116. BYTE b = (BYTE)(dw >> (n * 4)) & 0x0F;
  117. if (b < 0x0A)
  118. *psz = (char)('0' + b);
  119. else
  120. *psz = (char)('A' + b - 0x0A);
  121. psz++;
  122. n--;
  123. }
  124. *psz = L'\0';
  125. return;
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // WToNum
  130. //
  131. //----------------------------------------------------------------------------
  132. DWORD WToNum( WCHAR *psz)
  133. {
  134. DWORD dwNum = 0;
  135. for (; *psz; psz++) {
  136. if (*psz>= L'0' && *psz<= L'9') {
  137. dwNum = (dwNum << 4) | (*psz - L'0');
  138. } else if (*psz>= L'A' && *psz<= L'F') {
  139. dwNum = (dwNum << 4) | (*psz - L'A' + 0x000A);
  140. } else if (*psz>= L'a' && *psz<= L'f') {
  141. dwNum = (dwNum << 4) | (*psz - L'a' + 0x000A);
  142. } else {
  143. return (0);
  144. }
  145. }
  146. return (dwNum);
  147. }
  148. //+---------------------------------------------------------------------------
  149. //
  150. // NumToW
  151. //
  152. //----------------------------------------------------------------------------
  153. void NumToW(DWORD dw, WCHAR *psz)
  154. {
  155. int n = 7;
  156. while (n >= 0)
  157. {
  158. BYTE b = (BYTE)(dw >> (n * 4)) & 0x0F;
  159. if (b < 0x0A)
  160. *psz = (WCHAR)(L'0' + b);
  161. else
  162. *psz = (WCHAR)(L'A' + b - 0x0A);
  163. psz++;
  164. n--;
  165. }
  166. *psz = L'\0';
  167. return;
  168. }
  169. //+---------------------------------------------------------------------------
  170. //
  171. // GetTopIC
  172. //
  173. //----------------------------------------------------------------------------
  174. BOOL GetTopIC(ITfDocumentMgr *pdim, ITfContext **ppic)
  175. {
  176. HRESULT hr;
  177. *ppic = NULL;
  178. if (pdim == NULL)
  179. return FALSE;
  180. hr = pdim->GetTop(ppic);
  181. return SUCCEEDED(hr) ? TRUE : FALSE;
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // AdjustAnchor
  186. //
  187. //----------------------------------------------------------------------------
  188. LONG AdjustAnchor(LONG ichAdjStart, LONG ichAdjEnd, LONG cchNew, LONG ichAnchor, BOOL fGravityRight)
  189. {
  190. int cchAdjust;
  191. // if the adjustment is entirely to the right, nothing to do
  192. if (ichAdjStart > ichAnchor)
  193. return ichAnchor;
  194. // if the adjustment was a simple replacement -- no size change -- nothing to do
  195. if ((cchAdjust = cchNew - (ichAdjEnd - ichAdjStart)) == 0)
  196. return ichAnchor;
  197. if (ichAdjStart == ichAnchor && ichAdjEnd == ichAnchor)
  198. {
  199. // inserting at the anchor pos
  200. Assert(cchAdjust > 0);
  201. if (fGravityRight)
  202. {
  203. ichAnchor += cchAdjust;
  204. }
  205. }
  206. else if (ichAdjEnd <= ichAnchor)
  207. {
  208. // the adjustment is to the left of the anchor, just add the delta
  209. ichAnchor += cchAdjust;
  210. }
  211. else if (cchAdjust < 0)
  212. {
  213. // need to slide the anchor back if it's within the deleted range of text
  214. ichAnchor = min(ichAnchor, ichAdjEnd + cchAdjust);
  215. }
  216. else // cchAdjust > 0
  217. {
  218. // there's nothing to do
  219. }
  220. return ichAnchor;
  221. }
  222. //+---------------------------------------------------------------------------
  223. //
  224. // CompareRanges
  225. //
  226. //----------------------------------------------------------------------------
  227. int CompareRanges(TfEditCookie ec, ITfRange *pRangeSrc, ITfRange *pRangeCmp)
  228. {
  229. int nRet = CR_ERROR;
  230. BOOL fEqual;
  231. LONG l;
  232. pRangeCmp->CompareEnd(ec, pRangeSrc, TF_ANCHOR_START, &l);
  233. if (l <= 0)
  234. return CR_LEFT;
  235. pRangeSrc->CompareEnd(ec, pRangeCmp, TF_ANCHOR_START, &l);
  236. if (l < 0) // incl char to right
  237. return CR_RIGHT;
  238. if (pRangeSrc->IsEqualStart(ec, pRangeCmp, TF_ANCHOR_START, &fEqual) == S_OK && fEqual &&
  239. pRangeSrc->IsEqualEnd(ec, pRangeCmp, TF_ANCHOR_END, &fEqual) == S_OK && fEqual)
  240. {
  241. return CR_EQUAL;
  242. }
  243. pRangeSrc->CompareStart(ec, pRangeCmp, TF_ANCHOR_START, &l);
  244. if (l <= 0)
  245. {
  246. pRangeSrc->CompareEnd(ec, pRangeCmp, TF_ANCHOR_END, &l);
  247. if (l < 0)
  248. return CR_RIGHTMEET;
  249. else
  250. return CR_PARTIAL;
  251. }
  252. else
  253. {
  254. pRangeSrc->CompareEnd(ec, pRangeCmp, TF_ANCHOR_END, &l);
  255. if (l < 0)
  256. return CR_INCLUSION;
  257. else
  258. return CR_LEFTMEET;
  259. }
  260. return nRet;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // GetRangeForWholeDoc
  265. //
  266. //----------------------------------------------------------------------------
  267. HRESULT GetRangeForWholeDoc(TfEditCookie ec, ITfContext *pic, ITfRange **pprange)
  268. {
  269. HRESULT hr;
  270. ITfRange *pRangeEnd = NULL;
  271. ITfRange *pRange = NULL;
  272. *pprange = NULL;
  273. if (FAILED(hr = pic->GetStart(ec,&pRange)))
  274. return hr;
  275. if (FAILED(hr = pic->GetEnd(ec,&pRangeEnd)))
  276. return hr;
  277. hr = pRange->ShiftEndToRange(ec, pRangeEnd, TF_ANCHOR_END);
  278. pRangeEnd->Release();
  279. if (SUCCEEDED(hr))
  280. *pprange = pRange;
  281. else
  282. pRange->Release();
  283. return hr;
  284. }
  285. //+---------------------------------------------------------------------------
  286. //
  287. // CompareGUIDs
  288. //
  289. //----------------------------------------------------------------------------
  290. __inline int CompUnsigned(ULONG u1, ULONG u2)
  291. {
  292. if (u1 == u2)
  293. return 0;
  294. return (u1 > u2) ? 1 : -1;
  295. }
  296. int CompareGUIDs(REFGUID guid1, REFGUID guid2)
  297. {
  298. int i;
  299. int nRet;
  300. if (nRet = CompUnsigned(guid1.Data1, guid2.Data1))
  301. return nRet;
  302. if (nRet = CompUnsigned(guid1.Data2, guid2.Data2))
  303. return nRet;
  304. if (nRet = CompUnsigned(guid1.Data3, guid2.Data3))
  305. return nRet;
  306. for (i = 0; i < 8; i++)
  307. {
  308. if (nRet = CompUnsigned(guid1.Data4[i], guid2.Data4[i]))
  309. return nRet;
  310. }
  311. return 0;
  312. }
  313. //+---------------------------------------------------------------------------
  314. //
  315. // IsDisabledTextServices
  316. //
  317. //----------------------------------------------------------------------------
  318. BOOL IsDisabledTextServices(void)
  319. {
  320. static const TCHAR c_szCTFKey[] = TEXT("SOFTWARE\\Microsoft\\CTF");
  321. static const TCHAR c_szDiableTim[] = TEXT("Disable Thread Input Manager");
  322. HKEY hKey;
  323. if (RegOpenKey(HKEY_CURRENT_USER, c_szCTFKey, &hKey) == ERROR_SUCCESS)
  324. {
  325. DWORD cb;
  326. DWORD dwDisableTim = 0;
  327. cb = sizeof(DWORD);
  328. RegQueryValueEx(hKey,
  329. c_szDiableTim,
  330. NULL,
  331. NULL,
  332. (LPBYTE)&dwDisableTim,
  333. &cb);
  334. RegCloseKey(hKey);
  335. //
  336. // Ctfmon disabling flag is set, so return fail CreateInstance.
  337. //
  338. if (dwDisableTim)
  339. return TRUE;
  340. }
  341. return FALSE;
  342. }
  343. //+---------------------------------------------------------------------------
  344. //
  345. // IsTIPClsidEnabled
  346. //
  347. //----------------------------------------------------------------------------
  348. const TCHAR c_szLanguageProfile[] = TEXT("\\LanguageProfile");
  349. const TCHAR c_szCTFTipPath[] = TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\");
  350. BOOL IsTIPClsidEnabled(
  351. HKEY hkeyTop,
  352. LPTSTR szTipClsid,
  353. BOOL *bExistEnable)
  354. {
  355. BOOL bRet = FALSE;
  356. HKEY hkeyTipLang;
  357. HKEY hkeyTipLangid;
  358. HKEY hkeyTipGuid;
  359. UINT uIndex;
  360. UINT uIndex2;
  361. DWORD cb;
  362. DWORD cchLangid;
  363. DWORD cchGuid;
  364. DWORD dwEnableTIP = 0;
  365. LPTSTR pszGuid;
  366. LPTSTR pszLangid;
  367. TCHAR szTIPLangid[15];
  368. TCHAR szTIPGuid[128];
  369. TCHAR szTIPClsidLang[MAX_PATH];
  370. FILETIME lwt;
  371. UINT uLangidLen;
  372. UINT uGuidLen;
  373. StringCchCopy(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szCTFTipPath);
  374. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), szTipClsid);
  375. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szLanguageProfile);
  376. pszLangid = szTIPClsidLang + lstrlen(szTIPClsidLang);
  377. uLangidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
  378. if (RegOpenKeyEx(hkeyTop,
  379. szTIPClsidLang, 0,
  380. KEY_READ, &hkeyTipLang) != ERROR_SUCCESS)
  381. {
  382. goto Exit;
  383. }
  384. for (uIndex = 0; bRet == FALSE; uIndex++)
  385. {
  386. cchLangid = sizeof(szTIPLangid) / sizeof(TCHAR);
  387. if (RegEnumKeyEx(hkeyTipLang, uIndex,
  388. szTIPLangid, &cchLangid,
  389. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  390. {
  391. break;
  392. }
  393. if (cchLangid != 10)
  394. {
  395. // string langid subkeys should be like 0x00000409
  396. continue;
  397. }
  398. if (uLangidLen > (cchLangid + 1))
  399. {
  400. StringCchCopy(pszLangid, uLangidLen, TEXT("\\"));
  401. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), szTIPLangid);
  402. }
  403. if (RegOpenKeyEx(hkeyTop,
  404. szTIPClsidLang, 0,
  405. KEY_READ, &hkeyTipLangid) != ERROR_SUCCESS)
  406. {
  407. continue;
  408. }
  409. pszGuid = szTIPClsidLang + lstrlen(szTIPClsidLang);
  410. uGuidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
  411. for (uIndex2 = 0; bRet == FALSE; uIndex2++)
  412. {
  413. cchGuid = sizeof(szTIPGuid) / sizeof(TCHAR);
  414. if (RegEnumKeyEx(hkeyTipLangid, uIndex2,
  415. szTIPGuid, &cchGuid,
  416. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  417. {
  418. break;
  419. }
  420. if (cchGuid != 38)
  421. {
  422. continue;
  423. }
  424. if (uGuidLen > (cchGuid + 1))
  425. {
  426. StringCchCopy(pszGuid, uGuidLen, TEXT("\\"));
  427. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), szTIPGuid);
  428. }
  429. if (RegOpenKeyEx(hkeyTop,
  430. szTIPClsidLang, 0,
  431. KEY_READ, &hkeyTipGuid) == ERROR_SUCCESS)
  432. {
  433. cb = sizeof(DWORD);
  434. if (RegQueryValueEx(hkeyTipGuid,
  435. TEXT("Enable"),
  436. NULL,
  437. NULL,
  438. (LPBYTE)&dwEnableTIP,
  439. &cb) == ERROR_SUCCESS)
  440. {
  441. *bExistEnable = TRUE;
  442. if (dwEnableTIP)
  443. {
  444. bRet = TRUE;
  445. }
  446. }
  447. else if (hkeyTop == HKEY_LOCAL_MACHINE)
  448. {
  449. // Default is the enabled status on HKLM
  450. *bExistEnable = TRUE;
  451. bRet = TRUE;
  452. }
  453. else
  454. {
  455. *bExistEnable = FALSE;
  456. }
  457. RegCloseKey(hkeyTipGuid);
  458. }
  459. }
  460. RegCloseKey(hkeyTipLangid);
  461. }
  462. RegCloseKey(hkeyTipLang);
  463. Exit:
  464. return bRet;
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // NoTipsInstalled
  469. //
  470. //----------------------------------------------------------------------------
  471. // grab CLSID_SOFTKBDIMX here
  472. #include <initguid.h>
  473. #include "SoftKbd.h"
  474. BOOL NoTipsInstalled(BOOL *pfOnlyTranslationRunning)
  475. {
  476. const CLSID CLSID_SapiLayr = {0xdcbd6fa8, 0x032f, 0x11d3, {0xb5, 0xb1, 0x00, 0xc0, 0x4f, 0xc3, 0x24, 0xa1}};
  477. static const TCHAR c_szSpeechRecognizersKey[] = TEXT("Software\\Microsoft\\Speech\\Recognizers\\Tokens");
  478. static const TCHAR c_szCategory[] = TEXT("\\Category\\Category");
  479. BOOL bRet = TRUE;
  480. BOOL bExistEnable;
  481. HKEY hkeyTip;
  482. HKEY hkeyTipSub;
  483. UINT uIndex;
  484. DWORD dwSubKeys;
  485. DWORD cchClsid;
  486. CLSID clsidTip;
  487. TCHAR szTipClsid[128];
  488. TCHAR szTipClsidPath[MAX_PATH];
  489. FILETIME lwt;
  490. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  491. TEXT("Software\\Microsoft\\CTF\\TIP"),
  492. 0, KEY_READ, &hkeyTip) != ERROR_SUCCESS)
  493. {
  494. goto Exit;
  495. }
  496. // enum through all the TIP subkeys
  497. for (uIndex = 0; TRUE; uIndex++)
  498. {
  499. bExistEnable = FALSE;
  500. cchClsid = sizeof(szTipClsid) / sizeof(TCHAR);
  501. if (RegEnumKeyEx(hkeyTip, uIndex,
  502. szTipClsid, &cchClsid,
  503. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  504. {
  505. break;
  506. }
  507. if (cchClsid != 38)
  508. {
  509. // string clsid subkeys should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  510. continue;
  511. }
  512. StringCchCopy(szTipClsidPath, ARRAYSIZE(szTipClsidPath), szTipClsid);
  513. // we want subkey\Language Profiles key
  514. StringCchCat(szTipClsidPath, ARRAYSIZE(szTipClsidPath), c_szLanguageProfile);
  515. // is this subkey a tip?
  516. if (RegOpenKeyEx(hkeyTip,
  517. szTipClsidPath, 0,
  518. KEY_READ, &hkeyTipSub) == ERROR_SUCCESS)
  519. {
  520. RegCloseKey(hkeyTipSub);
  521. // it's a tip, get the clsid
  522. if (!StringAToCLSID(szTipClsid, &clsidTip))
  523. continue;
  524. // special case certain known tips
  525. if (IsEqualGUID(clsidTip, CLSID_SapiLayr))
  526. {
  527. //
  528. // This is SAPI TIP and need to handle it specially, since sptip has
  529. // a default option as the enabled status.
  530. //
  531. if (!IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
  532. {
  533. //
  534. // If SPTIP has enable registry setting on HKCU with the disabled
  535. // speech tip, we assume user intentionally disable it.
  536. //
  537. if (bExistEnable)
  538. continue;
  539. }
  540. // this is the sapi tip, which is always installed
  541. // but it will not activate if sapi is not installed
  542. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  543. c_szSpeechRecognizersKey, 0,
  544. KEY_READ, &hkeyTipSub) != ERROR_SUCCESS)
  545. {
  546. continue; // this tip doesn't count
  547. }
  548. // need 1 or more subkeys for sapi to be truely installed...whistler has a Tokens with nothing underneath
  549. if (RegQueryInfoKey(hkeyTipSub,
  550. NULL, NULL, NULL, &dwSubKeys, NULL,
  551. NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  552. {
  553. dwSubKeys = 0; // assume no sub keys on failure
  554. }
  555. RegCloseKey(hkeyTipSub);
  556. if (dwSubKeys != 0)
  557. {
  558. bRet = FALSE;
  559. break;
  560. }
  561. }
  562. else if (IsEqualGUID(clsidTip, CLSID_SoftkbdIMX))
  563. {
  564. // don't count the softkbd, it is disabled until another tip
  565. // enables it
  566. continue;
  567. }
  568. else if(IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
  569. {
  570. bRet = FALSE;
  571. break;
  572. }
  573. else if (!bExistEnable)
  574. {
  575. if(IsTIPClsidEnabled(HKEY_LOCAL_MACHINE, szTipClsid, &bExistEnable))
  576. {
  577. bRet = FALSE;
  578. break;
  579. }
  580. }
  581. }
  582. }
  583. RegCloseKey(hkeyTip);
  584. Exit:
  585. if (bRet == TRUE && pfOnlyTranslationRunning != NULL) // skip the check for aimm, which passes in NULL pfOnlyTranslationRunning
  586. {
  587. // word10 compart: check for bookshelf's translation service
  588. // it uses cicero, but does not formally register itself as a tip.
  589. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  590. TEXT("SOFTWARE\\Microsoft\\Microsoft Reference\\Bilinguals 1.0"),
  591. 0, KEY_READ, &hkeyTip) == ERROR_SUCCESS)
  592. {
  593. *pfOnlyTranslationRunning = TRUE;
  594. bRet = FALSE;
  595. RegCloseKey(hkeyTip);
  596. }
  597. }
  598. return bRet;
  599. }
  600. //+---------------------------------------------------------------------------
  601. //
  602. // RunningOnWow64
  603. //
  604. //----------------------------------------------------------------------------
  605. BOOL RunningOnWow64()
  606. {
  607. BOOL bOnWow64 = FALSE;
  608. // check to make sure that we are running on wow64
  609. LONG lStatus;
  610. ULONG_PTR Wow64Info;
  611. typedef BOOL (WINAPI *PFN_NTQUERYINFORMATIONPROCESS)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
  612. PFN_NTQUERYINFORMATIONPROCESS pfnNtQueryInformationProcess;
  613. HINSTANCE hLibNtDll = NULL;
  614. hLibNtDll = GetSystemModuleHandle( TEXT("ntdll.dll") );
  615. if (hLibNtDll)
  616. {
  617. pfnNtQueryInformationProcess = (PFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(hLibNtDll, TEXT("NtQueryInformationProcess"));
  618. if (pfnNtQueryInformationProcess)
  619. {
  620. lStatus = pfnNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, &Wow64Info, sizeof(Wow64Info), NULL);
  621. if (NT_SUCCESS(lStatus) && Wow64Info)
  622. {
  623. bOnWow64 = TRUE;
  624. }
  625. }
  626. }
  627. return bOnWow64;
  628. }
  629. //+---------------------------------------------------------------------------
  630. //
  631. // GetSystemDefaultHKL
  632. //
  633. //----------------------------------------------------------------------------
  634. HKL GetSystemDefaultHKL()
  635. {
  636. HKL hkl;
  637. if (SystemParametersInfo( SPI_GETDEFAULTINPUTLANG, 0, &hkl, 0))
  638. return hkl;
  639. return GetKeyboardLayout(0);
  640. }
  641. //+---------------------------------------------------------------------------
  642. //
  643. // IsDisabledCUAS
  644. //
  645. //----------------------------------------------------------------------------
  646. BOOL IsDisabledCUAS()
  647. {
  648. static const TCHAR c_szCtfShared[] = TEXT("SOFTWARE\\Microsoft\\CTF\\SystemShared");
  649. static const TCHAR c_szCUAS[] = TEXT("CUAS");
  650. DWORD cb;
  651. HKEY hkeyCTF;
  652. BOOL bRet = TRUE;
  653. DWORD dwEnableCUAS = 0;
  654. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) == ERROR_SUCCESS)
  655. {
  656. cb = sizeof(DWORD);
  657. RegQueryValueEx(hkeyCTF,
  658. c_szCUAS,
  659. NULL,
  660. NULL,
  661. (LPBYTE)&dwEnableCUAS,
  662. &cb);
  663. if (dwEnableCUAS)
  664. bRet = FALSE;
  665. RegCloseKey(hkeyCTF);
  666. }
  667. return bRet;
  668. }
  669. //+---------------------------------------------------------------------------
  670. //
  671. // IsInstalledEALangPack
  672. //
  673. //----------------------------------------------------------------------------
  674. BOOL IsInstalledEALangPack()
  675. {
  676. static const TCHAR c_szLangGroup[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Language Groups");
  677. static const TCHAR c_szLangJPN[] = TEXT("7");
  678. BOOL bRet = FALSE;
  679. HKEY hkeyLangGroup;
  680. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  681. c_szLangGroup,
  682. 0,
  683. KEY_READ,
  684. &hkeyLangGroup) == ERROR_SUCCESS)
  685. {
  686. DWORD cb;
  687. TCHAR szLangInstall[10];
  688. cb = sizeof(szLangInstall);
  689. //
  690. // The checking of Japan Language is enough to know EA language pack
  691. // installation.
  692. //
  693. if (RegQueryValueEx(hkeyLangGroup,
  694. c_szLangJPN,
  695. NULL,
  696. NULL,
  697. (LPBYTE)szLangInstall,
  698. &cb) == ERROR_SUCCESS)
  699. {
  700. if (szLangInstall[0] != 0)
  701. return TRUE;
  702. }
  703. RegCloseKey(hkeyLangGroup);
  704. }
  705. return bRet;
  706. }
  707. //+---------------------------------------------------------------------------
  708. //
  709. // SetDisableCUAS
  710. //
  711. //----------------------------------------------------------------------------
  712. void SetDisableCUAS(
  713. BOOL bDisableCUAS)
  714. {
  715. static const TCHAR c_szCtfShared[] = TEXT("SOFTWARE\\Microsoft\\CTF\\SystemShared");
  716. static const TCHAR c_szIMM[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IMM");
  717. static const TCHAR c_szLoadIMM[] = TEXT("LoadIMM");
  718. static const TCHAR c_szIMMFile[] = TEXT("IME File");
  719. static const TCHAR c_szIMMFileName[]= TEXT("msctfime.ime");
  720. static const TCHAR c_szCUAS[] = TEXT("CUAS");
  721. HKEY hkeyIMM;
  722. HKEY hkeyCTF;
  723. DWORD cb = sizeof(DWORD);
  724. DWORD dwIMM32, dwCUAS;
  725. if (bDisableCUAS)
  726. dwIMM32 = dwCUAS = 0;
  727. else
  728. dwIMM32 = dwCUAS = 1;
  729. if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szIMM, &hkeyIMM) != ERROR_SUCCESS)
  730. {
  731. hkeyIMM = NULL;
  732. }
  733. if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) != ERROR_SUCCESS)
  734. {
  735. hkeyCTF = NULL;
  736. }
  737. if (!bDisableCUAS)
  738. {
  739. //
  740. // Turn on LoadIMM and CUAS flags
  741. //
  742. if (hkeyIMM)
  743. {
  744. RegSetValueEx(hkeyIMM,
  745. c_szIMMFile,
  746. 0,
  747. REG_SZ,
  748. (LPBYTE)c_szIMMFileName,
  749. (lstrlen(c_szIMMFileName) + 1) * sizeof(TCHAR));
  750. }
  751. }
  752. else
  753. {
  754. //
  755. // Turn off LoadIMM and CUAS flags
  756. //
  757. BOOL bEALang = IsInstalledEALangPack();
  758. if (bEALang)
  759. {
  760. dwIMM32 = 1;
  761. }
  762. }
  763. if (hkeyIMM)
  764. {
  765. RegSetValueEx(hkeyIMM,
  766. c_szLoadIMM,
  767. 0,
  768. REG_DWORD,
  769. (LPBYTE)&dwIMM32,
  770. cb);
  771. }
  772. if (hkeyCTF)
  773. {
  774. RegSetValueEx(hkeyCTF,
  775. c_szCUAS,
  776. 0,
  777. REG_DWORD,
  778. (LPBYTE)&dwCUAS,
  779. cb);
  780. }
  781. if (hkeyIMM)
  782. RegCloseKey(hkeyIMM);
  783. if (hkeyCTF)
  784. RegCloseKey(hkeyCTF);
  785. }
  786. //+---------------------------------------------------------------------------
  787. //
  788. // RebootTheSystem
  789. //
  790. //----------------------------------------------------------------------------
  791. void RebootTheSystem()
  792. {
  793. HANDLE Token = NULL;
  794. ULONG ReturnLength, Index;
  795. PTOKEN_PRIVILEGES NewState = NULL;
  796. PTOKEN_PRIVILEGES OldState = NULL;
  797. BOOL Result;
  798. // Only allow admin privilege user for system reboot.
  799. if (!IsAdminPrivilege())
  800. return;
  801. Result = OpenProcessToken( GetCurrentProcess(),
  802. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  803. &Token );
  804. if (Result)
  805. {
  806. ReturnLength = 4096;
  807. NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  808. OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  809. Result = (BOOL)((NewState != NULL) && (OldState != NULL));
  810. if (Result)
  811. {
  812. Result = GetTokenInformation( Token, // TokenHandle
  813. TokenPrivileges, // TokenInformationClass
  814. NewState, // TokenInformation
  815. ReturnLength, // TokenInformationLength
  816. &ReturnLength ); // ReturnLength
  817. if (Result)
  818. {
  819. //
  820. // Set the state settings so that all privileges are
  821. // enabled...
  822. //
  823. if (NewState->PrivilegeCount > 0)
  824. {
  825. for (Index = 0; Index < NewState->PrivilegeCount; Index++)
  826. {
  827. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  828. }
  829. }
  830. Result = AdjustTokenPrivileges( Token, // TokenHandle
  831. FALSE, // DisableAllPrivileges
  832. NewState, // NewState
  833. ReturnLength, // BufferLength
  834. OldState, // PreviousState
  835. &ReturnLength ); // ReturnLength
  836. if (Result)
  837. {
  838. ExitWindowsEx(EWX_REBOOT, 0);
  839. AdjustTokenPrivileges( Token,
  840. FALSE,
  841. OldState,
  842. 0,
  843. NULL,
  844. NULL );
  845. }
  846. }
  847. }
  848. }
  849. if (NewState != NULL)
  850. {
  851. LocalFree(NewState);
  852. }
  853. if (OldState != NULL)
  854. {
  855. LocalFree(OldState);
  856. }
  857. if (Token != NULL)
  858. {
  859. CloseHandle(Token);
  860. }
  861. }
  862. //+---------------------------------------------------------------------------
  863. //
  864. // IsAdminPrivilege
  865. //
  866. //----------------------------------------------------------------------------
  867. BOOL IsAdminPrivilege()
  868. {
  869. BOOL bAdmin = FALSE;
  870. BOOL bResult = FALSE;
  871. BOOL fSIDCreated = FALSE;
  872. HANDLE hToken = NULL;
  873. PSID AdminSid;
  874. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  875. fSIDCreated = AllocateAndInitializeSid(&NtAuthority,
  876. 2,
  877. SECURITY_BUILTIN_DOMAIN_RID,
  878. DOMAIN_ALIAS_RID_ADMINS,
  879. 0, 0, 0, 0, 0, 0,
  880. &AdminSid);
  881. if (!fSIDCreated)
  882. return FALSE;
  883. bResult = OpenProcessToken(GetCurrentProcess(),
  884. TOKEN_QUERY,
  885. &hToken );
  886. if (bResult)
  887. {
  888. DWORD dwSize = 0;
  889. TOKEN_GROUPS *pTokenGrpInfo;
  890. GetTokenInformation(hToken,
  891. TokenGroups,
  892. NULL,
  893. dwSize,
  894. &dwSize);
  895. if (dwSize)
  896. pTokenGrpInfo = (PTOKEN_GROUPS) LocalAlloc(LPTR, dwSize);
  897. else
  898. pTokenGrpInfo = NULL;
  899. if (pTokenGrpInfo && GetTokenInformation(hToken,
  900. TokenGroups,
  901. pTokenGrpInfo,
  902. dwSize,
  903. &dwSize))
  904. {
  905. UINT i;
  906. for (i = 0; i < pTokenGrpInfo->GroupCount; i++)
  907. {
  908. if (EqualSid(pTokenGrpInfo->Groups[i].Sid, AdminSid) &&
  909. (pTokenGrpInfo->Groups[i].Attributes & SE_GROUP_ENABLED))
  910. {
  911. bAdmin = TRUE;
  912. break;
  913. }
  914. }
  915. }
  916. if (pTokenGrpInfo)
  917. LocalFree(pTokenGrpInfo);
  918. }
  919. if (hToken)
  920. CloseHandle(hToken);
  921. if (AdminSid)
  922. FreeSid(AdminSid);
  923. return bAdmin;
  924. }
  925. //+---------------------------------------------------------------------------
  926. //
  927. // IsInteractiveUserLogon
  928. //
  929. //----------------------------------------------------------------------------
  930. BOOL IsInteractiveUserLogon()
  931. {
  932. PSID InteractiveSid;
  933. BOOL bCheckSucceeded;
  934. BOOL bAmInteractive = FALSE;
  935. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  936. if (!AllocateAndInitializeSid(&NtAuthority,
  937. 1,
  938. SECURITY_INTERACTIVE_RID,
  939. 0, 0, 0, 0, 0, 0, 0,
  940. &InteractiveSid))
  941. {
  942. return FALSE;
  943. }
  944. //
  945. // This checking is for logged on user or not. So we can blcok running
  946. // ctfmon.exe process from non-authorized user.
  947. //
  948. bCheckSucceeded = CheckTokenMembership(NULL,
  949. InteractiveSid,
  950. &bAmInteractive);
  951. if (InteractiveSid)
  952. FreeSid(InteractiveSid);
  953. return (bCheckSucceeded && bAmInteractive);
  954. }
  955. //+---------------------------------------------------------------------------
  956. //
  957. // GetSystemModuleHandle
  958. //
  959. //----------------------------------------------------------------------------
  960. HMODULE GetSystemModuleHandle(LPCSTR lpModuleName)
  961. {
  962. CicSystemModulePath path;
  963. if (!path.Init(lpModuleName))
  964. return NULL;
  965. return GetModuleHandle(path.GetPath());
  966. }
  967. //+---------------------------------------------------------------------------
  968. //
  969. // LoadSystemLibrary
  970. //
  971. //----------------------------------------------------------------------------
  972. HMODULE LoadSystemLibrary(LPCSTR lpModuleName)
  973. {
  974. CicSystemModulePath path;
  975. if (!path.Init(lpModuleName))
  976. return NULL;
  977. return LoadLibrary(path.GetPath());
  978. }
  979. //+---------------------------------------------------------------------------
  980. //
  981. // LoadSystemLibraryEx
  982. //
  983. //----------------------------------------------------------------------------
  984. HMODULE LoadSystemLibraryEx(LPCSTR lpModuleName, HANDLE hFile, DWORD dwFlags)
  985. {
  986. CicSystemModulePath path;
  987. if (!path.Init(lpModuleName))
  988. return NULL;
  989. return LoadLibraryEx(path.GetPath(), hFile, dwFlags);
  990. }
  991. //+---------------------------------------------------------------------------
  992. //
  993. // GetSystemModuleHandleW
  994. //
  995. //----------------------------------------------------------------------------
  996. HMODULE GetSystemModuleHandleW(LPCWSTR lpModuleName)
  997. {
  998. CicSystemModulePathW path;
  999. if (!path.Init(lpModuleName))
  1000. return NULL;
  1001. return GetModuleHandleW(path.GetPath());
  1002. }
  1003. //+---------------------------------------------------------------------------
  1004. //
  1005. // LoadSystemLibraryW
  1006. //
  1007. //----------------------------------------------------------------------------
  1008. HMODULE LoadSystemLibraryW(LPCWSTR lpModuleName)
  1009. {
  1010. CicSystemModulePathW path;
  1011. if (!path.Init(lpModuleName))
  1012. return NULL;
  1013. return LoadLibraryW(path.GetPath());
  1014. }
  1015. //+---------------------------------------------------------------------------
  1016. //
  1017. // LoadSystemLibraryEx
  1018. //
  1019. //----------------------------------------------------------------------------
  1020. HMODULE LoadSystemLibraryExW(LPCWSTR lpModuleName, HANDLE hFile, DWORD dwFlags)
  1021. {
  1022. CicSystemModulePathW path;
  1023. if (!path.Init(lpModuleName))
  1024. return NULL;
  1025. return LoadLibraryExW(path.GetPath(), hFile, dwFlags);
  1026. }
  1027. //+---------------------------------------------------------------------------
  1028. //
  1029. // FullPathExec
  1030. //
  1031. //----------------------------------------------------------------------------
  1032. BOOL FullPathExec(
  1033. LPCSTR pszAppName,
  1034. LPCSTR pszCmdLine,
  1035. WORD wShowWindow,
  1036. BOOL fWinDir)
  1037. {
  1038. char szCmdLine[MAX_PATH + 1];
  1039. CicSystemModulePath fullpath;
  1040. fullpath.Init(pszAppName, fWinDir);
  1041. if (!fullpath.GetLength())
  1042. return FALSE;
  1043. //
  1044. // CreateProcess() wants an out buffer for CmdLine. So we just have it in
  1045. // stack.
  1046. //
  1047. StringCchCopy(szCmdLine, ARRAYSIZE(szCmdLine), pszCmdLine);
  1048. PROCESS_INFORMATION pi;
  1049. STARTUPINFO si = {0};
  1050. si.cb = sizeof(STARTUPINFO);
  1051. si.dwFlags = STARTF_USESHOWWINDOW;
  1052. si.wShowWindow = (WORD)wShowWindow;
  1053. return CreateProcess(fullpath.GetPath(),
  1054. szCmdLine,
  1055. NULL,
  1056. NULL,
  1057. FALSE,
  1058. NORMAL_PRIORITY_CLASS,
  1059. NULL,
  1060. NULL,
  1061. &si,
  1062. &pi);
  1063. }
  1064. //+---------------------------------------------------------------------------
  1065. //
  1066. // RunCPLs
  1067. //
  1068. //----------------------------------------------------------------------------
  1069. BOOL RunCPLSetting(
  1070. LPTSTR pCmdLine)
  1071. {
  1072. const TCHAR c_szRundll32[] = TEXT("Rundll32.exe");
  1073. if (!pCmdLine)
  1074. return FALSE;
  1075. return FullPathExec(c_szRundll32,
  1076. pCmdLine,
  1077. SW_SHOWMINNOACTIVE,
  1078. FALSE);
  1079. }
  1080. //+---------------------------------------------------------------------------
  1081. //
  1082. // DllShutdownInProgress
  1083. //
  1084. //+---------------------------------------------------------------------------
  1085. typedef BYTE (*PFNRTLDLLSHUTDOWININPROGRESS)(void);
  1086. BOOL DllShutdownInProgress()
  1087. {
  1088. BOOL fRet = FALSE;
  1089. static PFNRTLDLLSHUTDOWININPROGRESS pfn = NULL;
  1090. if (!pfn)
  1091. {
  1092. HINSTANCE hInst;
  1093. hInst= GetSystemModuleHandle("ntdll.dll");
  1094. if (hInst)
  1095. {
  1096. pfn = (PFNRTLDLLSHUTDOWININPROGRESS)GetProcAddress(hInst,
  1097. "RtlDllShutdownInProgress");
  1098. }
  1099. }
  1100. if (pfn)
  1101. fRet = pfn() ? TRUE : FALSE;
  1102. return fRet;
  1103. }