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.

1641 lines
42 KiB

  1. //
  2. // Include Files.
  3. //
  4. #include "input.h"
  5. #include <regstr.h>
  6. #include "util.h"
  7. #include "external.h"
  8. #include "msctf.h"
  9. #include "inputdlg.h"
  10. #define CLSID_STRLEN 38
  11. const TCHAR c_szSetupKey[] = TEXT("System\\Setup");
  12. const TCHAR c_szSetupInProgress[] = TEXT("SystemSetupInProgress");
  13. const TCHAR c_szLangBarSetting[] = TEXT("SOFTWARE\\Microsoft\\CTF\\LangBar");
  14. const TCHAR c_szShowStatus[] = TEXT("ShowStatus");
  15. const TCHAR c_szCtf[] = TEXT("SOFTWARE\\Microsoft\\CTF");
  16. const TCHAR c_szCtfShared[] = TEXT("SOFTWARE\\Microsoft\\CTF\\SystemShared");
  17. const TCHAR c_szDisableTim[] = TEXT("Disable Thread Input Manager");
  18. const TCHAR c_szLangBarSetting_DefUser[] = TEXT(".DEFAULT\\SOFTWARE\\Microsoft\\CTF\\LangBar");
  19. const TCHAR c_szLangGroup[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Language Groups");
  20. const TCHAR c_szLangJPN[] = TEXT("7");
  21. const TCHAR c_szLanguageProfile[] = TEXT("\\LanguageProfile");
  22. //
  23. // Cicero Unaware Application Support const strings.
  24. //
  25. const TCHAR c_szIMM[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IMM");
  26. const TCHAR c_szLoadIMM[] = TEXT("LoadIMM");
  27. const TCHAR c_szIMMFile[] = TEXT("IME File");
  28. const TCHAR c_szIMMFileName[] = TEXT("msctfime.ime");
  29. const TCHAR c_szCUAS[] = TEXT("CUAS");
  30. ////////////////////////////////////////////////////////////////////////////
  31. //
  32. // CLSIDToStringA
  33. //
  34. // Converts a CLSID to an mbcs string.
  35. //
  36. ////////////////////////////////////////////////////////////////////////////
  37. static const BYTE GuidMap[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
  38. 8, 9, '-', 10, 11, 12, 13, 14, 15};
  39. static const char szDigits[] = "0123456789ABCDEF";
  40. BOOL CLSIDToStringA(REFGUID refGUID, char *pchA)
  41. {
  42. int i;
  43. char *p = pchA;
  44. const BYTE * pBytes = (const BYTE *) refGUID;
  45. *p++ = '{';
  46. for (i = 0; i < sizeof(GuidMap); i++)
  47. {
  48. if (GuidMap[i] == '-')
  49. {
  50. *p++ = '-';
  51. }
  52. else
  53. {
  54. *p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
  55. *p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
  56. }
  57. }
  58. *p++ = '}';
  59. *p = '\0';
  60. return TRUE;
  61. }
  62. ////////////////////////////////////////////////////////////////////////////
  63. //
  64. // TransNum
  65. //
  66. // Converts a number string to a dword value (in hex).
  67. //
  68. ////////////////////////////////////////////////////////////////////////////
  69. DWORD TransNum(
  70. LPTSTR lpsz)
  71. {
  72. DWORD dw = 0L;
  73. TCHAR c;
  74. while (*lpsz)
  75. {
  76. c = *lpsz++;
  77. if (c >= TEXT('A') && c <= TEXT('F'))
  78. {
  79. c -= TEXT('A') - 0xa;
  80. }
  81. else if (c >= TEXT('0') && c <= TEXT('9'))
  82. {
  83. c -= TEXT('0');
  84. }
  85. else if (c >= TEXT('a') && c <= TEXT('f'))
  86. {
  87. c -= TEXT('a') - 0xa;
  88. }
  89. else
  90. {
  91. break;
  92. }
  93. dw *= 0x10;
  94. dw += c;
  95. }
  96. return (dw);
  97. }
  98. BOOL IsOSPlatform(DWORD dwOS)
  99. {
  100. BOOL bRet;
  101. static OSVERSIONINFOA s_osvi;
  102. static BOOL s_bVersionCached = FALSE;
  103. if (!s_bVersionCached)
  104. {
  105. s_bVersionCached = TRUE;
  106. s_osvi.dwOSVersionInfoSize = sizeof(s_osvi);
  107. GetVersionExA(&s_osvi);
  108. }
  109. switch (dwOS)
  110. {
  111. case OS_WINDOWS:
  112. bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId);
  113. break;
  114. case OS_NT:
  115. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId);
  116. break;
  117. case OS_WIN95:
  118. bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId &&
  119. s_osvi.dwMajorVersion >= 4);
  120. break;
  121. case OS_NT4:
  122. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
  123. (s_osvi.dwMajorVersion >= 4 && s_osvi.dwMajorVersion < 5));
  124. break;
  125. case OS_NT5:
  126. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
  127. s_osvi.dwMajorVersion >= 5);
  128. break;
  129. case OS_NT51:
  130. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
  131. s_osvi.dwMajorVersion >= 5 && s_osvi.dwMinorVersion >= 0x00000001);
  132. break;
  133. default:
  134. bRet = FALSE;
  135. break;
  136. }
  137. return bRet;
  138. }
  139. ////////////////////////////////////////////////////////////////////////////
  140. //
  141. // MirrorBitmapInDC
  142. //
  143. ////////////////////////////////////////////////////////////////////////////
  144. void MirrorBitmapInDC(
  145. HDC hdc,
  146. HBITMAP hbmOrig)
  147. {
  148. HDC hdcMem;
  149. HBITMAP hbm;
  150. BITMAP bm;
  151. if (!GetObject(hbmOrig, sizeof(BITMAP), &bm))
  152. {
  153. return;
  154. }
  155. hdcMem = CreateCompatibleDC(hdc);
  156. if (!hdcMem)
  157. {
  158. return;
  159. }
  160. hbm = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight);
  161. if (!hbm)
  162. {
  163. DeleteDC(hdcMem);
  164. return;
  165. }
  166. //
  167. // Flip the bitmap.
  168. //
  169. SelectObject(hdcMem, hbm);
  170. SetLayout(hdcMem, LAYOUT_RTL);
  171. BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdc, 0, 0, SRCCOPY);
  172. SetLayout(hdcMem, 0);
  173. //
  174. // The offset by 1 is to solve the off-by-one problem.
  175. //
  176. BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 1, 0, SRCCOPY);
  177. DeleteDC(hdcMem);
  178. DeleteObject(hbm);
  179. }
  180. ////////////////////////////////////////////////////////////////////////////
  181. //
  182. // IsSetupMode
  183. //
  184. // Look into the registry if we are currently in setup mode.
  185. //
  186. ////////////////////////////////////////////////////////////////////////////
  187. BOOL IsSetupMode()
  188. {
  189. HKEY hKey;
  190. DWORD cb;
  191. DWORD fSystemSetupInProgress;
  192. //
  193. // Open the registry key used by setup
  194. //
  195. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  196. c_szSetupKey,
  197. 0,
  198. KEY_READ,
  199. &hKey) != ERROR_SUCCESS)
  200. {
  201. return (FALSE);
  202. }
  203. //
  204. // Query for the value indicating that we are in setup.
  205. //
  206. cb = sizeof(fSystemSetupInProgress);
  207. if (RegQueryValueEx(hKey,
  208. c_szSetupInProgress,
  209. NULL,
  210. NULL,
  211. (LPBYTE)&fSystemSetupInProgress,
  212. &cb) != ERROR_SUCCESS)
  213. {
  214. RegCloseKey(hKey);
  215. return (FALSE);
  216. }
  217. //
  218. // Clean up
  219. //
  220. RegCloseKey(hKey);
  221. //
  222. // Check the value
  223. //
  224. if (fSystemSetupInProgress)
  225. {
  226. return (TRUE);
  227. }
  228. return FALSE;
  229. }
  230. ////////////////////////////////////////////////////////////////////////////
  231. //
  232. // IsAdminPrivilegeUser
  233. //
  234. ////////////////////////////////////////////////////////////////////////////
  235. BOOL IsAdminPrivilegeUser()
  236. {
  237. BOOL bAdmin = FALSE;
  238. BOOL bResult = FALSE;
  239. BOOL fSIDCreated = FALSE;
  240. HANDLE hToken = NULL;
  241. PSID AdminSid;
  242. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  243. fSIDCreated = AllocateAndInitializeSid(&NtAuthority,
  244. 2,
  245. SECURITY_BUILTIN_DOMAIN_RID,
  246. DOMAIN_ALIAS_RID_ADMINS,
  247. 0, 0, 0, 0, 0, 0,
  248. &AdminSid);
  249. if (!fSIDCreated)
  250. return FALSE;
  251. bResult = OpenProcessToken(GetCurrentProcess(),
  252. TOKEN_QUERY,
  253. &hToken );
  254. if (bResult)
  255. {
  256. DWORD dwSize = 0;
  257. TOKEN_GROUPS *pTokenGrpInfo;
  258. GetTokenInformation(hToken,
  259. TokenGroups,
  260. NULL,
  261. dwSize,
  262. &dwSize);
  263. if (dwSize)
  264. pTokenGrpInfo = (PTOKEN_GROUPS) LocalAlloc(LPTR, dwSize);
  265. else
  266. pTokenGrpInfo = NULL;
  267. if (pTokenGrpInfo && GetTokenInformation(hToken,
  268. TokenGroups,
  269. pTokenGrpInfo,
  270. dwSize,
  271. &dwSize))
  272. {
  273. UINT i;
  274. for (i = 0; i < pTokenGrpInfo->GroupCount; i++)
  275. {
  276. if (EqualSid(pTokenGrpInfo->Groups[i].Sid, AdminSid) &&
  277. (pTokenGrpInfo->Groups[i].Attributes & SE_GROUP_ENABLED))
  278. {
  279. bAdmin = TRUE;
  280. break;
  281. }
  282. }
  283. }
  284. if (pTokenGrpInfo)
  285. LocalFree(pTokenGrpInfo);
  286. }
  287. if (hToken)
  288. CloseHandle(hToken);
  289. if (AdminSid)
  290. FreeSid(AdminSid);
  291. return bAdmin;
  292. }
  293. ////////////////////////////////////////////////////////////////////////////
  294. //
  295. // IsInteractiveUserLogon
  296. //
  297. ////////////////////////////////////////////////////////////////////////////
  298. BOOL IsInteractiveUserLogon()
  299. {
  300. PSID InteractiveSid;
  301. BOOL bCheckSucceeded;
  302. BOOL bAmInteractive = FALSE;
  303. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  304. if (!AllocateAndInitializeSid(&NtAuthority,
  305. 1,
  306. SECURITY_INTERACTIVE_RID,
  307. 0, 0, 0, 0, 0, 0, 0,
  308. &InteractiveSid))
  309. {
  310. return FALSE;
  311. }
  312. //
  313. // This checking is for logged on user or not. So we can blcok running
  314. // ctfmon.exe process from non-authorized user.
  315. //
  316. bCheckSucceeded = CheckTokenMembership(NULL,
  317. InteractiveSid,
  318. &bAmInteractive);
  319. if (InteractiveSid)
  320. FreeSid(InteractiveSid);
  321. return (bCheckSucceeded && bAmInteractive);
  322. }
  323. ////////////////////////////////////////////////////////////////////////////
  324. //
  325. // IsValidLayout
  326. //
  327. ////////////////////////////////////////////////////////////////////////////
  328. BOOL IsValidLayout(
  329. DWORD dwLayout)
  330. {
  331. HKEY hKey1, hKey2;
  332. TCHAR szLayout[MAX_PATH];
  333. //
  334. // Get the layout id as a string.
  335. //
  336. StringCchPrintf(szLayout, ARRAYSIZE(szLayout), TEXT("%08x"), dwLayout);
  337. //
  338. // Open the Keyboard Layouts key.
  339. //
  340. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLayoutPath, &hKey1) != ERROR_SUCCESS)
  341. {
  342. return (FALSE);
  343. }
  344. //
  345. // Try to open the layout id key under the Keyboard Layouts key.
  346. //
  347. if (RegOpenKey(hKey1, szLayout, &hKey2) != ERROR_SUCCESS)
  348. {
  349. RegCloseKey(hKey1);
  350. return (FALSE);
  351. }
  352. //
  353. // Close the keys.
  354. //
  355. RegCloseKey(hKey1);
  356. RegCloseKey(hKey2);
  357. //
  358. // Return success.
  359. //
  360. return (TRUE);
  361. }
  362. ////////////////////////////////////////////////////////////////////////////
  363. //
  364. // SetLangBarOption
  365. //
  366. ////////////////////////////////////////////////////////////////////////////
  367. void SetLangBarOption(
  368. DWORD dwShowStatus,
  369. BOOL bDefUser)
  370. {
  371. DWORD cb;
  372. HKEY hkeyLangBar;
  373. if (bDefUser)
  374. {
  375. if (RegCreateKey(HKEY_USERS,
  376. c_szLangBarSetting_DefUser,
  377. &hkeyLangBar) != ERROR_SUCCESS)
  378. {
  379. hkeyLangBar = NULL;
  380. }
  381. }
  382. else
  383. {
  384. if (RegCreateKey(HKEY_CURRENT_USER,
  385. c_szLangBarSetting,
  386. &hkeyLangBar) != ERROR_SUCCESS)
  387. {
  388. hkeyLangBar = NULL;
  389. }
  390. }
  391. if (hkeyLangBar)
  392. {
  393. cb = sizeof(DWORD);
  394. RegSetValueEx(hkeyLangBar,
  395. c_szShowStatus,
  396. 0,
  397. REG_DWORD,
  398. (LPBYTE)&dwShowStatus,
  399. sizeof(DWORD) );
  400. RegCloseKey(hkeyLangBar);
  401. }
  402. }
  403. ////////////////////////////////////////////////////////////////////////////
  404. //
  405. // GetLangBarOption
  406. //
  407. ////////////////////////////////////////////////////////////////////////////
  408. BOOL GetLangBarOption(
  409. DWORD *dwShowStatus,
  410. BOOL bDefUser)
  411. {
  412. DWORD cb;
  413. HKEY hkeyLangBar;
  414. BOOL bRet = FALSE;
  415. if (bDefUser)
  416. {
  417. if (RegCreateKey(HKEY_USERS,
  418. c_szLangBarSetting_DefUser,
  419. &hkeyLangBar) != ERROR_SUCCESS)
  420. {
  421. hkeyLangBar = NULL;
  422. }
  423. }
  424. else
  425. {
  426. if (RegCreateKey(HKEY_CURRENT_USER,
  427. c_szLangBarSetting,
  428. &hkeyLangBar) != ERROR_SUCCESS)
  429. {
  430. hkeyLangBar = NULL;
  431. }
  432. }
  433. if (hkeyLangBar)
  434. {
  435. cb = sizeof(DWORD);
  436. if (RegQueryValueEx(hkeyLangBar,
  437. c_szShowStatus,
  438. NULL,
  439. NULL,
  440. (LPBYTE)&dwShowStatus,
  441. &cb) == ERROR_SUCCESS)
  442. {
  443. bRet = TRUE;
  444. }
  445. RegCloseKey(hkeyLangBar);
  446. }
  447. return bRet;
  448. }
  449. ////////////////////////////////////////////////////////////////////////////
  450. //
  451. // CheckInternatModule
  452. //
  453. ////////////////////////////////////////////////////////////////////////////
  454. void CheckInternatModule()
  455. {
  456. DWORD cb;
  457. HKEY hkeyRun;
  458. TCHAR szInternatName[MAX_PATH];
  459. if (RegOpenKey(HKEY_CURRENT_USER,
  460. REGSTR_PATH_RUN,
  461. &hkeyRun) == ERROR_SUCCESS)
  462. {
  463. cb = sizeof(szInternatName);
  464. if (RegQueryValueEx(hkeyRun,
  465. c_szInternat,
  466. NULL,
  467. NULL,
  468. (LPBYTE)szInternatName,
  469. &cb) == ERROR_SUCCESS)
  470. {
  471. LCID SysLocale;
  472. BOOL bMinLangBar = TRUE;
  473. TCHAR szCTFMonPath[MAX_PATH];
  474. SysLocale = GetSystemDefaultLCID();
  475. if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
  476. (SysLocale == 0x0412) || (SysLocale == 0x0804))
  477. {
  478. //
  479. // Show language bar in case of FE system as a default
  480. //
  481. bMinLangBar = FALSE;
  482. }
  483. if (bMinLangBar)
  484. {
  485. if (IsOSPlatform(OS_NT51))
  486. {
  487. SetLangBarOption(REG_LANGBAR_DESKBAND, FALSE);
  488. //
  489. // Update language band menu item to Taskbar
  490. //
  491. SetLanguageBandMenu(TRUE);
  492. }
  493. else
  494. {
  495. SetLangBarOption(REG_LANGBAR_MINIMIZED, FALSE);
  496. }
  497. }
  498. //
  499. // Get Ctfmon full path string
  500. //
  501. if (GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath)))
  502. {
  503. //
  504. // Set "ctfmon.exe" instead of "internat.exe" module.
  505. //
  506. RegSetValueEx(hkeyRun,
  507. c_szCTFMon,
  508. 0,
  509. REG_SZ,
  510. (LPBYTE)szCTFMonPath,
  511. (lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
  512. }
  513. }
  514. RegCloseKey(hkeyRun);
  515. }
  516. }
  517. #define MAX_REGKEY 10
  518. DWORD
  519. OpenUserKeyForWin9xUpgrade(
  520. LPCTSTR pszUserKey,
  521. HKEY *phKey
  522. )
  523. {
  524. DWORD dwResult = ERROR_INVALID_PARAMETER;
  525. if (NULL != pszUserKey && NULL != phKey)
  526. {
  527. typedef struct {
  528. LPTSTR pszRoot;
  529. HKEY hKeyRoot;
  530. } REGISTRY_ROOTS, *PREGISTRY_ROOTS;
  531. static REGISTRY_ROOTS rgRoots[] = {
  532. { TEXT("HKLM"), HKEY_LOCAL_MACHINE },
  533. { TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE },
  534. { TEXT("HKCC"), HKEY_CURRENT_CONFIG },
  535. { TEXT("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG },
  536. { TEXT("HKU"), HKEY_USERS },
  537. { TEXT("HKEY_USERS"), HKEY_USERS },
  538. { TEXT("HKCU"), HKEY_CURRENT_USER },
  539. { TEXT("HKEY_CURRENT_USER"), HKEY_CURRENT_USER },
  540. { TEXT("HKCR"), HKEY_CLASSES_ROOT },
  541. { TEXT("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT }
  542. };
  543. TCHAR szUserKey[MAX_PATH]; // For a local copy.
  544. LPTSTR pszSubKey = szUserKey;
  545. //
  546. // Make a local copy that we can modify.
  547. //
  548. StringCchCopy(szUserKey, ARRAYSIZE(szUserKey), pszUserKey);
  549. *phKey = NULL;
  550. //
  551. // Find the backslash.
  552. //
  553. while(*pszSubKey && TEXT('\\') != *pszSubKey)
  554. pszSubKey++;
  555. if (TEXT('\\') == *pszSubKey)
  556. {
  557. HKEY hkeyRoot = NULL;
  558. int i;
  559. //
  560. // Replace backslash with nul to separate the root key and
  561. // sub key strings in our local copy of the original argument
  562. // string.
  563. //
  564. *pszSubKey++ = TEXT('\0');
  565. //
  566. // Now find the true root key in rgRoots[].
  567. //
  568. for (i = 0; i < MAX_REGKEY; i++)
  569. {
  570. if (0 == lstrcmpi(rgRoots[i].pszRoot, szUserKey))
  571. {
  572. hkeyRoot = rgRoots[i].hKeyRoot;
  573. break;
  574. }
  575. }
  576. if (NULL != hkeyRoot)
  577. {
  578. //
  579. // Open the key.
  580. //
  581. dwResult = RegOpenKeyEx(hkeyRoot,
  582. pszSubKey,
  583. 0,
  584. KEY_ALL_ACCESS,
  585. phKey);
  586. }
  587. }
  588. }
  589. return dwResult;
  590. }
  591. ////////////////////////////////////////////////////////////////////////////
  592. //
  593. // MigrateCtfmonFromWin9x
  594. //
  595. ////////////////////////////////////////////////////////////////////////////
  596. DWORD MigrateCtfmonFromWin9x(LPCTSTR pszUserKey)
  597. {
  598. DWORD cb;
  599. LCID SysLocale;
  600. HKEY hkeyRun = NULL;
  601. HKEY hkeyUser = NULL;
  602. HKEY hkeyPreload = NULL;
  603. BOOL bAddCtfmon = FALSE;
  604. TCHAR szInternatName[MAX_PATH];
  605. DWORD dwResult = ERROR_INVALID_PARAMETER;
  606. if (lstrlen(pszUserKey) >= MAX_PATH)
  607. return 0;
  608. SysLocale = GetSystemDefaultLCID();
  609. if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
  610. (SysLocale == 0x0412) || (SysLocale == 0x0804))
  611. {
  612. return 0;
  613. }
  614. dwResult = OpenUserKeyForWin9xUpgrade(pszUserKey, &hkeyUser);
  615. if (ERROR_SUCCESS != dwResult || hkeyUser == NULL)
  616. {
  617. return dwResult;
  618. }
  619. //
  620. // Now read all of preload hkl from the registry.
  621. //
  622. if (RegOpenKeyEx(hkeyUser,
  623. c_szKbdPreloadKey,
  624. 0,
  625. KEY_ALL_ACCESS,
  626. &hkeyPreload) == ERROR_SUCCESS)
  627. {
  628. DWORD dwIndex;
  629. DWORD cchValue, cbData;
  630. TCHAR szValue[MAX_PATH]; // language id (number)
  631. TCHAR szData[MAX_PATH]; // language name
  632. dwIndex = 0;
  633. cchValue = sizeof(szValue) / sizeof(TCHAR);
  634. cbData = sizeof(szData);
  635. dwResult = RegEnumValue(hkeyPreload,
  636. dwIndex,
  637. szValue,
  638. &cchValue,
  639. NULL,
  640. NULL,
  641. (LPBYTE)szData,
  642. &cbData );
  643. if (dwResult != ERROR_SUCCESS)
  644. {
  645. goto Exit;
  646. }
  647. do
  648. {
  649. dwIndex++;
  650. if (dwIndex >= 2)
  651. {
  652. bAddCtfmon = TRUE;
  653. break;
  654. }
  655. cchValue = sizeof(szValue) / sizeof(TCHAR);
  656. szValue[0] = TEXT('\0');
  657. cbData = sizeof(szData);
  658. szData[0] = TEXT('\0');
  659. dwResult = RegEnumValue(hkeyPreload,
  660. dwIndex,
  661. szValue,
  662. &cchValue,
  663. NULL,
  664. NULL,
  665. (LPBYTE)szData,
  666. &cbData );
  667. } while (dwResult == ERROR_SUCCESS);
  668. }
  669. if (!bAddCtfmon)
  670. {
  671. goto Exit;
  672. }
  673. if (RegOpenKeyEx(hkeyUser,
  674. REGSTR_PATH_RUN,
  675. 0,
  676. KEY_ALL_ACCESS,
  677. &hkeyRun) == ERROR_SUCCESS)
  678. {
  679. HKEY hkeyLangBar;
  680. TCHAR szCTFMonPath[MAX_PATH];
  681. if (RegCreateKey(hkeyUser,
  682. c_szLangBarSetting,
  683. &hkeyLangBar) == ERROR_SUCCESS)
  684. {
  685. DWORD dwShowStatus = REG_LANGBAR_DESKBAND;
  686. cb = sizeof(DWORD);
  687. RegSetValueEx(hkeyLangBar,
  688. c_szShowStatus,
  689. 0,
  690. REG_DWORD,
  691. (LPBYTE)&dwShowStatus,
  692. sizeof(DWORD) );
  693. RegCloseKey(hkeyLangBar);
  694. }
  695. //
  696. // Get Ctfmon full path string
  697. //
  698. if (GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath)))
  699. {
  700. //
  701. // Set "ctfmon.exe" instead of "internat.exe" module.
  702. //
  703. dwResult = RegSetValueEx(hkeyRun,
  704. c_szCTFMon,
  705. 0,
  706. REG_SZ,
  707. (LPBYTE)szCTFMonPath,
  708. (lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
  709. }
  710. //
  711. // Clean up the registry for internat.
  712. //
  713. RegDeleteValue(hkeyRun, c_szInternat);
  714. }
  715. Exit:
  716. if (hkeyPreload)
  717. RegCloseKey(hkeyPreload);
  718. if (hkeyRun)
  719. RegCloseKey(hkeyRun);
  720. if (hkeyUser)
  721. RegCloseKey(hkeyUser);
  722. return dwResult;
  723. }
  724. ////////////////////////////////////////////////////////////////////////////
  725. //
  726. // IsDisableCtfmon
  727. //
  728. ////////////////////////////////////////////////////////////////////////////
  729. BOOL IsDisableCtfmon()
  730. {
  731. DWORD cb;
  732. HKEY hkeyLangBar;
  733. BOOL bRet = FALSE;
  734. DWORD dwDisableCtfmon = 0;
  735. if (RegOpenKey(HKEY_CURRENT_USER, c_szCtf, &hkeyLangBar) == ERROR_SUCCESS)
  736. {
  737. cb = sizeof(DWORD);
  738. RegQueryValueEx(hkeyLangBar,
  739. c_szDisableTim,
  740. NULL,
  741. NULL,
  742. (LPBYTE)&dwDisableCtfmon,
  743. &cb);
  744. if (dwDisableCtfmon)
  745. bRet = TRUE;
  746. RegCloseKey(hkeyLangBar);
  747. }
  748. return bRet;
  749. }
  750. ////////////////////////////////////////////////////////////////////////////
  751. //
  752. // SetDisableCtfmon
  753. //
  754. ////////////////////////////////////////////////////////////////////////////
  755. void SetDisalbeCtfmon(
  756. DWORD dwDisableCtfmon)
  757. {
  758. DWORD cb;
  759. HKEY hkeyLangBar;
  760. if (RegCreateKey(HKEY_CURRENT_USER, c_szCtf, &hkeyLangBar) == ERROR_SUCCESS)
  761. {
  762. cb = sizeof(DWORD);
  763. RegSetValueEx(hkeyLangBar,
  764. c_szDisableTim,
  765. 0,
  766. REG_DWORD,
  767. (LPBYTE)&dwDisableCtfmon,
  768. cb);
  769. RegCloseKey(hkeyLangBar);
  770. }
  771. }
  772. ////////////////////////////////////////////////////////////////////////////
  773. //
  774. // IsDisableCUAS
  775. //
  776. ////////////////////////////////////////////////////////////////////////////
  777. BOOL IsDisableCUAS()
  778. {
  779. DWORD cb;
  780. HKEY hkeyCTF;
  781. BOOL bRet = TRUE;
  782. DWORD dwEnableCUAS = 0;
  783. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) == ERROR_SUCCESS)
  784. {
  785. cb = sizeof(DWORD);
  786. RegQueryValueEx(hkeyCTF,
  787. c_szCUAS,
  788. NULL,
  789. NULL,
  790. (LPBYTE)&dwEnableCUAS,
  791. &cb);
  792. if (dwEnableCUAS)
  793. bRet = FALSE;
  794. RegCloseKey(hkeyCTF);
  795. }
  796. return bRet;
  797. }
  798. ////////////////////////////////////////////////////////////////////////////
  799. //
  800. // SetDisableCUAS
  801. //
  802. ////////////////////////////////////////////////////////////////////////////
  803. void SetDisableCUAS(
  804. BOOL bDisableCUAS)
  805. {
  806. HKEY hkeyIMM;
  807. HKEY hkeyCTF;
  808. DWORD cb = sizeof(DWORD);
  809. DWORD dwIMM32, dwCUAS;
  810. if (bDisableCUAS)
  811. dwIMM32 = dwCUAS = 0;
  812. else
  813. dwIMM32 = dwCUAS = 1;
  814. if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szIMM, &hkeyIMM) != ERROR_SUCCESS)
  815. {
  816. hkeyIMM = NULL;
  817. }
  818. if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) != ERROR_SUCCESS)
  819. {
  820. hkeyCTF = NULL;
  821. }
  822. if (!bDisableCUAS)
  823. {
  824. //
  825. // Turn on LoadIMM and CUAS flags
  826. //
  827. if (hkeyIMM)
  828. {
  829. RegSetValueEx(hkeyIMM,
  830. c_szIMMFile,
  831. 0,
  832. REG_SZ,
  833. (LPBYTE)c_szIMMFileName,
  834. (lstrlen(c_szIMMFileName) + 1) * sizeof(TCHAR));
  835. }
  836. }
  837. else
  838. {
  839. //
  840. // Turn off LoadIMM and CUAS flags
  841. //
  842. BOOL bEALang = IsInstalledEALangPack();
  843. if (bEALang)
  844. {
  845. dwIMM32 = 1;
  846. }
  847. }
  848. if (hkeyIMM)
  849. {
  850. RegSetValueEx(hkeyIMM,
  851. c_szLoadIMM,
  852. 0,
  853. REG_DWORD,
  854. (LPBYTE)&dwIMM32,
  855. cb);
  856. }
  857. if (hkeyCTF)
  858. {
  859. RegSetValueEx(hkeyCTF,
  860. c_szCUAS,
  861. 0,
  862. REG_DWORD,
  863. (LPBYTE)&dwCUAS,
  864. cb);
  865. }
  866. if (hkeyIMM)
  867. RegCloseKey(hkeyIMM);
  868. if (hkeyCTF)
  869. RegCloseKey(hkeyCTF);
  870. }
  871. ////////////////////////////////////////////////////////////////////////////
  872. //
  873. // SetDisableCtfmon
  874. //
  875. ////////////////////////////////////////////////////////////////////////////
  876. BOOL SetLanguageBandMenu(
  877. BOOL bLoad)
  878. {
  879. BOOL bRet = FALSE;
  880. HINSTANCE hMsutb = NULL;
  881. FARPROC pfnSetRegisterLangBand = NULL;
  882. //
  883. // Load MSUTB.DLL to register deskband menu item to TaskBar.
  884. //
  885. hMsutb = LoadSystemLibrary(TEXT("msutb.dll"));
  886. if (hMsutb)
  887. {
  888. //
  889. // Get SetRegisterLangBand()
  890. //
  891. pfnSetRegisterLangBand = GetProcAddress(hMsutb,
  892. (LPVOID)8);
  893. }
  894. else
  895. {
  896. goto Exit;
  897. }
  898. //
  899. // Call DllRegisterServer/DllUnregisterServer()
  900. //
  901. if (pfnSetRegisterLangBand)
  902. {
  903. pfnSetRegisterLangBand(bLoad);
  904. bRet = TRUE;
  905. }
  906. if (hMsutb)
  907. {
  908. FreeLibrary(hMsutb);
  909. }
  910. Exit:
  911. return bRet;
  912. }
  913. ////////////////////////////////////////////////////////////////////////////
  914. //
  915. // RunCtfmonProcess
  916. //
  917. ////////////////////////////////////////////////////////////////////////////
  918. BOOL RunCtfmonProcess()
  919. {
  920. TCHAR szCtfmonPath[MAX_PATH + 1];
  921. if (GetCtfmonPath(szCtfmonPath, ARRAYSIZE(szCtfmonPath)))
  922. {
  923. PROCESS_INFORMATION pi;
  924. STARTUPINFO si = {0};
  925. si.cb = sizeof(STARTUPINFO);
  926. si.dwFlags = STARTF_USESHOWWINDOW;
  927. si.wShowWindow = (WORD) SW_SHOWMINNOACTIVE;
  928. if (CreateProcess(szCtfmonPath,
  929. c_szCTFMon,
  930. NULL,
  931. NULL,
  932. FALSE,
  933. NORMAL_PRIORITY_CLASS,
  934. NULL,
  935. NULL,
  936. &si,
  937. &pi))
  938. {
  939. WaitForInputIdle(pi.hProcess, 2000) ;
  940. return TRUE;
  941. }
  942. }
  943. return FALSE;
  944. }
  945. ////////////////////////////////////////////////////////////////////////////
  946. //
  947. // GetCtfmonPath
  948. //
  949. ////////////////////////////////////////////////////////////////////////////
  950. UINT GetCtfmonPath(
  951. LPTSTR lpCtfmonPath,
  952. UINT uBuffLen)
  953. {
  954. UINT uSize = 0;
  955. if (!lpCtfmonPath)
  956. return uSize;
  957. *lpCtfmonPath = TEXT('\0');
  958. //
  959. // Confirmed lpCtfmonPath has MAX_PATH buffer size.
  960. //
  961. if (uSize = GetSystemDirectory(lpCtfmonPath, uBuffLen))
  962. {
  963. if (*(lpCtfmonPath + uSize - 1) != TEXT('\\'))
  964. {
  965. *(lpCtfmonPath + uSize) = TEXT('\\');
  966. uSize++;
  967. }
  968. if (uBuffLen - uSize > (UINT) lstrlen(c_szCTFMon))
  969. {
  970. lstrcpyn(lpCtfmonPath + uSize, c_szCTFMon, uBuffLen - uSize);
  971. uSize += lstrlen(c_szCTFMon);
  972. }
  973. else
  974. {
  975. *(lpCtfmonPath) = TEXT('\0');
  976. uSize = 0;
  977. }
  978. }
  979. return uSize;
  980. }
  981. ////////////////////////////////////////////////////////////////////////////
  982. //
  983. // IsInstalledEALangPack
  984. //
  985. ////////////////////////////////////////////////////////////////////////////
  986. BOOL IsInstalledEALangPack()
  987. {
  988. BOOL bRet = FALSE;
  989. HKEY hkeyLangGroup;
  990. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  991. c_szLangGroup,
  992. 0,
  993. KEY_READ,
  994. &hkeyLangGroup) == ERROR_SUCCESS)
  995. {
  996. DWORD cb;
  997. TCHAR szLangInstall[10];
  998. cb = sizeof(szLangInstall);
  999. //
  1000. // The checking of Japan Language is enough to know EA language pack
  1001. // installation.
  1002. //
  1003. if (RegQueryValueEx(hkeyLangGroup,
  1004. c_szLangJPN,
  1005. NULL,
  1006. NULL,
  1007. (LPBYTE)szLangInstall,
  1008. &cb) == ERROR_SUCCESS)
  1009. {
  1010. if (szLangInstall[0] != 0)
  1011. return TRUE;
  1012. }
  1013. RegCloseKey(hkeyLangGroup);
  1014. }
  1015. return bRet;
  1016. }
  1017. ////////////////////////////////////////////////////////////////////////////
  1018. //
  1019. // IsTIPClsidEnabled
  1020. //
  1021. ////////////////////////////////////////////////////////////////////////////
  1022. BOOL IsTIPClsidEnabled(
  1023. HKEY hkeyTop,
  1024. LPTSTR lpTipClsid,
  1025. BOOL *bExistEnable)
  1026. {
  1027. BOOL bRet = FALSE;
  1028. HKEY hkeyTipLang;
  1029. HKEY hkeyTipLangid;
  1030. HKEY hkeyTipGuid;
  1031. UINT uIndex;
  1032. UINT uIndex2;
  1033. DWORD cb;
  1034. DWORD cchLangid;
  1035. DWORD cchGuid;
  1036. DWORD dwEnableTIP = 0;
  1037. LPTSTR pszGuid;
  1038. LPTSTR pszLangid;
  1039. TCHAR szTIPLangid[15];
  1040. TCHAR szTIPGuid[128];
  1041. TCHAR szTIPClsidLang[MAX_PATH];
  1042. FILETIME lwt;
  1043. UINT uLangidLen;
  1044. UINT uGuidLen;
  1045. if (lstrlen(lpTipClsid) != CLSID_STRLEN)
  1046. return bRet;
  1047. StringCchCopy(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szCTFTipPath);
  1048. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), lpTipClsid);
  1049. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szLanguageProfile);
  1050. pszLangid = szTIPClsidLang + lstrlen(szTIPClsidLang);
  1051. uLangidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
  1052. if (RegOpenKeyEx(hkeyTop,
  1053. szTIPClsidLang, 0,
  1054. KEY_READ, &hkeyTipLang) != ERROR_SUCCESS)
  1055. {
  1056. goto Exit;
  1057. }
  1058. for (uIndex = 0; bRet == FALSE; uIndex++)
  1059. {
  1060. cchLangid = sizeof(szTIPLangid) / sizeof(TCHAR);
  1061. if (RegEnumKeyEx(hkeyTipLang, uIndex,
  1062. szTIPLangid, &cchLangid,
  1063. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  1064. {
  1065. break;
  1066. }
  1067. if (cchLangid != 10)
  1068. {
  1069. // string langid subkeys should be like 0x00000409
  1070. continue;
  1071. }
  1072. if (uLangidLen > (cchLangid + 1))
  1073. {
  1074. StringCchCopy(pszLangid, uLangidLen, TEXT("\\"));
  1075. StringCchCat(pszLangid, uLangidLen, szTIPLangid);
  1076. }
  1077. if (RegOpenKeyEx(hkeyTop,
  1078. szTIPClsidLang, 0,
  1079. KEY_READ, &hkeyTipLangid) != ERROR_SUCCESS)
  1080. {
  1081. continue;
  1082. }
  1083. pszGuid = szTIPClsidLang + lstrlen(szTIPClsidLang);
  1084. uGuidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
  1085. for (uIndex2 = 0; bRet == FALSE; uIndex2++)
  1086. {
  1087. cchGuid = sizeof(szTIPGuid) / sizeof(TCHAR);
  1088. if (RegEnumKeyEx(hkeyTipLangid, uIndex2,
  1089. szTIPGuid, &cchGuid,
  1090. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  1091. {
  1092. break;
  1093. }
  1094. if (cchGuid != CLSID_STRLEN)
  1095. {
  1096. continue;
  1097. }
  1098. if (uGuidLen > (cchGuid + 1))
  1099. {
  1100. StringCchCopy(pszGuid, uGuidLen, TEXT("\\"));
  1101. StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), szTIPGuid);
  1102. }
  1103. if (RegOpenKeyEx(hkeyTop,
  1104. szTIPClsidLang, 0,
  1105. KEY_READ, &hkeyTipGuid) == ERROR_SUCCESS)
  1106. {
  1107. cb = sizeof(DWORD);
  1108. if (RegQueryValueEx(hkeyTipGuid,
  1109. TEXT("Enable"),
  1110. NULL,
  1111. NULL,
  1112. (LPBYTE)&dwEnableTIP,
  1113. &cb) == ERROR_SUCCESS)
  1114. {
  1115. RegCloseKey(hkeyTipGuid);
  1116. *bExistEnable = TRUE;
  1117. if (dwEnableTIP)
  1118. {
  1119. bRet = TRUE;
  1120. }
  1121. }
  1122. else if (hkeyTop == HKEY_LOCAL_MACHINE)
  1123. {
  1124. // Default is the enabled status on HKLM
  1125. *bExistEnable = TRUE;
  1126. bRet = TRUE;
  1127. }
  1128. else
  1129. {
  1130. *bExistEnable = FALSE;
  1131. }
  1132. }
  1133. }
  1134. RegCloseKey(hkeyTipLangid);
  1135. }
  1136. RegCloseKey(hkeyTipLang);
  1137. Exit:
  1138. return bRet;
  1139. }
  1140. ////////////////////////////////////////////////////////////////////////////
  1141. //
  1142. // IsTipInstalled
  1143. //
  1144. ////////////////////////////////////////////////////////////////////////////
  1145. BOOL IsTipInstalled()
  1146. {
  1147. const CLSID CLSID_SapiLayr = {0xdcbd6fa8, 0x032f, 0x11d3, {0xb5, 0xb1, 0x00, 0xc0, 0x4f, 0xc3, 0x24, 0xa1}};
  1148. const CLSID CLSID_SoftkbdIMX = {0xf89e9e58, 0xbd2f, 0x4008, {0x9a, 0xc2, 0x0f, 0x81, 0x6c, 0x09, 0xf4, 0xee}};
  1149. static const TCHAR c_szSpeechRecognizersKey[] = TEXT("Software\\Microsoft\\Speech\\Recognizers\\Tokens");
  1150. static const TCHAR c_szCategory[] = TEXT("\\Category\\Category");
  1151. BOOL bRet = FALSE;
  1152. BOOL bExistEnable;
  1153. HKEY hkeyTip;
  1154. HKEY hkeyTipSub;
  1155. UINT uIndex;
  1156. DWORD dwSubKeys;
  1157. DWORD cchClsid;
  1158. CLSID clsidTip;
  1159. TCHAR szTipClsid[128];
  1160. TCHAR szTipClsidPath[MAX_PATH];
  1161. FILETIME lwt;
  1162. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1163. TEXT("Software\\Microsoft\\CTF\\TIP"),
  1164. 0, KEY_READ, &hkeyTip) != ERROR_SUCCESS)
  1165. {
  1166. goto Exit;
  1167. }
  1168. // enum through all the TIP subkeys
  1169. for (uIndex = 0; TRUE; uIndex++)
  1170. {
  1171. bExistEnable = FALSE;
  1172. cchClsid = sizeof(szTipClsid) / sizeof(TCHAR);
  1173. if (RegEnumKeyEx(hkeyTip, uIndex,
  1174. szTipClsid, &cchClsid,
  1175. NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
  1176. {
  1177. break;
  1178. }
  1179. if (cchClsid != CLSID_STRLEN)
  1180. {
  1181. // string clsid subkeys should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  1182. continue;
  1183. }
  1184. StringCchCopy(szTipClsidPath, ARRAYSIZE(szTipClsidPath), szTipClsid);
  1185. // we want subkey\Language Profiles key
  1186. StringCchCat(szTipClsidPath, ARRAYSIZE(szTipClsidPath), c_szLanguageProfile);
  1187. // is this subkey a tip?
  1188. if (RegOpenKeyEx(hkeyTip,
  1189. szTipClsidPath, 0,
  1190. KEY_READ, &hkeyTipSub) == ERROR_SUCCESS)
  1191. {
  1192. RegCloseKey(hkeyTipSub);
  1193. // it's a tip, get the clsid
  1194. if (CLSIDFromString((LPOLESTR )szTipClsid, &clsidTip) != NOERROR)
  1195. continue;
  1196. // special case certain known tips
  1197. if (IsEqualGUID(&clsidTip, &CLSID_SapiLayr))
  1198. {
  1199. //
  1200. // This is SAPI TIP and need to handle it specially, since sptip has
  1201. // a default option as the enabled status.
  1202. //
  1203. if (!IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
  1204. {
  1205. //
  1206. // If SPTIP has enable registry setting on HKCU with the disabled
  1207. // speech tip, we assume user intentionally disable it.
  1208. //
  1209. if (bExistEnable)
  1210. continue;
  1211. }
  1212. // this is the sapi tip, which is always installed
  1213. // but it will not activate if sapi is not installed
  1214. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1215. c_szSpeechRecognizersKey, 0,
  1216. KEY_READ, &hkeyTipSub) != ERROR_SUCCESS)
  1217. {
  1218. continue; // this tip doesn't count
  1219. }
  1220. // need 1 or more subkeys for sapi to be truely installed...whistler has a Tokens with nothing underneath
  1221. if (RegQueryInfoKey(hkeyTipSub,
  1222. NULL, NULL, NULL, &dwSubKeys, NULL,
  1223. NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  1224. {
  1225. dwSubKeys = 0; // assume no sub keys on failure
  1226. }
  1227. RegCloseKey(hkeyTipSub);
  1228. if (dwSubKeys != 0)
  1229. {
  1230. bRet = TRUE;
  1231. break;
  1232. }
  1233. }
  1234. else if (IsEqualGUID(&clsidTip, &CLSID_SoftkbdIMX))
  1235. {
  1236. // don't count the softkbd, it is disabled until another tip
  1237. // enables it
  1238. continue;
  1239. }
  1240. else if(IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
  1241. {
  1242. bRet = TRUE;
  1243. break;
  1244. }
  1245. else if (!bExistEnable)
  1246. {
  1247. if(IsTIPClsidEnabled(HKEY_LOCAL_MACHINE, szTipClsid, &bExistEnable))
  1248. {
  1249. bRet = TRUE;
  1250. break;
  1251. }
  1252. }
  1253. }
  1254. }
  1255. RegCloseKey(hkeyTip);
  1256. Exit:
  1257. return bRet;
  1258. }
  1259. ////////////////////////////////////////////////////////////////////////////
  1260. //
  1261. // ResetImm32AndCtfImeFlag
  1262. //
  1263. ////////////////////////////////////////////////////////////////////////////
  1264. void ResetImm32AndCtfIme()
  1265. {
  1266. BOOL bTipInstalled;
  1267. bTipInstalled = IsTipInstalled();
  1268. if (bTipInstalled)
  1269. {
  1270. //
  1271. // TIP is detected now, so automatically recover LoadImm
  1272. // and CUAS to "On" status
  1273. //
  1274. SetDisableCUAS(FALSE);
  1275. }
  1276. }
  1277. ////////////////////////////////////////////////////////////////////////////
  1278. //
  1279. // LoadSystemLibrary
  1280. //
  1281. ////////////////////////////////////////////////////////////////////////////
  1282. HMODULE LoadSystemLibrary(
  1283. LPCTSTR lpModuleName)
  1284. {
  1285. UINT uRet = 0;
  1286. HINSTANCE hModule = NULL;
  1287. TCHAR szModulePath[MAX_PATH + 1];
  1288. szModulePath[0] = TEXT('\0');
  1289. uRet = GetSystemDirectory(szModulePath, ARRAYSIZE(szModulePath));
  1290. if (uRet >= ARRAYSIZE(szModulePath))
  1291. {
  1292. // we don't have a room to copy module name.
  1293. uRet = 0;
  1294. }
  1295. else if (uRet)
  1296. {
  1297. if (szModulePath[uRet - 1] != TEXT('\\'))
  1298. {
  1299. szModulePath[uRet] = TEXT('\\');
  1300. uRet++;
  1301. }
  1302. if (ARRAYSIZE(szModulePath) - uRet > (UINT) lstrlen(lpModuleName))
  1303. {
  1304. lstrcpyn(&szModulePath[uRet],
  1305. lpModuleName,
  1306. ARRAYSIZE(szModulePath) - uRet);
  1307. }
  1308. else
  1309. {
  1310. uRet = 0;
  1311. }
  1312. }
  1313. if (uRet)
  1314. {
  1315. hModule = LoadLibrary(szModulePath);
  1316. }
  1317. return hModule;
  1318. }
  1319. ////////////////////////////////////////////////////////////////////////////
  1320. //
  1321. // LoadSystemLibraryEx
  1322. //
  1323. ////////////////////////////////////////////////////////////////////////////
  1324. HMODULE LoadSystemLibraryEx(
  1325. LPCTSTR lpModuleName,
  1326. HANDLE hFile,
  1327. DWORD dwFlags)
  1328. {
  1329. UINT uRet = 0;
  1330. HINSTANCE hModule = NULL;
  1331. TCHAR szModulePath[MAX_PATH + 1];
  1332. szModulePath[0] = TEXT('\0');
  1333. uRet = GetSystemDirectory(szModulePath, ARRAYSIZE(szModulePath));
  1334. if (uRet >= ARRAYSIZE(szModulePath))
  1335. {
  1336. // we don't have a room to copy module name.
  1337. uRet = 0;
  1338. }
  1339. else if (uRet)
  1340. {
  1341. if (szModulePath[uRet - 1] != TEXT('\\'))
  1342. {
  1343. szModulePath[uRet] = TEXT('\\');
  1344. uRet++;
  1345. }
  1346. if (ARRAYSIZE(szModulePath) - uRet > (UINT) lstrlen(lpModuleName))
  1347. {
  1348. lstrcpyn(&szModulePath[uRet],
  1349. lpModuleName,
  1350. ARRAYSIZE(szModulePath) - uRet);
  1351. }
  1352. else
  1353. {
  1354. uRet = 0;
  1355. }
  1356. }
  1357. if (uRet)
  1358. {
  1359. hModule = LoadLibraryEx(szModulePath, hFile,dwFlags);
  1360. }
  1361. return hModule;
  1362. }