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.

2131 lines
76 KiB

  1. /**************************************************************************\
  2. * Module Name: Winmain.cpp
  3. *
  4. * Copyright (C) 2000, Microsoft Corporation
  5. *
  6. * Korean IME 6.1 install utility
  7. *
  8. * History:
  9. * 11-Dec-2000 CSLim Ported from Satori 8.1 code
  10. \**************************************************************************/
  11. #include "private.h"
  12. #include <set>
  13. #include "imkrinst.h"
  14. #include "regtip.h"
  15. #include "insert.h"
  16. #include "..\tip\resource.h"
  17. #include "..\version\verres.h"
  18. // Safe String
  19. #define STRSAFE_NO_DEPRECATE
  20. #include "strsafe.h"
  21. #define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x)
  22. #define MEMFREE(x) LocalFree(x)
  23. // Profile reg key
  24. #define SZTIPREG_LANGPROFILE_TEMPLATE TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\%s\\LanguageProfile\\0x00000412")
  25. #if defined(_WIN64)
  26. #define SZTIPREG_LANGPROFILE_TEMPLATE_WOW64 TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\CTF\\TIP\\%s\\LanguageProfile\\0x00000412")
  27. #endif
  28. #ifdef DEBUG
  29. CCicCriticalSectionStatic g_cs;
  30. #endif
  31. // IA64 IME does not support IME Pad. So we just need to take care Wow64 IME in IA64.
  32. #if !defined(_WIN64)
  33. // Pad Applet Registry location
  34. #define SZPADSHARE TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042")
  35. #define SZAPPLETCLSID TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletCLSIDList")
  36. #define SZAPPLETIID TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletIIDList")
  37. #else
  38. #define SZPADSHARE TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042")
  39. #define SZAPPLETCLSID TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletCLSIDList")
  40. #define SZAPPLETIID TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletIIDList")
  41. #endif
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Script run routines
  44. BOOL CmdSetupDefaultParameters();
  45. BOOL CmdSetVersion(LPCTSTR szParam);
  46. BOOL CmdFileList(LPCTSTR szFormat);
  47. BOOL CmdPreSetupCheck(LPCTSTR szParam);
  48. BOOL CmdRenamePEFile(LPCTSTR szParam);
  49. BOOL CmdRenameFile(LPCTSTR szParam);
  50. BOOL CmdRegisterInterface(LPCTSTR szParam);
  51. BOOL CmdRegisterInterfaceWow64(LPCTSTR szParam);
  52. BOOL CmdRegisterIMEandTIP(LPCTSTR szParam);
  53. BOOL CmdRegisterPackageVersion(void);
  54. BOOL CmdRegisterPadOrder(void);
  55. BOOL CmdAddToPreload(LPCTSTR szParam);
  56. BOOL CmdPrepareMigration(LPCTSTR szParam);
  57. BOOL CmdCreateDirectory(LPCTSTR szParam);
  58. BOOL CmdRegisterHelpDirs();
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Private Functions
  61. // Utility functions
  62. static DWORD WINAPI ProcessScriptFile();
  63. static void RegisterIMEWithFixedHKL(LPCTSTR szHKL, LPCTSTR szIMEFileName, LPCTSTR szIMEName);
  64. static void cdecl LogOutDCPrintf(LPCTSTR lpFmt, va_list va);
  65. static void DebugLog(LPCTSTR szFormat, ...);
  66. static void ErrorLog(LPCTSTR szFormat, ...);
  67. static INT ParseEnvVar(LPTSTR szBuffer, const UINT arg_nLength);
  68. static void TrimString(LPTSTR szString);
  69. static BOOL fExistFile(LPCTSTR szFilePath);
  70. static BOOL fOldIMEsExist();
  71. static BOOL WINAPI ReplaceFileOnReboot (LPCTSTR pszExisting, LPCTSTR pszNew);
  72. static void GetPEFileVersion(LPTSTR szFilePath, DWORD *pdwMajorVersion, DWORD *pdwMiddleVersion, DWORD *pdwMinorVersion, DWORD *pdwBuildNumber);
  73. static BOOL ActRenameFile(LPCTSTR szSrcPath, LPCTSTR tszDstPath, DWORD dwFileAttributes);
  74. static void RegisterTIP(LPCTSTR szTIPName);
  75. static void RegisterTIPWow64(LPCTSTR szTIPName);
  76. static BOOL RegisterRUNKey(LPCTSTR szParam);
  77. static BOOL MakeSIDList();
  78. static PSECURITY_DESCRIPTOR CreateSD();
  79. static PSID MyCreateSid(DWORD dwSubAuthority);
  80. // HKL Helpers
  81. static void HKLHelpSetDefaultKeyboardLayout(HKEY hKeyHKCU, HKL hKL, BOOL fSetToDefault);
  82. static BOOL HKLHelp412ExistInPreload(HKEY hKeyCU);
  83. static HKL GetHKLfromHKLM(LPTSTR argszIMEFile);
  84. static void RestoreMajorVersionRegistry();
  85. /////////////////////////////////////////////////////////////////////////////
  86. // Global variables
  87. /////////////////////////////////////////////////////////////////////////////
  88. static TCHAR g_szCurrentDirectory[MAX_PATH] = {0}; // Directory in where this EXE resides.
  89. static TCHAR g_szScriptFile[MAX_PATH] = {0}; // File name (not full path) of script file.
  90. static TCHAR g_szSetupProgram[MAX_PATH] = {0}; // File name (not full path) of setup program.
  91. static TCHAR g_szSystemDirectory[MAX_PATH] = {0}; // System directory.
  92. static TCHAR g_szErrorMessage[200] = {0}; // Global buffer for last error message.
  93. static BOOL g_fDebugLog = FALSE; // Dump debug message when true.
  94. static BOOL g_fErrorLog = FALSE; // Dump error message when true.
  95. static DWORD g_dwMajorVersion = 0; // Package version of this installation.
  96. static DWORD g_dwMiddleVersion = 0;
  97. static DWORD g_dwMinorVersion = 0;
  98. static DWORD g_dwBuildNumber = 0;
  99. static std::set <FLE> g_FileList; // FileListSet. Used to store set of file paths given by "CmdFileList"
  100. // script command.
  101. TCHAR g_szVersionKeyCur[MAX_PATH] = {0};
  102. BOOL g_fExistNewerVersion = FALSE;
  103. /*---------------------------------------------------------------------------
  104. WinMain
  105. ---------------------------------------------------------------------------*/
  106. INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  107. {
  108. LPTSTR szHitPtr;
  109. LPTSTR szCommandLine;
  110. size_t cchCommandLine;
  111. if (FAILED(StringCchLength(GetCommandLine(), MAX_PATH, &cchCommandLine)))
  112. return (0);
  113. szCommandLine = new TCHAR[cchCommandLine + 1];
  114. if (szCommandLine == NULL)
  115. return (0);
  116. // szCommandLine contains all command line.
  117. // Will be modified by _tcstok.
  118. StringCchCopy(szCommandLine, cchCommandLine+1, GetCommandLine());
  119. // TEMP Code
  120. // LogOutDCPrintf(TEXT("WinMain CommandLine arg: %s"), szCommandLine);
  121. CoInitialize(NULL);
  122. szHitPtr = _tcstok(szCommandLine, TEXT("\""));
  123. // g_szCurrentDirectory has path for the process. (IMKRINST.EXE)
  124. StringCchCopy(g_szCurrentDirectory, ARRAYSIZE(g_szCurrentDirectory), szHitPtr);
  125. szHitPtr = _tcsrchr(g_szCurrentDirectory, TEXT('\\'));
  126. // if g_szCurrentDirectory contains full path,
  127. if (szHitPtr != NULL)
  128. {
  129. *szHitPtr = 0; // terminate with the last '\' character to obtain current directory,
  130. StringCchCopy(g_szSetupProgram, ARRAYSIZE(g_szSetupProgram), szHitPtr + 1); // then copy the rest (after last '\') to g_szScriptFile.
  131. }
  132. else
  133. {
  134. StringCchCopy(g_szSetupProgram, ARRAYSIZE(g_szSetupProgram), g_szCurrentDirectory); // Otherwise (g_szCurrentDirectory is not full path), copy entire
  135. GetCurrentDirectory(MAX_PATH, g_szCurrentDirectory); // to g_szScriptFile and obtain current directory by GetCurrentDirectory.
  136. }
  137. StringCchCopy(g_szScriptFile, ARRAYSIZE(g_szScriptFile), g_szSetupProgram);
  138. szHitPtr = _tcsrchr(g_szScriptFile, TEXT('.'));
  139. if (szHitPtr != NULL) // If g_szScriptFile contains '.' character, find the last one
  140. *szHitPtr = 0; // and terminate string with it, then concatenate ".inf" to it.
  141. // Usually it results ".exe" -> ".inf" replacement. If g_szScriptFile
  142. // doesn't have '.' character, just concatenate ".ini".
  143. lstrcat(g_szScriptFile, TEXT(".ini"));
  144. // Get system32 dir
  145. GetSystemDirectory(g_szSystemDirectory, ARRAYSIZE(g_szSystemDirectory));
  146. // g_szCurrentDirectory, g_szSetupProgram, g_szSystemDirectory and g_szScriptFile are prepared.
  147. // szCommandLine will be no longer used.
  148. // We can use these environment variable in the process.
  149. SetEnvironmentVariable(TEXT("SETUPSOURCE"), g_szCurrentDirectory);
  150. SetEnvironmentVariable(TEXT("SETUPEXE"), g_szSetupProgram);
  151. SetEnvironmentVariable(TEXT("SETUPINF"), g_szScriptFile);
  152. SetEnvironmentVariable(TEXT("SYSTEMDIR"), g_szSystemDirectory);
  153. delete[] szCommandLine;
  154. szCommandLine = NULL;
  155. //////////////////////////////////////////////////////////////////////////
  156. // Read and run Script file
  157. switch (ProcessScriptFile())
  158. {
  159. case errNoError:
  160. break;
  161. case errPreSetupCheck:
  162. {
  163. #ifdef NEVER
  164. for(set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++){
  165. DebugLog(TEXT("Cleanup: Deleting Source file: %s"), itFLE->szFileName);
  166. DeleteFile(itFLE->szFileName);
  167. }
  168. #endif // NEVER
  169. }
  170. break;
  171. default:
  172. DebugLog(g_szErrorMessage);
  173. }
  174. #ifdef NEVER
  175. for (set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++)
  176. {
  177. ErrorLog(TEXT("Warning: File %s in CmdFileList will be removed without any processing"), itFLE->szFileName);
  178. DeleteFile(itFLE->szFileName);
  179. }
  180. #endif // NEVER
  181. CoUninitialize();
  182. return(0);
  183. }
  184. /////////////////////////////////////////////////////////////////////////////
  185. // Main Script Processing functions
  186. /////////////////////////////////////////////////////////////////////////////
  187. inline LPCTSTR GetParameter(LPTSTR szLineBuffer)
  188. {
  189. return(szLineBuffer + lstrlen(szLineBuffer) + 1);
  190. }
  191. /*---------------------------------------------------------------------------
  192. ProcessScriptFile
  193. Read script file. Dispatch commands for each line.
  194. ---------------------------------------------------------------------------*/
  195. DWORD WINAPI ProcessScriptFile()
  196. {
  197. TCHAR szScriptFilePath[MAX_PATH];
  198. FILE *fileScript;
  199. wsprintf(szScriptFilePath, TEXT("%s\\%s"), g_szCurrentDirectory, g_szScriptFile);
  200. fileScript = _tfopen(szScriptFilePath, TEXT("rt"));
  201. if (fileScript != NULL)
  202. {
  203. TCHAR szLineBuffer[_cchBuffer];
  204. LPTSTR szCommand;
  205. // Parse command
  206. // Command form <Command>:<Parameter>
  207. while (_fgetts(szLineBuffer, _cchBuffer, fileScript) != NULL)
  208. {
  209. // Chop CR code.
  210. szLineBuffer[lstrlen(szLineBuffer) - 1] = 0;
  211. // Empty or Comment line
  212. if (lstrlen(szLineBuffer) == 0 || (_tcsncmp(TEXT("//"), szLineBuffer, 2) == 0))
  213. continue;
  214. DebugLog(TEXT("Line: %s"), szLineBuffer);
  215. szCommand = _tcstok(szLineBuffer, TEXT(":"));
  216. if (szCommand == NULL)
  217. { // Dispatch each commands.
  218. DebugLog(TEXT("Ignore line"));
  219. }
  220. else if (lstrcmpi(szCommand, TEXT("DebugLogOn")) == 0)
  221. {
  222. g_fDebugLog = TRUE;
  223. g_fErrorLog = TRUE;
  224. DebugLog(TEXT("Turn on DebugLog"));
  225. }
  226. else if (lstrcmpi(szCommand, TEXT("DebugLogOff")) == 0)
  227. {
  228. DebugLog(TEXT("Turn off DebugLog"));
  229. g_fDebugLog = FALSE;
  230. }
  231. else if (lstrcmpi(szCommand, TEXT("ErrorLogOn")) == 0)
  232. {
  233. g_fErrorLog = TRUE;
  234. DebugLog(TEXT("Turn on DebugLog"));
  235. }
  236. else if (lstrcmpi(szCommand, TEXT("ErrorLogOff")) == 0)
  237. {
  238. DebugLog(TEXT("Turn off DebugLog"));
  239. g_fErrorLog = FALSE;
  240. }
  241. else if (lstrcmpi(szCommand, TEXT("FileList")) == 0)
  242. {
  243. if (!CmdFileList(GetParameter(szCommand)))
  244. return(errFileList);
  245. }
  246. else if (lstrcmpi(szCommand, TEXT("SetupDefaultParameters")) == 0)
  247. {
  248. if (!CmdSetupDefaultParameters())
  249. return(errSetDefaultParameters);
  250. }
  251. else if (lstrcmpi(szCommand, TEXT("SetVersion")) == 0)
  252. {
  253. if (!CmdSetVersion(GetParameter(szCommand)))
  254. return(errSetVersion);
  255. }
  256. else if (lstrcmpi(szCommand, TEXT("PreSetupCheck")) == 0)
  257. {
  258. if (!CmdPreSetupCheck(GetParameter(szCommand)))
  259. return(errPreSetupCheck);
  260. }
  261. else if (lstrcmpi(szCommand, TEXT("RenamePEFile")) == 0)
  262. {
  263. if (!CmdRenamePEFile(GetParameter(szCommand)))
  264. return(errRenameFile);
  265. }
  266. else if (lstrcmpi(szCommand, TEXT("RenameFile")) == 0)
  267. {
  268. if (!CmdRenameFile(GetParameter(szCommand)))
  269. return(errRenameFile);
  270. }
  271. else if (lstrcmpi(szCommand, TEXT("RegisterIMEandTIP")) == 0)
  272. {
  273. if (!CmdRegisterIMEandTIP(GetParameter(szCommand)))
  274. return(errRegisterIMEandTIP);
  275. }
  276. else if (lstrcmpi(szCommand, TEXT("RegisterPackageVersion")) == 0)
  277. {
  278. if (!CmdRegisterPackageVersion())
  279. return(errRegisterPackageVersion);
  280. }
  281. else if (lstrcmpi(szCommand, TEXT("RegisterInterface")) == 0)
  282. {
  283. if (!CmdRegisterInterface(GetParameter(szCommand)))
  284. return(errRegisterInterface);
  285. }
  286. else if (lstrcmpi(szCommand, TEXT("RegisterInterfaceWow64")) == 0)
  287. {
  288. if (!CmdRegisterInterfaceWow64(GetParameter(szCommand)))
  289. return(errRegisterInterfaceWow64);
  290. }
  291. else if (lstrcmpi(szCommand, TEXT("RegisterPadOrder")) == 0)
  292. {
  293. if (!CmdRegisterPadOrder())
  294. return(errRegisterPadOrder);
  295. }
  296. else if (lstrcmpi(szCommand, TEXT("AddToPreload")) == 0)
  297. {
  298. if (!CmdAddToPreload(GetParameter(szCommand)))
  299. return(errAddToPreload);
  300. }
  301. else if (lstrcmpi(szCommand, TEXT("PrepareMigration")) == 0)
  302. {
  303. if (!CmdPrepareMigration(GetParameter(szCommand)))
  304. return(errPrepareMigration);
  305. }
  306. else if (lstrcmpi(szCommand, TEXT("CreateDirectory")) == 0)
  307. {
  308. if (!CmdCreateDirectory(GetParameter(szCommand)))
  309. return(errCmdCreateDirectory);
  310. }
  311. else if (lstrcmpi(szCommand, TEXT("RegisterHelpDirs")) == 0)
  312. {
  313. if (!CmdRegisterHelpDirs())
  314. return(errCmdRegisterHelpDirs);
  315. }
  316. else
  317. DebugLog(TEXT("Ignore line"));
  318. }
  319. fclose(fileScript);
  320. }
  321. else
  322. {
  323. wsprintf(g_szErrorMessage, TEXT("Cannot open %s"), g_szScriptFile);
  324. return(errNoFile);
  325. }
  326. return(errNoError);
  327. }
  328. /////////////////////////////////////////////////////////////////////////////
  329. // Command handlers. Which are invoked from ProcessScriptFile
  330. /////////////////////////////////////////////////////////////////////////////
  331. /*---------------------------------------------------------------------------
  332. CmdSetupDefaultParameters
  333. Setup default parameters. For now, it only sets default ProductVersion value.
  334. ---------------------------------------------------------------------------*/
  335. #define MAKE_STR(a) #a
  336. #define MAKE_VERSTR(a, b, c, d) MAKE_STR(a.b.c.d)
  337. #define VERRES_VERSIONSTR MAKE_VERSTR(VERRES_VERSION_MAJOR, VERRES_VERSION_MINOR, VERRES_VERSION_BUILD, VERRES_VERSION_REVISION)
  338. BOOL CmdSetupDefaultParameters()
  339. {
  340. _stscanf(TEXT(VERRES_VERSIONSTR), TEXT("%d.%d.%d.%d"), &g_dwMajorVersion, &g_dwMiddleVersion, &g_dwMinorVersion, &g_dwBuildNumber);
  341. wsprintf(g_szVersionKeyCur, "%s\\%d.%d\\%s", g_szVersionKey, g_dwMajorVersion, g_dwMiddleVersion, g_szVersion);
  342. DebugLog(TEXT("CmdSetupDefaultParameters: Version Info : %d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
  343. return(TRUE);
  344. }
  345. /*---------------------------------------------------------------------------
  346. CmdSetVersion
  347. Overwrites default ProductVersion value with value provided in script file.
  348. ---------------------------------------------------------------------------*/
  349. BOOL CmdSetVersion(LPCTSTR szParam)
  350. {
  351. int iNum = _stscanf(szParam, TEXT("%d.%d.%d.%d"), &g_dwMajorVersion, &g_dwMiddleVersion, &g_dwMinorVersion, &g_dwBuildNumber);
  352. wsprintf(g_szVersionKeyCur, "%s\\%d.%d\\%s", g_szVersionKey, g_dwMajorVersion, g_dwMiddleVersion, g_szVersion);
  353. if (iNum == 4)
  354. {
  355. DebugLog(TEXT("CmdSetVersion: Version Info : %d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
  356. return(TRUE);
  357. }
  358. else
  359. {
  360. ErrorLog(TEXT("CmdSetVersion: Failed to retrieve version number from string [%s]"), szParam);
  361. wsprintf(g_szErrorMessage, TEXT("CmdSetVersion: Failed to retrieve version number from string [%s]"), szParam);
  362. return(FALSE);
  363. }
  364. }
  365. /*---------------------------------------------------------------------------
  366. CmdFileList
  367. Add file to the file list. Files in the file list will be deleted when they become no longer needed.
  368. ---------------------------------------------------------------------------*/
  369. BOOL CmdFileList(LPCTSTR szFormat)
  370. {
  371. FLE flElem;
  372. TCHAR szExpandedFileName[MAX_PATH];
  373. flElem.fRemoved = FALSE;
  374. StringCchCopy(flElem.szFileName, MAX_PATH, szFormat);
  375. if (ExpandEnvironmentStrings(flElem.szFileName, szExpandedFileName, sizeof(szExpandedFileName)/sizeof(TCHAR)))
  376. StringCchCopy(flElem.szFileName, MAX_PATH, szExpandedFileName);
  377. // Add the element to file list set.
  378. if (g_FileList.insert(flElem).second)
  379. DebugLog(TEXT("Add to CmdFileList \"%s\" -> Added."), szFormat);
  380. else
  381. ErrorLog(TEXT("Add to CmdFileList \"%s\" -> Not added. Duplicate?"), szFormat);
  382. return(TRUE);
  383. }
  384. /*---------------------------------------------------------------------------
  385. CmdPreSetupCheck
  386. Check whether the newer IME has been installed.
  387. Return TRUE when we can proceed.
  388. !!! FALSE will terminates setup. !!!
  389. ---------------------------------------------------------------------------*/
  390. BOOL CmdPreSetupCheck(LPCTSTR szParam)
  391. {
  392. HKEY hKey;
  393. TCHAR szInstalledVersionString[30];
  394. DWORD cbInstalledVersionString = sizeof(szInstalledVersionString);
  395. DWORD dwInstalledMajorVersion, dwInstalledMiddleVersion, dwInstalledMinorVersion, dwInstalledBuildNumber;
  396. BOOL fResult = TRUE;
  397. RestoreMajorVersionRegistry();
  398. //
  399. // root
  400. //
  401. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
  402. {
  403. cbInstalledVersionString = sizeof(szInstalledVersionString);
  404. RegQueryValueEx(hKey, g_szVersion, NULL, NULL, (LPBYTE)szInstalledVersionString, &cbInstalledVersionString);
  405. if (_stscanf(szInstalledVersionString, TEXT("%d.%d"), &dwInstalledMajorVersion, &dwInstalledMiddleVersion) == 2)
  406. {
  407. if (VersionComparison2(g_dwMajorVersion, g_dwMiddleVersion) < VersionComparison2(dwInstalledMajorVersion, dwInstalledMiddleVersion))
  408. {
  409. DebugLog(TEXT("Newer version of IME has been already installed."));
  410. wsprintf(g_szErrorMessage, TEXT("Newer version of IME has been already installed. but, continue to setup"));
  411. g_fExistNewerVersion = TRUE;
  412. }
  413. }
  414. RegCloseKey(hKey);
  415. }
  416. //
  417. // current
  418. //
  419. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKeyCur, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  420. {
  421. cbInstalledVersionString = sizeof(szInstalledVersionString);
  422. RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)szInstalledVersionString, &cbInstalledVersionString);
  423. if (_stscanf(szInstalledVersionString, TEXT("%d.%d.%d.%04d"),
  424. &dwInstalledMajorVersion, &dwInstalledMiddleVersion, &dwInstalledMinorVersion, &dwInstalledBuildNumber) == 4)
  425. {
  426. if ( VersionComparison4(g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber)
  427. < VersionComparison4(dwInstalledMajorVersion, dwInstalledMiddleVersion, dwInstalledMinorVersion, dwInstalledBuildNumber))
  428. {
  429. DebugLog(TEXT("Newer version of IME has been already installed."));
  430. wsprintf(g_szErrorMessage, TEXT("Newer version of IME has been already installed."));
  431. fResult = FALSE;
  432. }
  433. }
  434. RegCloseKey(hKey);
  435. }
  436. return(fResult);
  437. }
  438. /*---------------------------------------------------------------------------
  439. CmdRenamePEFile
  440. Rename file with PE format version comparison.
  441. ---------------------------------------------------------------------------*/
  442. BOOL CmdRenamePEFile(LPCTSTR szParam)
  443. {
  444. TCHAR szSrc[MAX_PATH], szDst[MAX_PATH];
  445. TCHAR szExpandedSrc[MAX_PATH], szExpandedDst[MAX_PATH];
  446. LPTSTR szHitPtr;
  447. DWORD dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
  448. DWORD dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber;
  449. DWORD dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber;
  450. szHitPtr = _tcschr(szParam, TEXT(','));
  451. if (szHitPtr == NULL)
  452. {
  453. ErrorLog(TEXT("CmdRenamePEFile: Invalid parameters (%s)"), szParam);
  454. wsprintf(g_szErrorMessage, TEXT("CmdRenamePEFile: Invalid parameters (%s)"), szParam);
  455. return(FALSE);
  456. }
  457. *szHitPtr = 0;
  458. StringCchCopy(szSrc, ARRAYSIZE(szSrc), szParam);
  459. StringCchCopy(szDst, ARRAYSIZE(szDst), szHitPtr + 1); // Here, szDst may contain optional parameter.
  460. szHitPtr = _tcschr(szDst, TEXT(','));
  461. if (NULL != szHitPtr)
  462. {
  463. *szHitPtr = 0;
  464. _stscanf(szHitPtr + 1, TEXT("%d"), &dwFileAttributes);
  465. }
  466. TrimString(szSrc);
  467. TrimString(szDst);
  468. ExpandEnvironmentStrings(szSrc, szExpandedSrc, sizeof(szExpandedSrc));
  469. ExpandEnvironmentStrings(szDst, szExpandedDst, sizeof(szExpandedDst));
  470. DebugLog(TEXT("CmdRenamePEFile: szExpandedSrc = %s, szExpandedDst = %s"), szExpandedSrc, szExpandedDst);
  471. GetPEFileVersion(szExpandedSrc, &dwSrcMajorVersion, &dwSrcMiddleVersion, &dwSrcMinorVersion, &dwSrcBuildNumber);
  472. GetPEFileVersion(szExpandedDst, &dwDstMajorVersion, &dwDstMiddleVersion, &dwDstMinorVersion, &dwDstBuildNumber);
  473. DebugLog(TEXT("SrcVersion: (%d.%d.%d.%d), DstVersion: (%d.%d.%d.%d)"), dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber,
  474. dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber);
  475. if (VersionComparison4(0, 0, 0, 0) == VersionComparison4(dwSrcMajorVersion, dwSrcMinorVersion, dwSrcMiddleVersion, dwSrcBuildNumber))
  476. ErrorLog(TEXT("Version of source file (%s) is 0.0.0.0. May be file not found."), szSrc);
  477. if(VersionComparison4(dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber) <
  478. VersionComparison4(dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber))
  479. {
  480. DebugLog(TEXT("CmdRenamePEFile: Source version is less than Destination. Copy skipped and Source will be deleted."));
  481. if(DeleteFile(szSrc))
  482. {
  483. FLE fleKey;
  484. StringCchCopy(fleKey.szFileName, MAX_PATH, szSrc);
  485. g_FileList.erase(fleKey);
  486. }
  487. else
  488. DebugLog(TEXT("CmdRenamePEFile: Failed to delete Source file (%s)"), szSrc);
  489. }
  490. else
  491. {
  492. DebugLog(TEXT("CmdRenamePEFile: Invoke ActRenameFile"));
  493. ActRenameFile(szSrc, szDst, dwFileAttributes);
  494. }
  495. return(TRUE);
  496. }
  497. /*---------------------------------------------------------------------------
  498. CmdRenameFile
  499. Rename file without version comparison
  500. ---------------------------------------------------------------------------*/
  501. BOOL CmdRenameFile(LPCTSTR szParam)
  502. {
  503. TCHAR szSrc[MAX_PATH], szDst[MAX_PATH];
  504. TCHAR szExpandedSrc[MAX_PATH], szExpandedDst[MAX_PATH];
  505. LPTSTR szHitPtr;
  506. DWORD dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
  507. szHitPtr = _tcschr(szParam, TEXT(','));
  508. if (szHitPtr == NULL)
  509. {
  510. ErrorLog(TEXT("CmdRenameFile: Invalid parameters (%s)"), szParam);
  511. wsprintf(g_szErrorMessage, TEXT("CmdRenameFile: Invalid parameters (%s)"), szParam);
  512. return(FALSE);
  513. }
  514. *szHitPtr = 0;
  515. StringCchCopy(szSrc, ARRAYSIZE(szSrc), szParam);
  516. StringCchCopy(szDst, ARRAYSIZE(szDst), szHitPtr + 1); // Here, szDst may contain optional parameter.
  517. szHitPtr = _tcschr(szDst, TEXT(','));
  518. if (szHitPtr != NULL)
  519. {
  520. *szHitPtr = 0;
  521. _stscanf(szHitPtr + 1, TEXT("%d"), &dwFileAttributes);
  522. }
  523. TrimString(szSrc);
  524. TrimString(szDst);
  525. ExpandEnvironmentStrings(szSrc, szExpandedSrc, sizeof(szExpandedSrc));
  526. ExpandEnvironmentStrings(szDst, szExpandedDst, sizeof(szExpandedDst));
  527. DebugLog(TEXT("RanemeFile: szExpandedSrc = %s, szExpandedDst = %s"), szExpandedSrc, szExpandedDst);
  528. ActRenameFile(szExpandedSrc, szExpandedDst, dwFileAttributes);
  529. return(TRUE);
  530. }
  531. /*---------------------------------------------------------------------------
  532. RegisterIMEWithFixedHKL
  533. ---------------------------------------------------------------------------*/
  534. void RegisterIMEWithFixedHKL(LPCTSTR szHKL, LPCTSTR szIMEFileName, LPCTSTR szIMEName)
  535. {
  536. HKEY hKeyKbdLayout;
  537. HKEY hKeyOneIME;
  538. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  539. TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"),
  540. &hKeyKbdLayout) != ERROR_SUCCESS)
  541. return;
  542. if (RegCreateKey(hKeyKbdLayout,
  543. szHKL,
  544. &hKeyOneIME) != ERROR_SUCCESS)
  545. {
  546. RegCloseKey(hKeyKbdLayout);
  547. return;
  548. }
  549. if (RegSetValueEx(hKeyOneIME,
  550. TEXT("Ime File"),
  551. 0,
  552. REG_SZ,
  553. (CONST BYTE*)szIMEFileName,
  554. (lstrlen(szIMEFileName) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
  555. goto WriteImeLayoutFail;
  556. if (RegSetValueEx(hKeyOneIME,
  557. TEXT("Layout Text"),
  558. 0,
  559. REG_SZ,
  560. (CONST BYTE*)szIMEName,
  561. (lstrlen(szIMEName) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
  562. goto WriteImeLayoutFail;
  563. WriteImeLayoutFail:
  564. RegCloseKey(hKeyOneIME);
  565. RegCloseKey(hKeyKbdLayout);
  566. }
  567. /*---------------------------------------------------------------------------
  568. CmdRegisterInterface
  569. Invoke SelfReg. If given file is DLL, call DllRegisterServer export function. If given file is EXE, run it with "/RegServer"
  570. command line option.
  571. ---------------------------------------------------------------------------*/
  572. typedef HRESULT (STDAPICALLTYPE *pfnDllRegisterServerType)(void);
  573. BOOL CmdRegisterInterface(LPCTSTR szParam)
  574. {
  575. TCHAR szExpandedModulePath[MAX_PATH];
  576. HRESULT hr = S_FALSE;
  577. ExpandEnvironmentStrings(szParam, szExpandedModulePath, sizeof(szExpandedModulePath));
  578. TrimString(szExpandedModulePath);
  579. INT iLen = 0;
  580. iLen = lstrlen(szExpandedModulePath);
  581. if (iLen < 4)
  582. {
  583. ErrorLog(TEXT("CmdRegisterInterface: Too short szExpandedModulePath (%s)"), szExpandedModulePath);
  584. wsprintf(g_szErrorMessage, TEXT("CmdRegisterInterface: Invalid Parameters."));
  585. return(FALSE);
  586. }
  587. if (lstrcmpi(TEXT(".dll"), &szExpandedModulePath[iLen - 4]) == 0)
  588. {
  589. DebugLog(TEXT("CmdRegisterInterface: DLL mode for %s"), szExpandedModulePath);
  590. HINSTANCE hLib = LoadLibrary(szExpandedModulePath);
  591. if (hLib != NULL)
  592. {
  593. pfnDllRegisterServerType pfnDllRegisterServer = (pfnDllRegisterServerType)GetProcAddress(hLib, "DllRegisterServer");
  594. if (pfnDllRegisterServer != NULL)
  595. {
  596. hr = pfnDllRegisterServer();
  597. ErrorLog(TEXT("CmdRegisterInterface: hResult=%x"), hr);
  598. }
  599. FreeLibrary(hLib);
  600. }
  601. }
  602. else
  603. {
  604. if (lstrcmpi(TEXT(".exe"), &szExpandedModulePath[iLen - 4]) == 0)
  605. {
  606. DebugLog(TEXT("CmdRegisterInterface: EXE mode for %s"), szExpandedModulePath);
  607. TCHAR szCommandBuffer[MAX_PATH * 2];
  608. wsprintf(szCommandBuffer, TEXT("%s /RegServer"), szExpandedModulePath);
  609. STARTUPINFO si;
  610. ZeroMemory(&si, sizeof(si));
  611. si.cb = sizeof(si);
  612. si.dwFlags = STARTF_USESHOWWINDOW;
  613. si.wShowWindow = SW_HIDE;
  614. PROCESS_INFORMATION pi;
  615. ZeroMemory(&pi, sizeof(pi));
  616. if (CreateProcess(NULL, szCommandBuffer, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi))
  617. {
  618. DebugLog(TEXT("CmdRegisterInterface: Running \"%s\". Waiting for the process termination."), szCommandBuffer);
  619. WaitForSingleObject(pi.hProcess, INFINITE);
  620. DebugLog(TEXT("CmdRegisterInterface: \"%s\" terminates."), szCommandBuffer);
  621. CloseHandle(pi.hThread);
  622. CloseHandle(pi.hProcess);
  623. hr = S_OK;
  624. }
  625. else
  626. {
  627. DWORD dwError = GetLastError();
  628. ErrorLog(TEXT("CmdRegisterInterface: CreateProcess(\"%s\") failed with error code = %d(%x)"), szCommandBuffer, dwError, dwError);
  629. }
  630. }
  631. else
  632. ErrorLog(TEXT("Cannot detect module type for %s. Skipped."), szExpandedModulePath);
  633. }
  634. return(SUCCEEDED(hr));
  635. }
  636. /*---------------------------------------------------------------------------
  637. CmdRegisterInterfaceWow64
  638. Invoke SelfReg. If given file is DLL, call DllRegisterServer export function. If given file is EXE, run it with "/RegServer"
  639. command line option.
  640. ---------------------------------------------------------------------------*/
  641. BOOL CmdRegisterInterfaceWow64(LPCTSTR szParam)
  642. {
  643. #if defined(_WIN64)
  644. TCHAR szExpandedModulePath[MAX_PATH];
  645. TCHAR szCommandBuffer[MAX_PATH * 2];
  646. STARTUPINFO si;
  647. PROCESS_INFORMATION pi;
  648. ExpandEnvironmentStrings(szParam, szExpandedModulePath, sizeof(szExpandedModulePath));
  649. TrimString(szExpandedModulePath);
  650. INT iLen = 0;
  651. iLen = lstrlen(szExpandedModulePath);
  652. if (iLen < 4)
  653. {
  654. ErrorLog(TEXT("CmdRegisterInterfaceWow64: Too short szExpandedModulePath (%s)"), szExpandedModulePath);
  655. wsprintf(g_szErrorMessage, TEXT("CmdRegisterInterface: Invalid Parameters."));
  656. return(FALSE);
  657. }
  658. if (lstrcmpi(TEXT(".dll"), &szExpandedModulePath[iLen - 4]) == 0)
  659. {
  660. // First get systemWow64Directory
  661. TCHAR szSysWow64Dir[MAX_PATH] = TEXT("");
  662. HMODULE hmod = GetModuleHandle(TEXT("kernel32.dll"));
  663. DebugLog(TEXT("CmdRegisterInterfaceWow64: DLL mode for %s"), szExpandedModulePath);
  664. if (hmod == NULL)
  665. {
  666. DebugLog(TEXT("CmdRegisterInterfaceWow64: Faile to load kernel32.dll"));
  667. return (TRUE);
  668. }
  669. UINT (WINAPI* pfnGetSystemWow64Directory)(LPTSTR, UINT);
  670. (FARPROC&)pfnGetSystemWow64Directory = GetProcAddress (hmod, "GetSystemWow64DirectoryA");
  671. if (pfnGetSystemWow64Directory == NULL)
  672. {
  673. DebugLog(TEXT("CmdRegisterInterfaceWow64: Faile to load GetSystemWow64DirectoryA API"));
  674. return (TRUE);
  675. }
  676. /*
  677. * if GetSystemWow64Directory fails and sets the last error to
  678. * ERROR_CALL_NOT_IMPLEMENTED, we're on a 32-bit OS
  679. */
  680. if (((pfnGetSystemWow64Directory)(szSysWow64Dir, ARRAYSIZE(szSysWow64Dir)) == 0) &&
  681. (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
  682. {
  683. DebugLog(TEXT("CmdRegisterInterfaceWow64: Failed to load GetSystemWow64DirectoryA API"));
  684. return (TRUE);
  685. }
  686. wsprintf(szCommandBuffer, TEXT("%s\\regsvr32.exe \"%s\" /s"), szSysWow64Dir, szExpandedModulePath);
  687. }
  688. else
  689. if (lstrcmpi(TEXT(".exe"), &szExpandedModulePath[iLen - 4]) == 0)
  690. {
  691. DebugLog(TEXT("CmdRegisterInterfaceWow64: EXE mode for %s"), szExpandedModulePath);
  692. wsprintf(szCommandBuffer, TEXT("\"%s\" /RegServer"), szExpandedModulePath);
  693. }
  694. else
  695. {
  696. ErrorLog(TEXT("Cannot detect module type for %s. Skipped."), szExpandedModulePath);
  697. // Return true not to stop further processing.
  698. return (TRUE);
  699. }
  700. ZeroMemory(&si, sizeof(si));
  701. si.cb = sizeof(si);
  702. si.dwFlags = STARTF_USESHOWWINDOW;
  703. si.wShowWindow = SW_HIDE;
  704. ZeroMemory(&pi, sizeof(pi));
  705. if (CreateProcess(NULL, szCommandBuffer, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi))
  706. {
  707. DebugLog(TEXT("CmdRegisterInterfaceWow64: Running \"%s\". Waiting for the process termination."), szCommandBuffer);
  708. WaitForSingleObject(pi.hProcess, INFINITE);
  709. DebugLog(TEXT("CmdRegisterInterfaceWow64: \"%s\" terminates."), szCommandBuffer);
  710. CloseHandle(pi.hThread);
  711. CloseHandle(pi.hProcess);
  712. }
  713. else
  714. {
  715. DWORD dwError = GetLastError();
  716. ErrorLog(TEXT("CmdRegisterInterfaceWow64: CreateProcess(\"%s\") failed with error code = %d(%x)"), szCommandBuffer, dwError, dwError);
  717. }
  718. #endif
  719. return(TRUE);
  720. }
  721. /*---------------------------------------------------------------------------
  722. CmdRegisterIMEandTIP
  723. Register IME using IMM API and TIP
  724. ---------------------------------------------------------------------------*/
  725. BOOL CmdRegisterIMEandTIP(LPCTSTR szParam)
  726. {
  727. TCHAR szIMEFileName[MAX_PATH], szTIPName[MAX_PATH], szTIPNameWow64[MAX_PATH];
  728. TCHAR *szHitPtr;
  729. TCHAR *szHitPtr2;
  730. HKL hIME61KL = 0;
  731. TCHAR szHKL[10];
  732. TCHAR szNonFullPath[MAX_PATH];
  733. HKEY hKey;
  734. szHitPtr = _tcschr(szParam, TEXT(','));
  735. szHitPtr2 = _tcschr(szHitPtr + 1, TEXT(',')); // because there are three parameters
  736. if (szHitPtr2 == NULL)
  737. {
  738. ErrorLog(TEXT("CmdRegisterIMEandTIP: Invalid parameters (%s)"), szParam);
  739. wsprintf(g_szErrorMessage, TEXT("CmdRegisterIMEandTIP: Invalid parameters (%s)"), szParam);
  740. return(FALSE);
  741. }
  742. *szHitPtr = 0;
  743. *szHitPtr2 = 0;
  744. StringCchCopy(szIMEFileName, ARRAYSIZE(szIMEFileName), szParam);
  745. StringCchCopy(szTIPName, ARRAYSIZE(szTIPName), szHitPtr + 1);
  746. StringCchCopy(szTIPNameWow64, ARRAYSIZE(szTIPNameWow64), szHitPtr2 + 1);
  747. TrimString(szIMEFileName);
  748. TrimString(szTIPName);
  749. TrimString(szTIPNameWow64);
  750. ParseEnvVar(szIMEFileName, MAX_PATH);
  751. ParseEnvVar(szTIPName, MAX_PATH);
  752. ParseEnvVar(szTIPNameWow64, MAX_PATH);
  753. DebugLog(TEXT("CmdRegisterIMEandTIP: IMEFileName = %s, TIPFileName = %s szTIPNameWow64 = %s"), szIMEFileName, szTIPName, szTIPNameWow64);
  754. /////////////////////////////////////////////////////////////////////////////
  755. // IME registration
  756. if ((szHitPtr = _tcsrchr(szIMEFileName, TEXT('\\'))) != NULL)
  757. szHitPtr++;
  758. else
  759. szHitPtr = szIMEFileName;
  760. StringCchCopy(szNonFullPath, ARRAYSIZE(szNonFullPath), szHitPtr);
  761. hIME61KL = GetHKLfromHKLM(szNonFullPath);
  762. if (hIME61KL == (HKL)0)
  763. DebugLog(TEXT("CmdRegisterIMEandTIP: hIME61KL is zero %x -- error"), hIME61KL);
  764. //if (hKL && HKLHelp412ExistInPreload(HKEY_CURRENT_USER))
  765. // {
  766. // HKLHelpSetDefaultKeyboardLayout(HKEY_CURRENT_USER, hKL, FALSE);
  767. //hKL = ImmInstallIME(szIMEFileName, szLayoutText);
  768. // }
  769. /////////////////////////////////////////////////////////////////////////////
  770. // TIP registration
  771. // Regster wow64 TIP first to avoid regstry overwrite problem.
  772. RegisterTIPWow64(szTIPNameWow64);
  773. RegisterTIP(szTIPName);
  774. /////////////////////////////////////////////////////////////////////////////
  775. // IME and TIP - make substitution
  776. TCHAR szTIPGuid[MAX_PATH];
  777. TCHAR szLangProfile[MAX_PATH];
  778. CLSIDToStringA(CLSID_KorIMX, szTIPGuid);
  779. DebugLog(TEXT("CmdRegisterIMEandTIP: CLSID_KorIMX guid=%s"), szTIPGuid);
  780. // make a reg key
  781. wsprintf(szLangProfile, SZTIPREG_LANGPROFILE_TEMPLATE, szTIPGuid);
  782. /////////////////////////////////////////////////////////////////////////////
  783. // Add Substitute HKL value to the TIP registry
  784. if (hIME61KL != 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, szLangProfile, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  785. {
  786. TCHAR szSubKeyName[MAX_PATH], szHKL[MAX_PATH];
  787. DWORD dwIndex;
  788. HKEY hSubKey;
  789. wsprintf(szHKL, TEXT("0x%x"), hIME61KL);
  790. dwIndex = 0;
  791. while (RegEnumKey(hKey, dwIndex, szSubKeyName, MAX_PATH) != ERROR_NO_MORE_ITEMS)
  792. {
  793. if (RegOpenKeyEx(hKey,szSubKeyName,0,KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
  794. {
  795. RegSetValueEx(hSubKey, TEXT("SubstituteLayout"), 0,REG_SZ,(BYTE *)szHKL, sizeof(TCHAR)*(lstrlen(szHKL)+1));
  796. RegCloseKey(hSubKey);
  797. }
  798. dwIndex++;
  799. }
  800. RegCloseKey(hKey);
  801. }
  802. #if defined(_WIN64)
  803. // make a reg key
  804. wsprintf(szLangProfile, SZTIPREG_LANGPROFILE_TEMPLATE_WOW64, szTIPGuid);
  805. /////////////////////////////////////////////////////////////////////////////
  806. // Add Substitute HKL value to the TIP registry
  807. if (hIME61KL != 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, szLangProfile, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  808. {
  809. TCHAR szSubKeyName[MAX_PATH], szHKL[MAX_PATH];
  810. DWORD dwIndex;
  811. HKEY hSubKey;
  812. wsprintf(szHKL, TEXT("0x%x"), hIME61KL);
  813. dwIndex = 0;
  814. while (RegEnumKey(hKey, dwIndex, szSubKeyName, MAX_PATH) != ERROR_NO_MORE_ITEMS)
  815. {
  816. if (RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
  817. {
  818. RegSetValueEx(hSubKey, TEXT("SubstituteLayout"), 0, REG_SZ, (BYTE*)szHKL, sizeof(TCHAR)*(lstrlen(szHKL)+1));
  819. RegCloseKey(hSubKey);
  820. }
  821. dwIndex++;
  822. }
  823. RegCloseKey(hKey);
  824. }
  825. #endif
  826. return(TRUE);
  827. }
  828. /*---------------------------------------------------------------------------
  829. CmdRegisterRUNKey
  830. Register package version
  831. ---------------------------------------------------------------------------*/
  832. BOOL CmdRegisterPackageVersion(void)
  833. {
  834. HKEY hKey;
  835. TCHAR szVersionString[30];
  836. // Write RootVersion reg only if this is latest IME.
  837. if (g_fExistNewerVersion == FALSE)
  838. {
  839. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
  840. {
  841. wsprintf(szVersionString, TEXT("%d.%d"), g_dwMajorVersion, g_dwMiddleVersion);
  842. RegSetValueEx(hKey, g_szVersion, 0, REG_SZ, (CONST BYTE *)szVersionString, (lstrlen(szVersionString) + 1) * sizeof(TCHAR));
  843. RegCloseKey(hKey);
  844. }
  845. }
  846. // Current
  847. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKeyCur, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  848. {
  849. wsprintf(szVersionString, TEXT("%d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
  850. RegSetValueEx(hKey, NULL, 0, REG_SZ, (CONST BYTE *)szVersionString, (lstrlen(szVersionString) + 1) * sizeof(TCHAR));
  851. RegCloseKey(hKey);
  852. }
  853. return(TRUE);
  854. }
  855. //
  856. // Register Applet order
  857. //
  858. #define FE_KOREAN // need Korean stuff
  859. #include "../fecommon/imembx/guids.h"
  860. typedef
  861. struct tagAPPLETCLSID
  862. {
  863. const GUID *pguidClsid;
  864. BOOL fNoUIM;
  865. } APPLETCLSID;
  866. typedef
  867. struct tagAPPLETIID
  868. {
  869. const GUID *pguidIID;
  870. } APPLETIID;
  871. /*---------------------------------------------------------------------------
  872. CmdRegisterPadOrder
  873. Not support WOW64.
  874. ---------------------------------------------------------------------------*/
  875. BOOL CmdRegisterPadOrder(void)
  876. {
  877. HKEY hKey;
  878. TCHAR szClsid[MAX_PATH];
  879. TCHAR szKey[MAX_PATH];
  880. static const APPLETCLSID appletClsid[] =
  881. {
  882. { &CLSID_ImePadApplet_MultiBox, FALSE },
  883. {0},
  884. };
  885. static const APPLETIID appletIID[] =
  886. {
  887. { &IID_MultiBox },
  888. {0},
  889. };
  890. //
  891. // Applet clsid
  892. //
  893. for (INT i = 0; appletClsid[i].pguidClsid; i++)
  894. {
  895. CLSIDToStringA(*appletClsid[i].pguidClsid, szClsid);
  896. wsprintf(szKey, TEXT("%s\\%s"), SZAPPLETCLSID, szClsid);
  897. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  898. {
  899. if(appletClsid[i].fNoUIM)
  900. {
  901. DWORD dw = 1;
  902. RegSetValueEx(hKey, TEXT("nouim"), 0, NULL, (BYTE*)&dw, sizeof(DWORD));
  903. }
  904. RegCloseKey(hKey);
  905. }
  906. }
  907. //
  908. // Applet iid
  909. //
  910. TCHAR szSubKey[MAX_PATH];
  911. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZAPPLETIID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  912. {
  913. for (INT i = 0; appletIID[i].pguidIID; i++)
  914. {
  915. CLSIDToStringA(*appletIID[i].pguidIID, szKey);
  916. wsprintf(szSubKey, TEXT("%d"), i);
  917. RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (BYTE*)szKey, (lstrlen(szKey)+1)*sizeof(TCHAR));
  918. }
  919. RegCloseKey(hKey);
  920. }
  921. return(TRUE);
  922. }
  923. /*---------------------------------------------------------------------------
  924. CmdCreateDirectory
  925. ---------------------------------------------------------------------------*/
  926. BOOL CmdCreateDirectory(LPCTSTR szParam)
  927. {
  928. TCHAR szDirectory[MAX_PATH], szExpandedDirectory[MAX_PATH];
  929. StringCchCopy(szDirectory, ARRAYSIZE(szDirectory), szParam);
  930. TrimString(szDirectory);
  931. ExpandEnvironmentStrings(szDirectory, szExpandedDirectory, sizeof(szExpandedDirectory)/sizeof(TCHAR));
  932. CreateDirectory(szExpandedDirectory, NULL);
  933. return(TRUE);
  934. }
  935. /*---------------------------------------------------------------------------
  936. CmdAddToPreload
  937. Add HKL for given IMEFile to current user's preload. The HKL won't become default IME.
  938. ---------------------------------------------------------------------------*/
  939. BOOL CmdAddToPreload(LPCTSTR szParam)
  940. {
  941. TCHAR tszIMEFileName[MAX_PATH];
  942. HKL hKL;
  943. // If there is no Kor IME exist in preload, we shouldn't add Kor IME.
  944. if (!HKLHelp412ExistInPreload(HKEY_CURRENT_USER))
  945. {
  946. DebugLog(TEXT("CmdAddToPreload: No 0412 HKL exist in HKCU\\Preload"));
  947. return TRUE;
  948. }
  949. StringCchCopy(tszIMEFileName, ARRAYSIZE(tszIMEFileName), szParam);
  950. TrimString(tszIMEFileName);
  951. hKL = GetHKLfromHKLM(tszIMEFileName);
  952. DebugLog(TEXT("CmdAddToPreload: Calling SetDefaultKeyboardLayout(HKEY_CURRENT_USER, %x, FALSE)"), hKL);
  953. HKLHelpSetDefaultKeyboardLayout(HKEY_CURRENT_USER, hKL, FALSE);
  954. return(TRUE);
  955. }
  956. /*---------------------------------------------------------------------------
  957. fOldIMEsExist
  958. Register Run regi onl if old IME exist in system.
  959. ---------------------------------------------------------------------------*/
  960. static BOOL fOldIMEsExist()
  961. {
  962. HKL hKL;
  963. static LPCSTR m_szOldIMEs[] =
  964. {
  965. "msime95.ime", // Win 95 IME
  966. "msime95k.ime", // NT 4 IME
  967. "imekr98u.ime", // IME98
  968. "imekr.ime", // Office 10 IME
  969. ""
  970. };
  971. CHAR** ppch = (CHAR**)&m_szOldIMEs[0];
  972. while (ppch && **ppch)
  973. {
  974. hKL = GetHKLfromHKLM(*ppch);
  975. if (hKL)
  976. return TRUE; // existing
  977. ppch++;
  978. }
  979. return FALSE;
  980. }
  981. /*---------------------------------------------------------------------------
  982. DisableTIP60ByDefault
  983. ---------------------------------------------------------------------------*/
  984. VOID DisableTIP60ByDefault()
  985. {
  986. // KorIMX CLSID
  987. // {766A2C14-B226-4fd6-B52A-867B3EBF38D2}
  988. const static CLSID CLSID_KorTIP60 =
  989. {
  990. 0x766A2C14,
  991. 0xB226,
  992. 0x4FD6,
  993. {0xb5, 0x2a, 0x86, 0x7b, 0x3e, 0xbf, 0x38, 0xd2}
  994. };
  995. const static GUID guidProfile60 =
  996. // {E47ABB1E-46AC-45f3-8A89-34F9D706DA83}
  997. {
  998. 0xe47abb1e,
  999. 0x46ac,
  1000. 0x45f3,
  1001. {0x8a, 0x89, 0x34, 0xf9, 0xd7, 0x6, 0xda, 0x83}
  1002. };
  1003. // Set default Tip as for Cicero.
  1004. CoInitialize(NULL);
  1005. ITfInputProcessorProfiles *pProfile;
  1006. HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
  1007. IID_ITfInputProcessorProfiles, (void **) &pProfile);
  1008. if (SUCCEEDED(hr))
  1009. {
  1010. pProfile->EnableLanguageProfileByDefault(CLSID_KorTIP60,
  1011. MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile60, FALSE);
  1012. pProfile->Release();
  1013. }
  1014. else
  1015. {
  1016. OurEnableLanguageProfileByDefault(CLSID_KorTIP60, MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile60, FALSE);
  1017. }
  1018. CoUninitialize();
  1019. }
  1020. /*---------------------------------------------------------------------------
  1021. CmdPrepareMigration
  1022. ---------------------------------------------------------------------------*/
  1023. BOOL CmdPrepareMigration(LPCTSTR szParam)
  1024. {
  1025. // Disable TIP 6.0 from HKLM by default
  1026. // This will handle Office 10 install after Whistler mig exe removed from run reg.
  1027. DisableTIP60ByDefault();
  1028. // First user SID list
  1029. if (MakeSIDList() == FALSE)
  1030. return FALSE;
  1031. //Register IMEKRMIG.EXE to run reg Key on "Software\Microsoft\Windows\CurrentVersion\Run"
  1032. return RegisterRUNKey(szParam);
  1033. }
  1034. /*---------------------------------------------------------------------------
  1035. CmdRegisterHelpDirs
  1036. ---------------------------------------------------------------------------*/
  1037. BOOL CmdRegisterHelpDirs()
  1038. {
  1039. TCHAR szFileNameFullPath[MAX_PATH], szFileName[MAX_PATH];
  1040. LPTSTR szExtension, szFileNamePtr;
  1041. HKEY hKey;
  1042. for (std::set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++)
  1043. {
  1044. StringCchCopy(szFileNameFullPath, ARRAYSIZE(szFileNameFullPath), itFLE->szFileName);
  1045. szExtension = _tcsrchr(szFileNameFullPath, TEXT('.'));
  1046. if (szExtension == NULL)
  1047. continue;
  1048. if (lstrcmpi(szExtension, TEXT(".CHM")) == 0)
  1049. {
  1050. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\HTML Help"), 0, NULL,
  1051. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  1052. {
  1053. szFileNamePtr = _tcsrchr(szFileNameFullPath, TEXT('\\'));
  1054. // Get file name
  1055. StringCchCopy(szFileName, ARRAYSIZE(szFileName), szFileNamePtr+1);
  1056. // Get rid of file name we only need path.
  1057. *(szFileNamePtr+1) = 0;
  1058. RegSetValueEx(hKey, szFileName, 0, REG_SZ, (LPBYTE)szFileNameFullPath, (lstrlen(szFileNameFullPath)+1)*sizeof(TCHAR));
  1059. }
  1060. }
  1061. else
  1062. if (lstrcmpi(szExtension, TEXT(".HLP")) == 0)
  1063. {
  1064. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\Help"), 0, NULL,
  1065. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
  1066. {
  1067. szFileNamePtr = _tcsrchr(szFileNameFullPath, TEXT('\\'));
  1068. // Get file name
  1069. StringCchCopy(szFileName, ARRAYSIZE(szFileName), szFileNamePtr+1);
  1070. // Get rid of file name we only need path.
  1071. *(szFileNamePtr+1) = 0;
  1072. RegSetValueEx(hKey, szFileName, 0, REG_SZ, (LPBYTE)szFileNameFullPath, (lstrlen(szFileNameFullPath)+1)*sizeof(TCHAR));
  1073. }
  1074. }
  1075. }
  1076. return(TRUE);
  1077. }
  1078. /////////////////////////////////////////////////////////////////////////////
  1079. // Private functions
  1080. /////////////////////////////////////////////////////////////////////////////
  1081. //
  1082. // Debug output routine.
  1083. //
  1084. void cdecl LogOutDCPrintf(LPCTSTR lpFmt, va_list va)
  1085. {
  1086. static INT DCLine = 0;
  1087. HDC hDC = GetDC((HWND)0);
  1088. TCHAR sz[512];
  1089. HANDLE hFile;
  1090. DWORD dwWrite;
  1091. wvsprintf(sz, lpFmt, va );
  1092. lstrcat(sz, TEXT("| "));
  1093. TextOut(hDC, 0, DCLine*16, sz, lstrlen(sz));
  1094. if (DCLine++ > 50)
  1095. DCLine = 0;
  1096. hFile = CreateFile(TEXT("\\IMKRINST.LOG"), GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  1097. if (hFile != INVALID_HANDLE_VALUE)
  1098. {
  1099. SetFilePointer(hFile, 0, NULL, FILE_END);
  1100. WriteFile(hFile, sz, lstrlen(sz), &dwWrite, NULL);
  1101. WriteFile(hFile, TEXT("\r\n"), 2, &dwWrite, NULL);
  1102. CloseHandle(hFile);
  1103. }
  1104. ReleaseDC((HWND)0, hDC);
  1105. }
  1106. void DebugLog(LPCTSTR szFormat, ...)
  1107. {
  1108. va_list va;
  1109. va_start(va, szFormat);
  1110. if (g_fDebugLog)
  1111. LogOutDCPrintf(szFormat, va);
  1112. va_end(va);
  1113. }
  1114. void ErrorLog(LPCTSTR szFormat, ...)
  1115. {
  1116. va_list va;
  1117. va_start(va, szFormat);
  1118. if (g_fErrorLog)
  1119. LogOutDCPrintf(szFormat, va);
  1120. va_end(va);
  1121. }
  1122. /*---------------------------------------------------------------------------
  1123. ParseEnvVar
  1124. Evaluate environment variable. Modiry given string.
  1125. ---------------------------------------------------------------------------*/
  1126. INT ParseEnvVar(LPTSTR szBuffer, const UINT arg_nLength)
  1127. {
  1128. INT iTranslated=0, i, j;
  1129. TCHAR *pLParen, *pRParen, *pStart = szBuffer;
  1130. INT nLength = min(arg_nLength, MAX_PATH);
  1131. static TCHAR szInternalBuffer[MAX_PATH*2], szValue[MAX_PATH];
  1132. szInternalBuffer[0] = 0;
  1133. for (i=0; i<nLength; i++)
  1134. {
  1135. if (szBuffer[i] == 0)
  1136. break;
  1137. if (szBuffer[i] == '%')
  1138. {
  1139. pLParen = &(szBuffer[i]);
  1140. pRParen = NULL;
  1141. for (j=1; i+j<nLength; j++)
  1142. {
  1143. if (szBuffer[i+j] == 0)
  1144. break;
  1145. if (szBuffer[i+j] == TEXT('%'))
  1146. {
  1147. pRParen = &(szBuffer[i+j]);
  1148. break;
  1149. }
  1150. }
  1151. if (pRParen)
  1152. {
  1153. *pLParen = 0;
  1154. *pRParen = 0;
  1155. lstrcat(szInternalBuffer, pStart);
  1156. if (GetEnvironmentVariable(pLParen+1, szValue, sizeof(szValue)/sizeof(TCHAR)) == 0)
  1157. {
  1158. lstrcat(szInternalBuffer, TEXT("%"));
  1159. lstrcat(szInternalBuffer, pLParen+1);
  1160. lstrcat(szInternalBuffer, TEXT("%"));
  1161. }
  1162. else
  1163. {
  1164. lstrcat(szInternalBuffer, szValue);
  1165. iTranslated++;
  1166. }
  1167. pStart = pRParen+1;
  1168. i += j;
  1169. }
  1170. }
  1171. }
  1172. if (iTranslated)
  1173. {
  1174. lstrcat(szInternalBuffer, pStart);
  1175. lstrcpyn(szBuffer, szInternalBuffer, arg_nLength);
  1176. }
  1177. return(iTranslated);
  1178. }
  1179. /*---------------------------------------------------------------------------
  1180. TrimString
  1181. Chop head/tail white space from given string. Given string will be modified.
  1182. ---------------------------------------------------------------------------*/
  1183. void TrimString(LPTSTR szString)
  1184. {
  1185. INT iBuffSize = lstrlen(szString) + 1;
  1186. LPTSTR szBuffer = new TCHAR[iBuffSize];
  1187. if (szBuffer != NULL)
  1188. {
  1189. INT iHeadSpace, iTailSpace;
  1190. StringCchCopy(szBuffer, MAX_PATH, szString);
  1191. iHeadSpace = (INT)_tcsspn(szBuffer, TEXT(" \t"));
  1192. _tcsrev(szBuffer);
  1193. iTailSpace = (INT)_tcsspn(szBuffer, TEXT(" \t"));
  1194. _tcsrev(szBuffer);
  1195. szBuffer[lstrlen(szBuffer) - iTailSpace] = 0;
  1196. StringCchCopy(szString, MAX_PATH, szBuffer + iHeadSpace);
  1197. }
  1198. if (szBuffer != NULL)
  1199. {
  1200. delete[] szBuffer;
  1201. szBuffer = NULL;
  1202. }
  1203. }
  1204. /*---------------------------------------------------------------------------
  1205. fExistFile
  1206. ---------------------------------------------------------------------------*/
  1207. BOOL fExistFile(LPCTSTR szFilePath)
  1208. {
  1209. BOOL fResult = TRUE;
  1210. if (GetFileAttributes(szFilePath) == -1)
  1211. fResult = FALSE;
  1212. return(fResult);
  1213. }
  1214. /*---------------------------------------------------------------------------
  1215. ReplaceFileOnReboot
  1216. Writes wininit.ini rename section. Note that this function writes lines in reverse order (down to upper).
  1217. ---------------------------------------------------------------------------*/
  1218. BOOL WINAPI ReplaceFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew)
  1219. {
  1220. if (MoveFileEx(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT))
  1221. return TRUE;
  1222. else
  1223. return FALSE;
  1224. }
  1225. /*---------------------------------------------------------------------------
  1226. GetPEFileVersion
  1227. Get version information from PE format.
  1228. ---------------------------------------------------------------------------*/
  1229. void GetPEFileVersion(LPTSTR szFilePath, DWORD *pdwMajorVersion, DWORD *pdwMiddleVersion, DWORD *pdwMinorVersion, DWORD *pdwBuildNumber)
  1230. {
  1231. *pdwMajorVersion = *pdwMiddleVersion = *pdwMinorVersion = *pdwBuildNumber = 0;
  1232. DWORD dwDummy, dwVerResSize;
  1233. dwVerResSize = GetFileVersionInfoSize(szFilePath, &dwDummy);
  1234. if (dwVerResSize)
  1235. {
  1236. BYTE *pbData = new BYTE[dwVerResSize];
  1237. if (NULL != pbData)
  1238. {
  1239. if(GetFileVersionInfo(szFilePath, 0, dwVerResSize, pbData))
  1240. {
  1241. VS_FIXEDFILEINFO *pffiVersion;
  1242. UINT cbffiVersion;
  1243. if(VerQueryValue(pbData, TEXT("\\"), (LPVOID *)&pffiVersion, &cbffiVersion))
  1244. {
  1245. *pdwMajorVersion = HIWORD(pffiVersion->dwFileVersionMS);
  1246. *pdwMiddleVersion = LOWORD(pffiVersion->dwFileVersionMS);
  1247. *pdwMinorVersion = HIWORD(pffiVersion->dwFileVersionLS);
  1248. *pdwBuildNumber = LOWORD(pffiVersion->dwFileVersionLS);
  1249. }
  1250. }
  1251. }
  1252. if (NULL != pbData)
  1253. {
  1254. delete[] pbData;
  1255. pbData = NULL;
  1256. }
  1257. }
  1258. }
  1259. /*---------------------------------------------------------------------------
  1260. ActRenameFile
  1261. MoveFile. If destination file exists, it will be overwritten. If existing destination file cannot be
  1262. overwritten in this session, file replacement is reserved to be held after rebooting.
  1263. ---------------------------------------------------------------------------*/
  1264. BOOL ActRenameFile(LPCTSTR szSrcPath, LPCTSTR tszDstPath, DWORD dwFileAttributes)
  1265. {
  1266. BOOL fReplaceAfterReboot = FALSE;
  1267. BOOL fResult = TRUE;
  1268. FLE fleKey;
  1269. StringCchCopy(fleKey.szFileName, MAX_PATH, szSrcPath);
  1270. if (g_FileList.end() == g_FileList.find(fleKey))
  1271. ErrorLog(TEXT("ActRenameFile: WARNING: Cannot find source file [%s] in CmdFileList"), szSrcPath);
  1272. if (!fExistFile(szSrcPath))
  1273. {
  1274. ErrorLog(TEXT("ActRenameFile: Source file [%s] doesn't exist."), szSrcPath);
  1275. wsprintf(g_szErrorMessage, TEXT("ActRenameFile: Source file [%s] doesn't exist."), szSrcPath);
  1276. return(FALSE);
  1277. }
  1278. if (fExistFile(tszDstPath))
  1279. {
  1280. SetFileAttributes(tszDstPath, FILE_ATTRIBUTE_NORMAL);
  1281. if(!DeleteFile(tszDstPath))
  1282. {
  1283. DWORD dwError = GetLastError();
  1284. fReplaceAfterReboot = TRUE;
  1285. DebugLog(TEXT("ActRenameFile: Cannot delete destination file [%s] with error code = %d(%x)"), tszDstPath, dwError, dwError);
  1286. }
  1287. }
  1288. if (!fReplaceAfterReboot)
  1289. {
  1290. if(MoveFile(szSrcPath, tszDstPath))
  1291. {
  1292. SetFileAttributes(szSrcPath, dwFileAttributes);
  1293. DebugLog(TEXT("ActRenameFile: MoveFile(%s, %s) succeeded."), szSrcPath, tszDstPath);
  1294. }
  1295. else
  1296. {
  1297. DWORD dwError = GetLastError();
  1298. DebugLog(TEXT("ActRenameFile: MoveFile(%s, %s) failed with error code = %d(%x)."), szSrcPath, tszDstPath, dwError, dwError);
  1299. DebugLog(TEXT("ActRenameFile: Try again with fReplaceAfterReboot."));
  1300. fReplaceAfterReboot = TRUE;
  1301. }
  1302. }
  1303. if (fReplaceAfterReboot)
  1304. {
  1305. SetFileAttributes(szSrcPath, dwFileAttributes); // In this case, change file attributes for Src path.
  1306. ReplaceFileOnReboot(szSrcPath, tszDstPath); // Since this function writes lines in reverse order, deletion of
  1307. DebugLog(TEXT("ActRenameFile: ReplaceFileOnReboot(%s, %s)."), szSrcPath, tszDstPath);
  1308. ReplaceFileOnReboot(tszDstPath, NULL); // tszDstPath will come first.
  1309. DebugLog(TEXT("ActRenameFile: ReplaceFileOnReboot(%s, NULL)."), tszDstPath);
  1310. }
  1311. if (fResult)
  1312. g_FileList.erase(fleKey);
  1313. return(fResult);
  1314. }
  1315. ///////////////////////////////////////////////////////////////////////////////
  1316. // This should sync with SERVER.CPP in TIP folder
  1317. // TIP Categories to be added
  1318. const REGISTERCAT c_rgRegCat[] =
  1319. {
  1320. {&GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &CLSID_KorIMX},
  1321. {&GUID_TFCAT_TIP_KEYBOARD, &CLSID_KorIMX},
  1322. {&GUID_TFCAT_PROPSTYLE_CUSTOM, &GUID_PROP_OVERTYPE},
  1323. {NULL, NULL}
  1324. };
  1325. // TIP Profile name
  1326. const REGTIPLANGPROFILE c_rgProf[] =
  1327. {
  1328. { MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), &GUID_Profile, SZ_TIPDISPNAME, SZ_TIPMODULENAME, (IDI_UNIKOR-IDI_ICONBASE), IDS_PROFILEDESC },
  1329. {0, &GUID_NULL, L"", L"", 0, 0}
  1330. };
  1331. //
  1332. ///////////////////////////////////////////////////////////////////////////////
  1333. /*---------------------------------------------------------------------------
  1334. RegisterTIP
  1335. Write neccessary registry key and values for TIP
  1336. ---------------------------------------------------------------------------*/
  1337. void RegisterTIP(LPCTSTR szTIPName)
  1338. {
  1339. HKEY hKey;
  1340. TCHAR szTIPGuid[MAX_PATH];
  1341. TCHAR szTIPProfileGuid[MAX_PATH];
  1342. TCHAR szSubKey[MAX_PATH];
  1343. DWORD dwValue;
  1344. DebugLog(TEXT("RegisterTIP: (%s)."), szTIPName);
  1345. // Run self reg
  1346. // If self reg fails, run custom TIP registration
  1347. if (!CmdRegisterInterface(szTIPName))
  1348. {
  1349. TCHAR szExpandedTIPPath[MAX_PATH];
  1350. DebugLog(TEXT("RegisterTIP: TIP self reg failed, Run custom reg"));
  1351. // Expand Env var
  1352. ExpandEnvironmentStrings(szTIPName, szExpandedTIPPath, sizeof(szExpandedTIPPath));
  1353. // Register TIP CLSID
  1354. if (!RegisterServer(CLSID_KorIMX, SZ_TIPSERVERNAME, szExpandedTIPPath, TEXT("Apartment"), NULL))
  1355. {
  1356. DebugLog(TEXT("RegisterTIP: RegisterServer failed"));
  1357. return;
  1358. }
  1359. if (!OurRegisterTIP(szExpandedTIPPath, CLSID_KorIMX, SZ_TIPNAME, c_rgProf))
  1360. {
  1361. DebugLog(TEXT("RegisterTIP: szExpandedTIPPath failed"));
  1362. return;
  1363. }
  1364. if (FAILED(OurRegisterCategories(CLSID_KorIMX, c_rgRegCat)))
  1365. {
  1366. DebugLog(TEXT("RegisterTIP: OurRegisterCategories failed"));
  1367. return;
  1368. }
  1369. }
  1370. // Get String format GUIDs
  1371. CLSIDToStringA(CLSID_KorIMX, szTIPGuid);
  1372. CLSIDToStringA(GUID_Profile, szTIPProfileGuid);
  1373. /////////////////////////////////////////////////////////////////////////////
  1374. // If no Kor IME is in .default user.
  1375. // Set HKLM [HKLM\Software\Microsoft\CTF\TIP\TIP classid\LanguageProfile\Language ID\Guid Profile]
  1376. // "Enable" = "0" (DWORD)
  1377. if (RegOpenKeyEx(HKEY_USERS, TEXT(".DEFAULT"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  1378. {
  1379. if (!HKLHelp412ExistInPreload(hKey))
  1380. {
  1381. HKEY hKProfRegKey;
  1382. // Create "Software\Microsoft\CTF\TIP\{CLSID_KorIMX}\LanguageProfile\0x00000412\{CLSID_INPUTPROFILE}"
  1383. wsprintf(szSubKey, TEXT("%s%s\\LanguageProfile\\0x00000412\\%s"), TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\"), szTIPGuid, szTIPProfileGuid);
  1384. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_ALL_ACCESS, &hKProfRegKey) == ERROR_SUCCESS)
  1385. {
  1386. // Enabled
  1387. DebugLog(TEXT("RegisterTIP: IME HKL not exist in HKU\\.Default disable TIP"));
  1388. dwValue= 0;
  1389. RegSetValueEx(hKProfRegKey, TEXT("Enable"), 0, REG_DWORD, (BYTE*)&dwValue, sizeof(dwValue));
  1390. RegCloseKey(hKProfRegKey);
  1391. }
  1392. }
  1393. RegCloseKey(hKey);
  1394. }
  1395. }
  1396. /*---------------------------------------------------------------------------
  1397. RegisterTIPWow64
  1398. Write neccessary registry key and values for TIP
  1399. ---------------------------------------------------------------------------*/
  1400. void RegisterTIPWow64(LPCTSTR szTIPName)
  1401. {
  1402. #if defined(_WIN64)
  1403. // Run just selfreg. Cicero doesn't use "HKLM\Software\Wow6432Node\Microsoft\CTF\TIP\"
  1404. CmdRegisterInterfaceWow64(szTIPName);
  1405. #endif
  1406. }
  1407. ////////////////////////////////////////////////////////////////////////////
  1408. // HKL Helper functions
  1409. ////////////////////////////////////////////////////////////////////////////
  1410. /*---------------------------------------------------------------------------
  1411. GetHKLfromHKLM
  1412. ---------------------------------------------------------------------------*/
  1413. HKL GetHKLfromHKLM(LPTSTR argszIMEFile)
  1414. {
  1415. HKL hklAnswer = 0;
  1416. HKEY hKey, hSubKey;
  1417. DWORD i, cbSubKey, cbIMEFile;
  1418. TCHAR szSubKey[MAX_PATH], szIMEFile[MAX_PATH];
  1419. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\Keyboard Layouts"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  1420. {
  1421. for (i=0; ;i++)
  1422. {
  1423. cbSubKey = MAX_PATH;
  1424. if (RegEnumKeyEx(hKey, i, szSubKey, &cbSubKey, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
  1425. break;
  1426. RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey);
  1427. cbIMEFile=MAX_PATH;
  1428. if (RegQueryValueEx(hSubKey, TEXT("IME File"), NULL, NULL, (LPBYTE)szIMEFile, &cbIMEFile) == ERROR_SUCCESS)
  1429. {
  1430. if (lstrcmpi(argszIMEFile, szIMEFile) == 0)
  1431. {
  1432. RegCloseKey(hSubKey);
  1433. _stscanf(szSubKey, TEXT("%08x"), &hklAnswer);
  1434. break;
  1435. }
  1436. }
  1437. RegCloseKey(hSubKey);
  1438. }
  1439. RegCloseKey(hKey);
  1440. }
  1441. return(hklAnswer);
  1442. }
  1443. /*---------------------------------------------------------------------------
  1444. HKLHelpSetDefaultKeyboardLayout
  1445. ---------------------------------------------------------------------------*/
  1446. void HKLHelpSetDefaultKeyboardLayout(HKEY hKeyHKCU, HKL hKL, BOOL fSetToDefault)
  1447. {
  1448. TCHAR szKL[20];
  1449. BYTE Data[MAX_PATH];
  1450. DWORD cbData;
  1451. TCHAR szSubKey[MAX_PATH];
  1452. HKEY hKey,hSubKey;
  1453. DWORD NumKL;
  1454. wsprintf(szKL, TEXT("%08x"), hKL);
  1455. RegOpenKeyEx(hKeyHKCU, TEXT("Keyboard Layout\\Preload"), 0, KEY_ALL_ACCESS, &hKey);
  1456. RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &NumKL, NULL, NULL, NULL, NULL);
  1457. for (DWORD i=0; i<NumKL; i++)
  1458. {
  1459. wsprintf(szSubKey, TEXT("%d"), i+1);
  1460. cbData = MAX_PATH;
  1461. RegQueryValueEx(hKey, szSubKey, NULL, NULL, Data, &cbData);
  1462. if (lstrcmpi((LPCTSTR)Data, szKL) == 0)
  1463. break;
  1464. }
  1465. // if hKL is not exist create it.
  1466. if (NumKL == i)
  1467. {
  1468. wsprintf(szSubKey, TEXT("%d"), i+1);
  1469. RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (const LPBYTE)szKL, (lstrlen(szKL)+1)*sizeof(TCHAR));
  1470. NumKL++;
  1471. }
  1472. // Set hKL as first, Shift down other.
  1473. if(fSetToDefault)
  1474. {
  1475. for(int j=i; j>0; j--)
  1476. {
  1477. wsprintf(szSubKey, TEXT("%d"),j);
  1478. cbData = MAX_PATH;
  1479. RegQueryValueEx(hKey, szSubKey, NULL, NULL, Data, &cbData);
  1480. wsprintf(szSubKey, TEXT("%d"),j+1);
  1481. RegSetValueEx(hKey, szSubKey, 0, REG_SZ, Data, cbData);
  1482. }
  1483. RegSetValueEx(hKey, TEXT("1"), 0, REG_SZ, (const LPBYTE)szKL, (lstrlen(szKL)+1)*sizeof(TCHAR));
  1484. }
  1485. RegCloseKey(hKey);
  1486. (void)LoadKeyboardLayout(szKL, KLF_ACTIVATE);
  1487. // To activate IME2002 right now without reboot.
  1488. if(fSetToDefault)
  1489. (void)SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKL, SPIF_SENDCHANGE);
  1490. }
  1491. #define MAX_NAME 100
  1492. /*---------------------------------------------------------------------------
  1493. HKLHelp412ExistInPreload
  1494. ---------------------------------------------------------------------------*/
  1495. BOOL HKLHelp412ExistInPreload(HKEY hKeyCU)
  1496. {
  1497. HKEY hKey, hSubKey;
  1498. int i ,j;
  1499. DWORD cbName, cbData;
  1500. CHAR szName[MAX_NAME];
  1501. CHAR szData[MAX_NAME];
  1502. HKL hkl;
  1503. FILETIME ftLastWriteTime;
  1504. BOOL fResult = FALSE;
  1505. if (RegOpenKeyEx(hKeyCU, "Keyboard Layout\\Preload", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  1506. {
  1507. for (j=0; cbName=MAX_NAME, cbData=MAX_NAME, RegEnumValue(hKey, j, szName, &cbName, NULL, NULL, (LPBYTE)szData, &cbData) != ERROR_NO_MORE_ITEMS; j++)
  1508. {
  1509. // See If Korean KL exist. Just compare last LCID part if it's 0x412.
  1510. // IME hkl set 0xE000 on hiword.
  1511. sscanf(szData, "%08x", &hkl);
  1512. if ((HIWORD(hkl) & 0xe000) && LOWORD(hkl) == 0x0412)
  1513. {
  1514. fResult = TRUE;
  1515. break;
  1516. }
  1517. }
  1518. RegCloseKey(hKey);
  1519. }
  1520. return(fResult);
  1521. }
  1522. /*---------------------------------------------------------------------------
  1523. RegisterRUNKey
  1524. Register IME using IMM API and TIP
  1525. ---------------------------------------------------------------------------*/
  1526. BOOL RegisterRUNKey(LPCTSTR szParam)
  1527. {
  1528. TCHAR szKey[MAX_PATH];
  1529. TCHAR szFilename[MAX_PATH];
  1530. TCHAR *szHitPtr;
  1531. HKEY hRunKey;
  1532. szHitPtr = _tcschr(szParam, TEXT(','));
  1533. if (szHitPtr == NULL)
  1534. {
  1535. ErrorLog(TEXT("RegisterRUNKey: Invalid parameters (%s)"), szParam);
  1536. wsprintf(g_szErrorMessage, TEXT("RegisterRUNKey: Invalid parameters (%s)"), szParam);
  1537. return(FALSE);
  1538. }
  1539. *szHitPtr = 0;
  1540. StringCchCopy(szKey, ARRAYSIZE(szKey), szParam);
  1541. StringCchCopy(szFilename, ARRAYSIZE(szFilename), szHitPtr + 1);
  1542. TrimString(szKey);
  1543. TrimString(szFilename);
  1544. ParseEnvVar(szKey, MAX_PATH);
  1545. ParseEnvVar(szFilename, MAX_PATH);
  1546. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRunKey, NULL) == ERROR_SUCCESS)
  1547. {
  1548. RegSetValueEx(hRunKey, szKey, 0, REG_SZ, (CONST BYTE *)szFilename, (lstrlen(szFilename)+1)*sizeof(TCHAR));
  1549. RegCloseKey(hRunKey);
  1550. }
  1551. return(TRUE);
  1552. }
  1553. /*---------------------------------------------------------------------------
  1554. MakeSIDList
  1555. Gets all users' SID and list that in the reg for migration
  1556. ---------------------------------------------------------------------------*/
  1557. BOOL MakeSIDList()
  1558. {
  1559. HKEY hKey, hUserList;
  1560. DWORD i, cbName;
  1561. BOOL fNoMoreSID = FALSE;
  1562. TCHAR szMigRegKey[MAX_PATH], szName[500];
  1563. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"), 0, KEY_READ, &hKey) ==ERROR_SUCCESS)
  1564. {
  1565. StringCchCopy(szMigRegKey, ARRAYSIZE(g_szIMERootKey), g_szIMERootKey);
  1566. lstrcat(szMigRegKey, TEXT("\\MigrateUser"));
  1567. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szMigRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hUserList, NULL) == ERROR_SUCCESS)
  1568. {
  1569. for (i=0; !fNoMoreSID; i++)
  1570. {
  1571. cbName = 500;
  1572. if (RegEnumKeyEx(hKey, i, szName, &cbName, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
  1573. fNoMoreSID = TRUE;
  1574. else
  1575. {
  1576. // Do not add Local Service and Network Service pid
  1577. if (lstrlen(szName) > 8)
  1578. RegSetValueEx(hUserList, szName, 0, REG_SZ, (BYTE *)TEXT(""), sizeof(TCHAR)*2);
  1579. }
  1580. }
  1581. //Change MigrateUser List security settings
  1582. PSECURITY_DESCRIPTOR pSD = CreateSD();
  1583. if (pSD)
  1584. {
  1585. RegSetKeySecurity(hUserList, DACL_SECURITY_INFORMATION, pSD);
  1586. MEMFREE(pSD);
  1587. }
  1588. RegCloseKey(hUserList);
  1589. }
  1590. RegCloseKey(hKey);
  1591. }
  1592. return (TRUE);
  1593. }
  1594. /*---------------------------------------------------------------------------
  1595. RestoreMajorVersionRegistry
  1596. Restore IME major version reg value.
  1597. It could be overwritten during Win9x to NT upgrade.
  1598. ---------------------------------------------------------------------------*/
  1599. void RestoreMajorVersionRegistry()
  1600. {
  1601. HKEY hKey;
  1602. ///////////////////////////////////////////////////////////////////////////
  1603. // Restore IME major version reg value.
  1604. // It could be overwritten during Win9x to NT upgrading.
  1605. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  1606. {
  1607. CHAR szVersion[MAX_PATH];
  1608. DWORD cbVersion = MAX_PATH;
  1609. CHAR szMaxVersion[MAX_PATH];
  1610. FILETIME time;
  1611. float flVersion, flMaxVersion;
  1612. StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), "0");
  1613. for (int i=0; cbVersion = MAX_PATH, RegEnumKeyEx(hKey, i, szVersion, &cbVersion, NULL, NULL, NULL, &time) != ERROR_NO_MORE_ITEMS; i++)
  1614. {
  1615. if (lstrcmp(szVersion, szMaxVersion) > 0)
  1616. StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), szVersion);
  1617. }
  1618. StringCchCopy(szVersion, ARRAYSIZE(szVersion), "0");
  1619. RegQueryValueEx(hKey, g_szVersion, NULL, NULL, (BYTE *)szVersion, &cbVersion);
  1620. flVersion = (float)atof(szVersion);
  1621. flMaxVersion = (float)atof(szMaxVersion);
  1622. if (flVersion < flMaxVersion)
  1623. RegSetValueEx(hKey, g_szVersion, 0, REG_SZ, (BYTE *)szMaxVersion, (sizeof(CHAR)*lstrlen(szMaxVersion)));
  1624. RegCloseKey(hKey);
  1625. }
  1626. ///////////////////////////////////////////////////////////////////////////
  1627. }
  1628. /*---------------------------------------------------------------------------
  1629. CreateSecurityAttributes
  1630. ---------------------------------------------------------------------------*/
  1631. PSECURITY_DESCRIPTOR CreateSD()
  1632. {
  1633. PSECURITY_DESCRIPTOR psd;
  1634. PACL pacl;
  1635. ULONG AclSize;
  1636. PSID psid1, psid2, psid3, psid4;
  1637. BOOL fResult;
  1638. psid1 = MyCreateSid(SECURITY_INTERACTIVE_RID);
  1639. if (psid1 == NULL)
  1640. return NULL;
  1641. psid2 = MyCreateSid(SECURITY_LOCAL_SYSTEM_RID);
  1642. if (psid2 == NULL)
  1643. goto Fail4;
  1644. psid3 = MyCreateSid(SECURITY_SERVICE_RID);
  1645. if (psid3 == NULL)
  1646. goto Fail3;
  1647. psid4 = MyCreateSid(SECURITY_NETWORK_RID);
  1648. if (psid4 == NULL)
  1649. goto Fail2;
  1650. //
  1651. // allocate and initialize an access control list (ACL) that will
  1652. // contain the SIDs we've just created.
  1653. //
  1654. AclSize = sizeof(ACL) +
  1655. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
  1656. GetLengthSid(psid1) +
  1657. GetLengthSid(psid2) +
  1658. GetLengthSid(psid3) +
  1659. GetLengthSid(psid4);
  1660. //
  1661. // allocate and initialize a new security descriptor plus ACL
  1662. //
  1663. psd = MEMALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
  1664. if (psd == NULL)
  1665. {
  1666. return NULL;
  1667. }
  1668. pacl = (PACL)((LPBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  1669. fResult = InitializeAcl(pacl, AclSize, ACL_REVISION);
  1670. if (!fResult)
  1671. {
  1672. goto Fail;
  1673. }
  1674. //
  1675. // adds an access-allowed ACE for interactive users to the ACL
  1676. //
  1677. fResult = AddAccessAllowedAce(pacl,
  1678. ACL_REVISION,
  1679. GENERIC_ALL,
  1680. psid1);
  1681. if (!fResult)
  1682. {
  1683. goto Fail;
  1684. }
  1685. //
  1686. // adds an access-allowed ACE for operating system to the ACL
  1687. //
  1688. fResult = AddAccessAllowedAce(pacl,
  1689. ACL_REVISION,
  1690. GENERIC_ALL,
  1691. psid2);
  1692. if (!fResult)
  1693. {
  1694. goto Fail;
  1695. }
  1696. //
  1697. // adds an access-allowed ACE for operating system to the ACL
  1698. //
  1699. fResult = AddAccessAllowedAce(pacl,
  1700. ACL_REVISION,
  1701. GENERIC_ALL,
  1702. psid3);
  1703. if (!fResult)
  1704. {
  1705. goto Fail;
  1706. }
  1707. //
  1708. // adds an access-allowed ACE for operating system to the ACL
  1709. //
  1710. fResult = AddAccessAllowedAce(pacl,
  1711. ACL_REVISION,
  1712. GENERIC_ALL,
  1713. psid4);
  1714. if (!fResult)
  1715. {
  1716. goto Fail;
  1717. }
  1718. //
  1719. // Let's make sure that our ACL is valid.
  1720. //
  1721. if (!IsValidAcl(pacl))
  1722. {
  1723. goto Fail;
  1724. }
  1725. if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
  1726. {
  1727. goto Fail;
  1728. }
  1729. fResult = SetSecurityDescriptorDacl(psd, fTrue, pacl, fFalse );
  1730. // The discretionary ACL is referenced by, not copied
  1731. // into, the security descriptor. We shouldn't free up ACL
  1732. // after the SetSecurityDescriptorDacl call.
  1733. if (!fResult)
  1734. {
  1735. goto Fail;
  1736. }
  1737. if (!IsValidSecurityDescriptor(psd))
  1738. {
  1739. goto Fail;
  1740. }
  1741. //
  1742. // Those SIDs have been copied into the ACL. We don't need'em any more.
  1743. //
  1744. FreeSid(psid1);
  1745. FreeSid(psid2);
  1746. FreeSid(psid3);
  1747. FreeSid(psid4);
  1748. return psd;
  1749. Fail:
  1750. MEMFREE(psd);
  1751. FreeSid(psid4);
  1752. Fail2:
  1753. FreeSid(psid3);
  1754. Fail3:
  1755. FreeSid(psid2);
  1756. Fail4:
  1757. FreeSid(psid1);
  1758. return NULL;
  1759. }
  1760. PSID MyCreateSid(DWORD dwSubAuthority)
  1761. {
  1762. PSID psid;
  1763. BOOL fResult;
  1764. SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
  1765. //
  1766. // allocate and initialize an SID
  1767. //
  1768. fResult = AllocateAndInitializeSid(&SidAuthority,
  1769. 1,
  1770. dwSubAuthority,
  1771. 0,0,0,0,0,0,0,
  1772. &psid );
  1773. if (!fResult)
  1774. {
  1775. return NULL;
  1776. }
  1777. if (!IsValidSid(psid))
  1778. {
  1779. FreeSid(psid);
  1780. return NULL;
  1781. }
  1782. return psid;
  1783. }