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.

922 lines
29 KiB

  1. /****************************************************************************
  2. WINMAIN.CPP : Per-user migration and reg install
  3. History:
  4. 22-SEP-2000 CSLim Created
  5. ****************************************************************************/
  6. #include "private.h"
  7. #include <shlobj.h>
  8. #include "hklhelp.h"
  9. #include "msctf.h"
  10. #include <initguid.h>
  11. #include "common.h"
  12. #define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x)
  13. #define MEMFREE(x) LocalFree(x)
  14. // Current Major version. Whistler has IME 6.1
  15. #define MAJORVER "6.1"
  16. // IME 6.1 main module
  17. #define SZMODULENAME_MAIN "imekr61.ime"
  18. #define IME_REGISTRY_MIGRATION "IMEKRMIG6.1"
  19. extern BOOL WINAPI IsNT();
  20. // Private functions
  21. static void MigrateUserData(HKEY hKeyCurrentUser);
  22. static void WriteHKCUData(HKEY hKeyCurrentUser);
  23. static BOOL IsNewerAppsIMEExist();
  24. static VOID EnableTIPByDefault(GUID clsidTIP, GUID guidProfile, BOOL fEnable);
  25. static VOID EnableTIP(GUID clsidTIP, GUID guidProfile, BOOL fEnable);
  26. static VOID DisableTIP61();
  27. static VOID DisableTIP60();
  28. static PSID KYGetCurrentSID();
  29. static BOOL GetTextualSid(PSID pSid, LPSTR TextualSid, LPDWORD dwBufferLen);
  30. static void GetSIDString(LPSTR tszBuffer, SIZE_T cbBuffLen);
  31. static POSVERSIONINFO GetVersionInfo();
  32. static void CheckForDeleteRunReg();
  33. static DWORD OpenUserKeyForWin9xUpgrade(LPSTR pszUserKeyA, HKEY *phKey);
  34. static void RestoreMajorVersionRegistry();
  35. static PSECURITY_DESCRIPTOR CreateSD();
  36. static PSID MyCreateSid(DWORD dwSubAuthority);
  37. /*---------------------------------------------------------------------------
  38. WinMain
  39. ---------------------------------------------------------------------------*/
  40. INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
  41. {
  42. HKEY hKeyCurrentUser = NULL, hKey = NULL;
  43. TCHAR szMigrateUserKey[MAX_PATH];
  44. TCHAR szBuffer[500];
  45. HKL hKL;
  46. BOOL fMigrationAlreadyDone = FALSE;
  47. BOOL fWin9xMig = FALSE;
  48. if (lpCmdLine)
  49. {
  50. LPSTR sz_Arg1 = NULL;
  51. LPSTR sz_Arg2 = NULL;
  52. sz_Arg1 = strtok(lpCmdLine, " \t");
  53. sz_Arg2 = strtok(NULL, " \t");
  54. if (lstrcmpi(sz_Arg1, "Win9xMig") == 0)
  55. {
  56. OpenUserKeyForWin9xUpgrade(sz_Arg2, &hKeyCurrentUser);
  57. if (hKeyCurrentUser != NULL)
  58. fWin9xMig = TRUE;
  59. }
  60. }
  61. if (hKeyCurrentUser == NULL)
  62. hKeyCurrentUser = HKEY_CURRENT_USER;
  63. StringCchCopy(szMigrateUserKey, ARRAYSIZE(szMigrateUserKey), g_szIMERootKey);
  64. StringCchCat(szMigrateUserKey, ARRAYSIZE(szMigrateUserKey), "\\MigrateUser");
  65. // Check Migrated flag
  66. if (RegOpenKeyEx(hKeyCurrentUser, g_szIMERootKey, 0, KEY_ALL_ACCESS, &hKey)== ERROR_SUCCESS )
  67. {
  68. if (RegQueryValueEx(hKey, "Migrated", NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  69. fMigrationAlreadyDone = TRUE;
  70. else
  71. fMigrationAlreadyDone = FALSE;
  72. RegCloseKey(hKey);
  73. }
  74. // if sid exists under HKLM\Software\Microsoft\IMEKR\6.1\MigrateUser migrate and delete sid from reg
  75. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateUserKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  76. {
  77. GetSIDString(szBuffer, sizeof(szBuffer)); // get the sid of the current user
  78. if (RegQueryValueEx(hKey, szBuffer, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  79. {
  80. HKEY hKeyRW;
  81. // Get R/W access again.
  82. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateUserKey, 0, KEY_ALL_ACCESS, &hKeyRW) == ERROR_SUCCESS)
  83. {
  84. // Delete current user's sid
  85. RegDeleteValue(hKeyRW, szBuffer);
  86. // Change MigrateUser List security settings
  87. PSECURITY_DESCRIPTOR pSD = CreateSD();
  88. if (pSD)
  89. {
  90. RegSetKeySecurity(hKeyRW, DACL_SECURITY_INFORMATION, pSD);
  91. MEMFREE(pSD);
  92. }
  93. RegCloseKey(hKeyRW);
  94. }
  95. }
  96. else
  97. fMigrationAlreadyDone = TRUE;
  98. RegCloseKey(hKey);
  99. }
  100. // If no more user list for migration, delete run reg.
  101. if (!fWin9xMig)
  102. CheckForDeleteRunReg();
  103. // in, Lab06 2643 build Profilelist NULL when IMKRINST.EXE run.
  104. //if (fMigrationAlreadyDone)
  105. // return (0);
  106. if (!IsNewerAppsIMEExist())
  107. {
  108. if (!fMigrationAlreadyDone || fWin9xMig)
  109. {
  110. // 1. Do migrate
  111. MigrateUserData(hKeyCurrentUser);
  112. // 2. Write any HKCU data
  113. WriteHKCUData(hKeyCurrentUser);
  114. // 3. Clean up HKCU preload reg. (Remove old IME)
  115. hKL = GetHKLfromHKLM(SZMODULENAME_MAIN);
  116. if (hKL && HKLHelp412ExistInPreload(hKeyCurrentUser))
  117. {
  118. AddPreload(hKeyCurrentUser, hKL);
  119. // Enable TIP
  120. EnableTIP(CLSID_KorIMX, GUID_Profile, fTrue);
  121. }
  122. // Set migrated reg
  123. if (RegOpenKeyEx(hKeyCurrentUser, g_szIMERootKey, 0, KEY_ALL_ACCESS, &hKey)== ERROR_SUCCESS )
  124. {
  125. DWORD dwMigrated = 1;
  126. RegSetValueEx(hKey, "Migrated", 0, REG_DWORD, (BYTE *)&dwMigrated, sizeof(DWORD));
  127. RegCloseKey(hKey);
  128. }
  129. }
  130. // !!! WORKAROUND CODE !!!
  131. // Check if IME HKL exist in HKU\.Default, then enable the TIP by default.
  132. // In US Whistler, IME HKL added to "HKU\.Default\KeyboarLayout\Preload" after IMKRINST.EXE run
  133. // But IMKRINST disable KOR TIP if there is no Kor IME in the preload.
  134. // So this code reenable the default setting. Only work when admin right user first logon.
  135. if (RegOpenKeyEx(HKEY_USERS, TEXT(".DEFAULT"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  136. {
  137. if (HKLHelp412ExistInPreload(hKey))
  138. EnableTIPByDefault(CLSID_KorIMX, GUID_Profile, fTrue);
  139. RegCloseKey(hKey);
  140. }
  141. // !!! End of WORKAROUND CODE !!!
  142. // If IME 6.0 TIP(Office 10 IME) exist in system, Disable it.
  143. DisableTIP60();
  144. }
  145. else
  146. {
  147. // Remove IME 6.1 from Preload
  148. hKL = GetHKLfromHKLM(SZMODULENAME_MAIN);
  149. HKLHelpRemoveFromPreload(hKeyCurrentUser, hKL);
  150. DisableTIP61();
  151. }
  152. if (hKeyCurrentUser != HKEY_CURRENT_USER)
  153. RegCloseKey(hKeyCurrentUser);
  154. return(0);
  155. }
  156. //////////////////////////////////////////////////////////////////////////////
  157. // Private functions
  158. //////////////////////////////////////////////////////////////////////////////
  159. /*---------------------------------------------------------------------------
  160. MigrateUserData
  161. This function migrate BeolSik and K1 Hanja setting
  162. Search IME98, Win95 IME, NT4 IME and AIME reg.
  163. ---------------------------------------------------------------------------*/
  164. void MigrateUserData(HKEY hKeyCurrentUser)
  165. {
  166. const INT iMaxIMERegKeys = 5;
  167. static LPSTR rgszOldIMERegKeys[iMaxIMERegKeys] =
  168. {
  169. // IME 2002(6.0)
  170. "Software\\Microsoft\\IMEKR\\6.0",
  171. // IME98
  172. "Software\\Microsoft\\Windows\\CurrentVersion\\IME\\Korea\\IMEKR98U",
  173. // Win95 IME
  174. "Software\\Microsoft\\Windows\\CurrentVersion\\MSIME95",
  175. // Kor NT4 IME
  176. "Software\\Microsoft\\Windows\\CurrentVersion\\MSIME95K",
  177. // Korean AIME
  178. "Software\\Microsoft\\Windows\\CurrentVersion\\Wansung"
  179. };
  180. // Beolsik value
  181. static CHAR szBeolsik[] = "InputMethod";
  182. // K1 Hanja enable(IME98 only)
  183. static CHAR szEnableK1Hanja[] = "KSC5657";
  184. HKEY hKey;
  185. DWORD dwCb, dwIMEKL, dwKSC5657;
  186. // Set default values
  187. dwIMEKL = dwKSC5657 = 0;
  188. for (INT i=0; i<iMaxIMERegKeys; i++)
  189. {
  190. if (RegOpenKeyEx(hKeyCurrentUser, rgszOldIMERegKeys[i], 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  191. {
  192. ///////////////////////////////////////////////////////////////////
  193. // Get Beolsik
  194. dwCb = sizeof(dwIMEKL);
  195. if (RegQueryValueEx(hKey, szBeolsik, NULL, NULL, (LPBYTE)&dwIMEKL, &dwCb) != ERROR_SUCCESS)
  196. {
  197. dwIMEKL = 0;
  198. }
  199. ///////////////////////////////////////////////////////////////////
  200. // Get K1 Hanja Setting
  201. dwCb = sizeof(dwKSC5657);
  202. if (RegQueryValueEx(hKey, szEnableK1Hanja, NULL, NULL, (LPBYTE)&dwKSC5657, &dwCb) != ERROR_SUCCESS)
  203. {
  204. dwKSC5657 = 0;
  205. }
  206. RegCloseKey(hKey);
  207. // Break for loop
  208. break;
  209. }
  210. }
  211. // Set values to IME2002 reg
  212. if (RegCreateKey(hKeyCurrentUser, g_szIMERootKey, &hKey) == ERROR_SUCCESS)
  213. {
  214. // 1. BeolSik
  215. dwCb = sizeof(dwIMEKL);
  216. if (dwIMEKL >= 100 && dwIMEKL <= 102)
  217. dwIMEKL -= 100;
  218. else
  219. if (dwIMEKL > 2) // Only accept 0, 1, 2
  220. dwIMEKL = 0;
  221. RegSetValueEx(hKey, szBeolsik, 0, REG_DWORD, (LPBYTE)&dwIMEKL, dwCb);
  222. // K1 Hanja flag
  223. if (dwKSC5657 != 0 && dwKSC5657 != 1) // Only accept 0 or 1
  224. dwKSC5657 = 0;
  225. RegSetValueEx(hKey, szEnableK1Hanja, 0, REG_DWORD, (LPBYTE)&dwKSC5657, dwCb);
  226. RegCloseKey(hKey);
  227. }
  228. }
  229. /*---------------------------------------------------------------------------
  230. WriteHKCUData
  231. ---------------------------------------------------------------------------*/
  232. void WriteHKCUData(HKEY hKeyCurrentUser)
  233. {
  234. HKEY hKey;
  235. // Set default Tip as for Cicero.
  236. CoInitialize(NULL);
  237. ITfInputProcessorProfiles *pProfile;
  238. HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
  239. IID_ITfInputProcessorProfiles, (void **) &pProfile);
  240. if (SUCCEEDED(hr))
  241. {
  242. pProfile->SetDefaultLanguageProfile(MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT),
  243. CLSID_KorIMX, GUID_Profile);
  244. pProfile->Release();
  245. }
  246. CoUninitialize();
  247. // Reset Show Status
  248. if (RegOpenKeyEx(hKeyCurrentUser, "Control Panel\\Input Method", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  249. {
  250. LPSTR szStatus = "1";
  251. RegSetValueEx(hKey, "Show Status", 0, REG_SZ, (BYTE *)szStatus, (sizeof(CHAR)*lstrlen(szStatus)));
  252. RegCloseKey(hKey);
  253. }
  254. }
  255. /*---------------------------------------------------------------------------
  256. IsNewerAppsIMEExist
  257. ---------------------------------------------------------------------------*/
  258. BOOL IsNewerAppsIMEExist()
  259. {
  260. HKEY hKey;
  261. float flInstalledVersion, flVersion;
  262. CHAR szVersion[MAX_PATH];
  263. DWORD cbVersion = MAX_PATH;
  264. BOOL fNewer = FALSE;
  265. RestoreMajorVersionRegistry();
  266. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  267. {
  268. if (RegQueryValueEx(hKey, "version", NULL, NULL, (BYTE *)szVersion, &cbVersion) == ERROR_SUCCESS)
  269. {
  270. flInstalledVersion = (float)atof(szVersion);
  271. flVersion = (float)atof(MAJORVER);
  272. if (flVersion < flInstalledVersion)
  273. fNewer = TRUE;
  274. }
  275. RegCloseKey(hKey);
  276. }
  277. return fNewer;
  278. }
  279. /*---------------------------------------------------------------------------
  280. DisableTIP60ByDefault
  281. ---------------------------------------------------------------------------*/
  282. VOID EnableTIPByDefault(GUID clsidTIP, GUID guidProfile, BOOL fEnable)
  283. {
  284. // Set default Tip as for Cicero.
  285. CoInitialize(NULL);
  286. ITfInputProcessorProfiles *pProfile;
  287. HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
  288. IID_ITfInputProcessorProfiles, (void **) &pProfile);
  289. if (SUCCEEDED(hr))
  290. {
  291. pProfile->EnableLanguageProfileByDefault(clsidTIP,
  292. MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, fEnable);
  293. pProfile->Release();
  294. }
  295. CoUninitialize();
  296. }
  297. /*---------------------------------------------------------------------------
  298. EnableTip
  299. ---------------------------------------------------------------------------*/
  300. VOID EnableTIP(GUID clsidTIP, GUID guidProfile, BOOL fEnable)
  301. {
  302. // Set default Tip as for Cicero.
  303. CoInitialize(NULL);
  304. ITfInputProcessorProfiles *pProfile;
  305. HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
  306. IID_ITfInputProcessorProfiles, (void **) &pProfile);
  307. if (SUCCEEDED(hr))
  308. {
  309. BOOL fCurEnabled = FALSE;
  310. pProfile->IsEnabledLanguageProfile(clsidTIP,
  311. MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, &fCurEnabled);
  312. if (fCurEnabled != fEnable)
  313. pProfile->EnableLanguageProfile(clsidTIP,
  314. MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, fEnable);
  315. pProfile->Release();
  316. }
  317. CoUninitialize();
  318. }
  319. /*---------------------------------------------------------------------------
  320. DisableTip61
  321. ---------------------------------------------------------------------------*/
  322. VOID DisableTIP61()
  323. {
  324. // Disable from HKLM
  325. EnableTIPByDefault(CLSID_KorIMX, GUID_Profile, fFalse); // Actually mig exe was not registered by IMKRINST.EXE if newer apps IME exist.
  326. // Dsiable from HKCU to make sure
  327. EnableTIP(CLSID_KorIMX, GUID_Profile, fFalse);
  328. }
  329. /*---------------------------------------------------------------------------
  330. DisableTip60
  331. ---------------------------------------------------------------------------*/
  332. VOID DisableTIP60()
  333. {
  334. // KorIMX CLSID
  335. // {766A2C14-B226-4fd6-B52A-867B3EBF38D2}
  336. const static CLSID CLSID_KorTIP60 =
  337. {
  338. 0x766A2C14,
  339. 0xB226,
  340. 0x4FD6,
  341. {0xb5, 0x2a, 0x86, 0x7b, 0x3e, 0xbf, 0x38, 0xd2}
  342. };
  343. const static GUID g_guidProfile60 =
  344. // {E47ABB1E-46AC-45f3-8A89-34F9D706DA83}
  345. { 0xe47abb1e,
  346. 0x46ac,
  347. 0x45f3,
  348. {0x8a, 0x89, 0x34, 0xf9, 0xd7, 0x6, 0xda, 0x83}
  349. };
  350. // Disable from HKLM
  351. EnableTIPByDefault(CLSID_KorTIP60, g_guidProfile60, fFalse); // Actually already done by IMKRINST.EXE
  352. // Dsiable from HKCU to make sure
  353. EnableTIP(CLSID_KorTIP60, g_guidProfile60, fFalse);
  354. }
  355. /*---------------------------------------------------------------------------
  356. GetTextualSid
  357. ---------------------------------------------------------------------------*/
  358. BOOL GetTextualSid(PSID pSid, LPSTR TextualSid, LPDWORD dwBufferLen)
  359. {
  360. PSID_IDENTIFIER_AUTHORITY psia;
  361. DWORD dwSubAuthorities;
  362. DWORD dwSidRev=SID_REVISION;
  363. DWORD dwCounter;
  364. DWORD dwSidSize;
  365. if (!IsValidSid(pSid))
  366. return FALSE;
  367. // SidIdentifierAuthority ???
  368. psia=GetSidIdentifierAuthority(pSid);
  369. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  370. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  371. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  372. if (*dwBufferLen < dwSidSize)
  373. {
  374. *dwBufferLen = dwSidSize;
  375. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  376. return FALSE;
  377. }
  378. // S-SID_REVISION
  379. dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
  380. // SidIdentifierAuthority
  381. if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
  382. {
  383. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  384. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  385. (USHORT)psia->Value[0],
  386. (USHORT)psia->Value[1],
  387. (USHORT)psia->Value[2],
  388. (USHORT)psia->Value[3],
  389. (USHORT)psia->Value[4],
  390. (USHORT)psia->Value[5]);
  391. }
  392. else
  393. {
  394. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  395. TEXT("%lu"),
  396. (ULONG)(psia->Value[5] ) +
  397. (ULONG)(psia->Value[4] << 8) +
  398. (ULONG)(psia->Value[3] << 16) +
  399. (ULONG)(psia->Value[2] << 24) );
  400. }
  401. // SidSubAuthorities
  402. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  403. {
  404. dwSidSize += wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
  405. *GetSidSubAuthority(pSid, dwCounter) );
  406. }
  407. return fTrue;
  408. }
  409. /*---------------------------------------------------------------------------
  410. KYGetCurrentSID
  411. ---------------------------------------------------------------------------*/
  412. PSID KYGetCurrentSID()
  413. {
  414. HANDLE hToken = NULL;
  415. BOOL bSuccess;
  416. #define MY_BUFSIZE 512 // highly unlikely to exceed 512 bytes
  417. static UCHAR InfoBuffer[MY_BUFSIZE];
  418. DWORD cbInfoBuffer = MY_BUFSIZE;
  419. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  420. return(NULL);
  421. bSuccess = GetTokenInformation(
  422. hToken,
  423. TokenUser,
  424. InfoBuffer,
  425. cbInfoBuffer,
  426. &cbInfoBuffer
  427. );
  428. if (!bSuccess)
  429. {
  430. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  431. {
  432. //
  433. // alloc buffer and try GetTokenInformation() again
  434. //
  435. CloseHandle(hToken);
  436. return(NULL);
  437. }
  438. else
  439. {
  440. //
  441. // error getting token info
  442. //
  443. CloseHandle(hToken);
  444. return(NULL);
  445. }
  446. }
  447. CloseHandle(hToken);
  448. return(((PTOKEN_USER)InfoBuffer)->User.Sid);
  449. }
  450. /*---------------------------------------------------------------------------
  451. GetSIDString
  452. ---------------------------------------------------------------------------*/
  453. void GetSIDString(LPSTR tszBuffer, SIZE_T cbBuffLen)
  454. {
  455. DWORD cbBuffer = (DWORD)cbBuffLen;
  456. if (!GetTextualSid(KYGetCurrentSID(), tszBuffer, &cbBuffer))
  457. tszBuffer[0] = 0;
  458. }
  459. /*---------------------------------------------------------------------------
  460. GetVersionInfo
  461. ---------------------------------------------------------------------------*/
  462. POSVERSIONINFO GetVersionInfo()
  463. {
  464. static BOOL fFirstCall = fTrue;
  465. static OSVERSIONINFO os;
  466. if (fFirstCall)
  467. {
  468. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  469. if (GetVersionEx(&os))
  470. fFirstCall = fFalse;
  471. }
  472. return &os;
  473. }
  474. /*---------------------------------------------------------------------------
  475. IsNT
  476. ---------------------------------------------------------------------------*/
  477. BOOL WINAPI IsNT()
  478. {
  479. BOOL fResult;
  480. fResult = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT);
  481. return fResult;
  482. }
  483. /*---------------------------------------------------------------------------
  484. CheckForDeleteRunReg
  485. ---------------------------------------------------------------------------*/
  486. void CheckForDeleteRunReg()
  487. {
  488. HKEY hKey, hRunKey;
  489. TCHAR szValueName[MAX_PATH];
  490. TCHAR szMigUserKey[MAX_PATH];
  491. DWORD cbValueName = MAX_PATH;
  492. BOOL fRemoveRunKey = FALSE;
  493. StringCchCopy(szMigUserKey, ARRAYSIZE(szMigUserKey), g_szIMERootKey);
  494. StringCchCat(szMigUserKey, ARRAYSIZE(szMigUserKey), TEXT("\\MigrateUser"));
  495. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigUserKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  496. {
  497. if (RegEnumValue(hKey, 0, szValueName, &cbValueName, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
  498. fRemoveRunKey = TRUE;
  499. RegCloseKey(hKey);
  500. }
  501. else
  502. fRemoveRunKey = TRUE;
  503. if (fRemoveRunKey &&
  504. (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hRunKey)) == ERROR_SUCCESS)
  505. {
  506. RegDeleteValue(hRunKey, IME_REGISTRY_MIGRATION);
  507. RegCloseKey(hRunKey);
  508. }
  509. }
  510. //
  511. // On upgrades from Win9x we are passed a string value representing the
  512. // key under which we'll find the user's Control Panel\Appearance subkey.
  513. // The string is in the form "HKCU\$$$". We first translate the root key
  514. // descriptor into a true root key then pass that root and the "$$$"
  515. // part onto RegOpenKeyEx. This function takes that string and opens
  516. // the associated hive key.
  517. //
  518. DWORD OpenUserKeyForWin9xUpgrade(LPSTR pszUserKeyA, HKEY *phKey)
  519. {
  520. DWORD dwResult = ERROR_INVALID_PARAMETER;
  521. if (NULL != pszUserKeyA && NULL != phKey)
  522. {
  523. typedef struct {
  524. char *pszRootA;
  525. HKEY hKeyRoot;
  526. } REGISTRY_ROOTS, *PREGISTRY_ROOTS;
  527. static REGISTRY_ROOTS rgRoots[] = {
  528. { "HKLM", HKEY_LOCAL_MACHINE },
  529. { "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
  530. { "HKCC", HKEY_CURRENT_CONFIG },
  531. { "HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG },
  532. { "HKU", HKEY_USERS },
  533. { "HKEY_USERS", HKEY_USERS },
  534. { "HKCU", HKEY_CURRENT_USER },
  535. { "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
  536. { "HKCR", HKEY_CLASSES_ROOT },
  537. { "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT }
  538. };
  539. char szUserKeyA[MAX_PATH]; // For a local copy.
  540. LPSTR pszSubKeyA = szUserKeyA;
  541. //
  542. // Make a local copy that we can modify.
  543. //
  544. lstrcpynA(szUserKeyA, pszUserKeyA, ARRAYSIZE(szUserKeyA));
  545. *phKey = NULL;
  546. //
  547. // Find the backslash.
  548. //
  549. while(*pszSubKeyA && '\\' != *pszSubKeyA)
  550. pszSubKeyA++;
  551. if ('\\' == *pszSubKeyA)
  552. {
  553. HKEY hkeyRoot = NULL;
  554. int i;
  555. //
  556. // Replace backslash with nul to separate the root key and
  557. // sub key strings in our local copy of the original argument
  558. // string.
  559. //
  560. *pszSubKeyA++ = '\0';
  561. //
  562. // Now find the true root key in rgRoots[].
  563. //
  564. for (i = 0; i < ARRAYSIZE(rgRoots); i++)
  565. {
  566. if (0 == lstrcmpiA(rgRoots[i].pszRootA, szUserKeyA))
  567. {
  568. hkeyRoot = rgRoots[i].hKeyRoot;
  569. break;
  570. }
  571. }
  572. if (NULL != hkeyRoot)
  573. {
  574. //
  575. // Open the key.
  576. //
  577. dwResult = RegOpenKeyExA(hkeyRoot,
  578. pszSubKeyA,
  579. 0,
  580. KEY_ALL_ACCESS,
  581. phKey);
  582. }
  583. }
  584. }
  585. return dwResult;
  586. }
  587. /*---------------------------------------------------------------------------
  588. RestoreMajorVersionRegistry
  589. Restore IME major version reg value.
  590. It could be overwritten during Win9x to NT upgrade.
  591. ---------------------------------------------------------------------------*/
  592. void RestoreMajorVersionRegistry()
  593. {
  594. HKEY hKey;
  595. ///////////////////////////////////////////////////////////////////////////
  596. // Restore IME major version reg value.
  597. // It could be overwritten during Win9x to NT upgrading.
  598. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  599. {
  600. CHAR szVersion[MAX_PATH];
  601. DWORD cbVersion = MAX_PATH;
  602. CHAR szMaxVersion[MAX_PATH];
  603. FILETIME time;
  604. float flVersion, flMaxVersion;
  605. StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), "0");
  606. for (int i=0; cbVersion = MAX_PATH, RegEnumKeyEx(hKey, i, szVersion, &cbVersion, NULL, NULL, NULL, &time) != ERROR_NO_MORE_ITEMS; i++)
  607. {
  608. if (lstrcmp(szVersion, szMaxVersion) > 0)
  609. StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), szVersion);
  610. }
  611. StringCchCopy(szVersion, ARRAYSIZE(szVersion), "0");
  612. RegQueryValueEx(hKey, g_szVersion, NULL, NULL, (BYTE *)szVersion, &cbVersion);
  613. flVersion = (float)atof(szVersion);
  614. flMaxVersion = (float)atof(szMaxVersion);
  615. if (flVersion < flMaxVersion)
  616. RegSetValueEx(hKey, g_szVersion, 0, REG_SZ, (BYTE *)szMaxVersion, (sizeof(CHAR)*lstrlen(szMaxVersion)));
  617. RegCloseKey(hKey);
  618. }
  619. ///////////////////////////////////////////////////////////////////////////
  620. }
  621. /*---------------------------------------------------------------------------
  622. CreateSecurityAttributes
  623. ---------------------------------------------------------------------------*/
  624. PSECURITY_DESCRIPTOR CreateSD()
  625. {
  626. PSECURITY_DESCRIPTOR psd;
  627. PACL pacl;
  628. ULONG AclSize;
  629. PSID psid1, psid2, psid3, psid4;
  630. BOOL fResult;
  631. psid1 = MyCreateSid(SECURITY_INTERACTIVE_RID);
  632. if (psid1 == NULL)
  633. return NULL;
  634. psid2 = MyCreateSid(SECURITY_LOCAL_SYSTEM_RID);
  635. if (psid2 == NULL)
  636. goto Fail4;
  637. psid3 = MyCreateSid(SECURITY_SERVICE_RID);
  638. if (psid3 == NULL)
  639. goto Fail3;
  640. psid4 = MyCreateSid(SECURITY_NETWORK_RID);
  641. if (psid4 == NULL)
  642. goto Fail2;
  643. //
  644. // allocate and initialize an access control list (ACL) that will
  645. // contain the SIDs we've just created.
  646. //
  647. AclSize = sizeof(ACL) +
  648. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
  649. GetLengthSid(psid1) +
  650. GetLengthSid(psid2) +
  651. GetLengthSid(psid3) +
  652. GetLengthSid(psid4);
  653. //
  654. // allocate and initialize a new security descriptor plus ACL
  655. //
  656. psd = MEMALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
  657. if (psd == NULL)
  658. {
  659. return NULL;
  660. }
  661. pacl = (PACL)((LPBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  662. fResult = InitializeAcl(pacl, AclSize, ACL_REVISION);
  663. if (!fResult)
  664. {
  665. goto Fail;
  666. }
  667. //
  668. // adds an access-allowed ACE for interactive users to the ACL
  669. //
  670. fResult = AddAccessAllowedAce(pacl,
  671. ACL_REVISION,
  672. GENERIC_ALL,
  673. psid1);
  674. if (!fResult)
  675. {
  676. goto Fail;
  677. }
  678. //
  679. // adds an access-allowed ACE for operating system to the ACL
  680. //
  681. fResult = AddAccessAllowedAce(pacl,
  682. ACL_REVISION,
  683. GENERIC_ALL,
  684. psid2);
  685. if (!fResult)
  686. {
  687. goto Fail;
  688. }
  689. //
  690. // adds an access-allowed ACE for operating system to the ACL
  691. //
  692. fResult = AddAccessAllowedAce(pacl,
  693. ACL_REVISION,
  694. GENERIC_ALL,
  695. psid3);
  696. if (!fResult)
  697. {
  698. goto Fail;
  699. }
  700. //
  701. // adds an access-allowed ACE for operating system to the ACL
  702. //
  703. fResult = AddAccessAllowedAce(pacl,
  704. ACL_REVISION,
  705. GENERIC_ALL,
  706. psid4);
  707. if (!fResult)
  708. {
  709. goto Fail;
  710. }
  711. //
  712. // Let's make sure that our ACL is valid.
  713. //
  714. if (!IsValidAcl(pacl))
  715. {
  716. goto Fail;
  717. }
  718. if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
  719. {
  720. goto Fail;
  721. }
  722. fResult = SetSecurityDescriptorDacl(psd, fTrue, pacl, fFalse );
  723. // The discretionary ACL is referenced by, not copied
  724. // into, the security descriptor. We shouldn't free up ACL
  725. // after the SetSecurityDescriptorDacl call.
  726. if (!fResult)
  727. {
  728. goto Fail;
  729. }
  730. if (!IsValidSecurityDescriptor(psd))
  731. {
  732. goto Fail;
  733. }
  734. //
  735. // Those SIDs have been copied into the ACL. We don't need'em any more.
  736. //
  737. FreeSid(psid1);
  738. FreeSid(psid2);
  739. FreeSid(psid3);
  740. FreeSid(psid4);
  741. return psd;
  742. Fail:
  743. MEMFREE(psd);
  744. FreeSid(psid4);
  745. Fail2:
  746. FreeSid(psid3);
  747. Fail3:
  748. FreeSid(psid2);
  749. Fail4:
  750. FreeSid(psid1);
  751. return NULL;
  752. }
  753. PSID MyCreateSid(DWORD dwSubAuthority)
  754. {
  755. PSID psid;
  756. BOOL fResult;
  757. SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
  758. //
  759. // allocate and initialize an SID
  760. //
  761. fResult = AllocateAndInitializeSid(&SidAuthority,
  762. 1,
  763. dwSubAuthority,
  764. 0,0,0,0,0,0,0,
  765. &psid );
  766. if (!fResult)
  767. {
  768. return NULL;
  769. }
  770. if (!IsValidSid(psid))
  771. {
  772. FreeSid(psid);
  773. return NULL;
  774. }
  775. return psid;
  776. }