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
922 lines
29 KiB
/****************************************************************************
|
|
WINMAIN.CPP : Per-user migration and reg install
|
|
|
|
History:
|
|
22-SEP-2000 CSLim Created
|
|
****************************************************************************/
|
|
|
|
#include "private.h"
|
|
#include <shlobj.h>
|
|
#include "hklhelp.h"
|
|
#include "msctf.h"
|
|
|
|
#include <initguid.h>
|
|
#include "common.h"
|
|
|
|
#define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x)
|
|
#define MEMFREE(x) LocalFree(x)
|
|
|
|
// Current Major version. Whistler has IME 6.1
|
|
#define MAJORVER "6.1"
|
|
|
|
// IME 6.1 main module
|
|
#define SZMODULENAME_MAIN "imekr61.ime"
|
|
#define IME_REGISTRY_MIGRATION "IMEKRMIG6.1"
|
|
extern BOOL WINAPI IsNT();
|
|
|
|
// Private functions
|
|
static void MigrateUserData(HKEY hKeyCurrentUser);
|
|
static void WriteHKCUData(HKEY hKeyCurrentUser);
|
|
static BOOL IsNewerAppsIMEExist();
|
|
static VOID EnableTIPByDefault(GUID clsidTIP, GUID guidProfile, BOOL fEnable);
|
|
static VOID EnableTIP(GUID clsidTIP, GUID guidProfile, BOOL fEnable);
|
|
static VOID DisableTIP61();
|
|
static VOID DisableTIP60();
|
|
static PSID KYGetCurrentSID();
|
|
static BOOL GetTextualSid(PSID pSid, LPSTR TextualSid, LPDWORD dwBufferLen);
|
|
static void GetSIDString(LPSTR tszBuffer, SIZE_T cbBuffLen);
|
|
static POSVERSIONINFO GetVersionInfo();
|
|
static void CheckForDeleteRunReg();
|
|
static DWORD OpenUserKeyForWin9xUpgrade(LPSTR pszUserKeyA, HKEY *phKey);
|
|
static void RestoreMajorVersionRegistry();
|
|
static PSECURITY_DESCRIPTOR CreateSD();
|
|
static PSID MyCreateSid(DWORD dwSubAuthority);
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
WinMain
|
|
---------------------------------------------------------------------------*/
|
|
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
|
|
{
|
|
HKEY hKeyCurrentUser = NULL, hKey = NULL;
|
|
TCHAR szMigrateUserKey[MAX_PATH];
|
|
TCHAR szBuffer[500];
|
|
HKL hKL;
|
|
BOOL fMigrationAlreadyDone = FALSE;
|
|
BOOL fWin9xMig = FALSE;
|
|
|
|
if (lpCmdLine)
|
|
{
|
|
LPSTR sz_Arg1 = NULL;
|
|
LPSTR sz_Arg2 = NULL;
|
|
|
|
sz_Arg1 = strtok(lpCmdLine, " \t");
|
|
sz_Arg2 = strtok(NULL, " \t");
|
|
if (lstrcmpi(sz_Arg1, "Win9xMig") == 0)
|
|
{
|
|
OpenUserKeyForWin9xUpgrade(sz_Arg2, &hKeyCurrentUser);
|
|
if (hKeyCurrentUser != NULL)
|
|
fWin9xMig = TRUE;
|
|
}
|
|
}
|
|
|
|
if (hKeyCurrentUser == NULL)
|
|
hKeyCurrentUser = HKEY_CURRENT_USER;
|
|
|
|
StringCchCopy(szMigrateUserKey, ARRAYSIZE(szMigrateUserKey), g_szIMERootKey);
|
|
StringCchCat(szMigrateUserKey, ARRAYSIZE(szMigrateUserKey), "\\MigrateUser");
|
|
|
|
// Check Migrated flag
|
|
if (RegOpenKeyEx(hKeyCurrentUser, g_szIMERootKey, 0, KEY_ALL_ACCESS, &hKey)== ERROR_SUCCESS )
|
|
{
|
|
if (RegQueryValueEx(hKey, "Migrated", NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
fMigrationAlreadyDone = TRUE;
|
|
else
|
|
fMigrationAlreadyDone = FALSE;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// if sid exists under HKLM\Software\Microsoft\IMEKR\6.1\MigrateUser migrate and delete sid from reg
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateUserKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
GetSIDString(szBuffer, sizeof(szBuffer)); // get the sid of the current user
|
|
|
|
if (RegQueryValueEx(hKey, szBuffer, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
HKEY hKeyRW;
|
|
// Get R/W access again.
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateUserKey, 0, KEY_ALL_ACCESS, &hKeyRW) == ERROR_SUCCESS)
|
|
{
|
|
// Delete current user's sid
|
|
RegDeleteValue(hKeyRW, szBuffer);
|
|
|
|
// Change MigrateUser List security settings
|
|
PSECURITY_DESCRIPTOR pSD = CreateSD();
|
|
if (pSD)
|
|
{
|
|
RegSetKeySecurity(hKeyRW, DACL_SECURITY_INFORMATION, pSD);
|
|
MEMFREE(pSD);
|
|
}
|
|
RegCloseKey(hKeyRW);
|
|
}
|
|
}
|
|
else
|
|
fMigrationAlreadyDone = TRUE;
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// If no more user list for migration, delete run reg.
|
|
if (!fWin9xMig)
|
|
CheckForDeleteRunReg();
|
|
|
|
// in, Lab06 2643 build Profilelist NULL when IMKRINST.EXE run.
|
|
//if (fMigrationAlreadyDone)
|
|
// return (0);
|
|
|
|
if (!IsNewerAppsIMEExist())
|
|
{
|
|
if (!fMigrationAlreadyDone || fWin9xMig)
|
|
{
|
|
// 1. Do migrate
|
|
MigrateUserData(hKeyCurrentUser);
|
|
|
|
// 2. Write any HKCU data
|
|
WriteHKCUData(hKeyCurrentUser);
|
|
|
|
// 3. Clean up HKCU preload reg. (Remove old IME)
|
|
hKL = GetHKLfromHKLM(SZMODULENAME_MAIN);
|
|
if (hKL && HKLHelp412ExistInPreload(hKeyCurrentUser))
|
|
{
|
|
AddPreload(hKeyCurrentUser, hKL);
|
|
// Enable TIP
|
|
EnableTIP(CLSID_KorIMX, GUID_Profile, fTrue);
|
|
}
|
|
|
|
// Set migrated reg
|
|
if (RegOpenKeyEx(hKeyCurrentUser, g_szIMERootKey, 0, KEY_ALL_ACCESS, &hKey)== ERROR_SUCCESS )
|
|
{
|
|
DWORD dwMigrated = 1;
|
|
RegSetValueEx(hKey, "Migrated", 0, REG_DWORD, (BYTE *)&dwMigrated, sizeof(DWORD));
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
// !!! WORKAROUND CODE !!!
|
|
// Check if IME HKL exist in HKU\.Default, then enable the TIP by default.
|
|
// In US Whistler, IME HKL added to "HKU\.Default\KeyboarLayout\Preload" after IMKRINST.EXE run
|
|
// But IMKRINST disable KOR TIP if there is no Kor IME in the preload.
|
|
// So this code reenable the default setting. Only work when admin right user first logon.
|
|
if (RegOpenKeyEx(HKEY_USERS, TEXT(".DEFAULT"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (HKLHelp412ExistInPreload(hKey))
|
|
EnableTIPByDefault(CLSID_KorIMX, GUID_Profile, fTrue);
|
|
RegCloseKey(hKey);
|
|
}
|
|
// !!! End of WORKAROUND CODE !!!
|
|
|
|
// If IME 6.0 TIP(Office 10 IME) exist in system, Disable it.
|
|
DisableTIP60();
|
|
}
|
|
else
|
|
{
|
|
// Remove IME 6.1 from Preload
|
|
hKL = GetHKLfromHKLM(SZMODULENAME_MAIN);
|
|
HKLHelpRemoveFromPreload(hKeyCurrentUser, hKL);
|
|
DisableTIP61();
|
|
}
|
|
|
|
if (hKeyCurrentUser != HKEY_CURRENT_USER)
|
|
RegCloseKey(hKeyCurrentUser);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Private functions
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*---------------------------------------------------------------------------
|
|
MigrateUserData
|
|
|
|
This function migrate BeolSik and K1 Hanja setting
|
|
Search IME98, Win95 IME, NT4 IME and AIME reg.
|
|
---------------------------------------------------------------------------*/
|
|
void MigrateUserData(HKEY hKeyCurrentUser)
|
|
{
|
|
const INT iMaxIMERegKeys = 5;
|
|
static LPSTR rgszOldIMERegKeys[iMaxIMERegKeys] =
|
|
{
|
|
// IME 2002(6.0)
|
|
"Software\\Microsoft\\IMEKR\\6.0",
|
|
// IME98
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\IME\\Korea\\IMEKR98U",
|
|
// Win95 IME
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\MSIME95",
|
|
// Kor NT4 IME
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\MSIME95K",
|
|
// Korean AIME
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Wansung"
|
|
};
|
|
|
|
// Beolsik value
|
|
static CHAR szBeolsik[] = "InputMethod";
|
|
// K1 Hanja enable(IME98 only)
|
|
static CHAR szEnableK1Hanja[] = "KSC5657";
|
|
|
|
HKEY hKey;
|
|
DWORD dwCb, dwIMEKL, dwKSC5657;
|
|
|
|
// Set default values
|
|
dwIMEKL = dwKSC5657 = 0;
|
|
|
|
for (INT i=0; i<iMaxIMERegKeys; i++)
|
|
{
|
|
if (RegOpenKeyEx(hKeyCurrentUser, rgszOldIMERegKeys[i], 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
///////////////////////////////////////////////////////////////////
|
|
// Get Beolsik
|
|
dwCb = sizeof(dwIMEKL);
|
|
if (RegQueryValueEx(hKey, szBeolsik, NULL, NULL, (LPBYTE)&dwIMEKL, &dwCb) != ERROR_SUCCESS)
|
|
{
|
|
dwIMEKL = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Get K1 Hanja Setting
|
|
dwCb = sizeof(dwKSC5657);
|
|
if (RegQueryValueEx(hKey, szEnableK1Hanja, NULL, NULL, (LPBYTE)&dwKSC5657, &dwCb) != ERROR_SUCCESS)
|
|
{
|
|
dwKSC5657 = 0;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
// Break for loop
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set values to IME2002 reg
|
|
if (RegCreateKey(hKeyCurrentUser, g_szIMERootKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
// 1. BeolSik
|
|
dwCb = sizeof(dwIMEKL);
|
|
if (dwIMEKL >= 100 && dwIMEKL <= 102)
|
|
dwIMEKL -= 100;
|
|
else
|
|
if (dwIMEKL > 2) // Only accept 0, 1, 2
|
|
dwIMEKL = 0;
|
|
RegSetValueEx(hKey, szBeolsik, 0, REG_DWORD, (LPBYTE)&dwIMEKL, dwCb);
|
|
|
|
// K1 Hanja flag
|
|
if (dwKSC5657 != 0 && dwKSC5657 != 1) // Only accept 0 or 1
|
|
dwKSC5657 = 0;
|
|
RegSetValueEx(hKey, szEnableK1Hanja, 0, REG_DWORD, (LPBYTE)&dwKSC5657, dwCb);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
WriteHKCUData
|
|
---------------------------------------------------------------------------*/
|
|
void WriteHKCUData(HKEY hKeyCurrentUser)
|
|
{
|
|
HKEY hKey;
|
|
|
|
// Set default Tip as for Cicero.
|
|
CoInitialize(NULL);
|
|
|
|
ITfInputProcessorProfiles *pProfile;
|
|
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfiles, (void **) &pProfile);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pProfile->SetDefaultLanguageProfile(MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT),
|
|
CLSID_KorIMX, GUID_Profile);
|
|
pProfile->Release();
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
// Reset Show Status
|
|
if (RegOpenKeyEx(hKeyCurrentUser, "Control Panel\\Input Method", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
LPSTR szStatus = "1";
|
|
|
|
RegSetValueEx(hKey, "Show Status", 0, REG_SZ, (BYTE *)szStatus, (sizeof(CHAR)*lstrlen(szStatus)));
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
IsNewerAppsIMEExist
|
|
---------------------------------------------------------------------------*/
|
|
BOOL IsNewerAppsIMEExist()
|
|
{
|
|
HKEY hKey;
|
|
float flInstalledVersion, flVersion;
|
|
CHAR szVersion[MAX_PATH];
|
|
DWORD cbVersion = MAX_PATH;
|
|
BOOL fNewer = FALSE;
|
|
|
|
RestoreMajorVersionRegistry();
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx(hKey, "version", NULL, NULL, (BYTE *)szVersion, &cbVersion) == ERROR_SUCCESS)
|
|
{
|
|
flInstalledVersion = (float)atof(szVersion);
|
|
flVersion = (float)atof(MAJORVER);
|
|
|
|
if (flVersion < flInstalledVersion)
|
|
fNewer = TRUE;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return fNewer;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
DisableTIP60ByDefault
|
|
---------------------------------------------------------------------------*/
|
|
VOID EnableTIPByDefault(GUID clsidTIP, GUID guidProfile, BOOL fEnable)
|
|
{
|
|
// Set default Tip as for Cicero.
|
|
CoInitialize(NULL);
|
|
|
|
ITfInputProcessorProfiles *pProfile;
|
|
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfiles, (void **) &pProfile);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pProfile->EnableLanguageProfileByDefault(clsidTIP,
|
|
MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, fEnable);
|
|
|
|
pProfile->Release();
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
EnableTip
|
|
---------------------------------------------------------------------------*/
|
|
VOID EnableTIP(GUID clsidTIP, GUID guidProfile, BOOL fEnable)
|
|
{
|
|
// Set default Tip as for Cicero.
|
|
CoInitialize(NULL);
|
|
|
|
ITfInputProcessorProfiles *pProfile;
|
|
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfiles, (void **) &pProfile);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BOOL fCurEnabled = FALSE;
|
|
pProfile->IsEnabledLanguageProfile(clsidTIP,
|
|
MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, &fCurEnabled);
|
|
if (fCurEnabled != fEnable)
|
|
pProfile->EnableLanguageProfile(clsidTIP,
|
|
MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile, fEnable);
|
|
|
|
pProfile->Release();
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
DisableTip61
|
|
---------------------------------------------------------------------------*/
|
|
VOID DisableTIP61()
|
|
{
|
|
// Disable from HKLM
|
|
EnableTIPByDefault(CLSID_KorIMX, GUID_Profile, fFalse); // Actually mig exe was not registered by IMKRINST.EXE if newer apps IME exist.
|
|
// Dsiable from HKCU to make sure
|
|
EnableTIP(CLSID_KorIMX, GUID_Profile, fFalse);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
DisableTip60
|
|
---------------------------------------------------------------------------*/
|
|
VOID DisableTIP60()
|
|
{
|
|
// KorIMX CLSID
|
|
// {766A2C14-B226-4fd6-B52A-867B3EBF38D2}
|
|
const static CLSID CLSID_KorTIP60 =
|
|
{
|
|
0x766A2C14,
|
|
0xB226,
|
|
0x4FD6,
|
|
{0xb5, 0x2a, 0x86, 0x7b, 0x3e, 0xbf, 0x38, 0xd2}
|
|
};
|
|
|
|
const static GUID g_guidProfile60 =
|
|
// {E47ABB1E-46AC-45f3-8A89-34F9D706DA83}
|
|
{ 0xe47abb1e,
|
|
0x46ac,
|
|
0x45f3,
|
|
{0x8a, 0x89, 0x34, 0xf9, 0xd7, 0x6, 0xda, 0x83}
|
|
};
|
|
// Disable from HKLM
|
|
EnableTIPByDefault(CLSID_KorTIP60, g_guidProfile60, fFalse); // Actually already done by IMKRINST.EXE
|
|
// Dsiable from HKCU to make sure
|
|
EnableTIP(CLSID_KorTIP60, g_guidProfile60, fFalse);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
GetTextualSid
|
|
---------------------------------------------------------------------------*/
|
|
BOOL GetTextualSid(PSID pSid, LPSTR TextualSid, LPDWORD dwBufferLen)
|
|
{
|
|
PSID_IDENTIFIER_AUTHORITY psia;
|
|
DWORD dwSubAuthorities;
|
|
DWORD dwSidRev=SID_REVISION;
|
|
DWORD dwCounter;
|
|
DWORD dwSidSize;
|
|
|
|
if (!IsValidSid(pSid))
|
|
return FALSE;
|
|
|
|
// SidIdentifierAuthority ???
|
|
psia=GetSidIdentifierAuthority(pSid);
|
|
|
|
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
|
|
|
|
// S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
|
|
dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
|
|
|
|
if (*dwBufferLen < dwSidSize)
|
|
{
|
|
*dwBufferLen = dwSidSize;
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
|
|
// S-SID_REVISION
|
|
dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
|
|
|
|
// SidIdentifierAuthority
|
|
if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
|
|
{
|
|
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
|
|
TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
|
|
(USHORT)psia->Value[0],
|
|
(USHORT)psia->Value[1],
|
|
(USHORT)psia->Value[2],
|
|
(USHORT)psia->Value[3],
|
|
(USHORT)psia->Value[4],
|
|
(USHORT)psia->Value[5]);
|
|
}
|
|
else
|
|
{
|
|
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
|
|
TEXT("%lu"),
|
|
(ULONG)(psia->Value[5] ) +
|
|
(ULONG)(psia->Value[4] << 8) +
|
|
(ULONG)(psia->Value[3] << 16) +
|
|
(ULONG)(psia->Value[2] << 24) );
|
|
}
|
|
|
|
// SidSubAuthorities
|
|
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
|
|
{
|
|
dwSidSize += wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
|
|
*GetSidSubAuthority(pSid, dwCounter) );
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
KYGetCurrentSID
|
|
---------------------------------------------------------------------------*/
|
|
PSID KYGetCurrentSID()
|
|
{
|
|
HANDLE hToken = NULL;
|
|
BOOL bSuccess;
|
|
#define MY_BUFSIZE 512 // highly unlikely to exceed 512 bytes
|
|
static UCHAR InfoBuffer[MY_BUFSIZE];
|
|
DWORD cbInfoBuffer = MY_BUFSIZE;
|
|
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
|
return(NULL);
|
|
|
|
bSuccess = GetTokenInformation(
|
|
hToken,
|
|
TokenUser,
|
|
InfoBuffer,
|
|
cbInfoBuffer,
|
|
&cbInfoBuffer
|
|
);
|
|
|
|
if (!bSuccess)
|
|
{
|
|
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
//
|
|
// alloc buffer and try GetTokenInformation() again
|
|
//
|
|
|
|
CloseHandle(hToken);
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// error getting token info
|
|
//
|
|
|
|
CloseHandle(hToken);
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
CloseHandle(hToken);
|
|
|
|
return(((PTOKEN_USER)InfoBuffer)->User.Sid);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
GetSIDString
|
|
---------------------------------------------------------------------------*/
|
|
void GetSIDString(LPSTR tszBuffer, SIZE_T cbBuffLen)
|
|
{
|
|
DWORD cbBuffer = (DWORD)cbBuffLen;
|
|
|
|
if (!GetTextualSid(KYGetCurrentSID(), tszBuffer, &cbBuffer))
|
|
tszBuffer[0] = 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
GetVersionInfo
|
|
---------------------------------------------------------------------------*/
|
|
POSVERSIONINFO GetVersionInfo()
|
|
{
|
|
static BOOL fFirstCall = fTrue;
|
|
static OSVERSIONINFO os;
|
|
|
|
if (fFirstCall)
|
|
{
|
|
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if (GetVersionEx(&os))
|
|
fFirstCall = fFalse;
|
|
}
|
|
|
|
return &os;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
IsNT
|
|
---------------------------------------------------------------------------*/
|
|
BOOL WINAPI IsNT()
|
|
{
|
|
BOOL fResult;
|
|
fResult = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CheckForDeleteRunReg
|
|
---------------------------------------------------------------------------*/
|
|
void CheckForDeleteRunReg()
|
|
{
|
|
HKEY hKey, hRunKey;
|
|
TCHAR szValueName[MAX_PATH];
|
|
TCHAR szMigUserKey[MAX_PATH];
|
|
DWORD cbValueName = MAX_PATH;
|
|
BOOL fRemoveRunKey = FALSE;
|
|
|
|
StringCchCopy(szMigUserKey, ARRAYSIZE(szMigUserKey), g_szIMERootKey);
|
|
StringCchCat(szMigUserKey, ARRAYSIZE(szMigUserKey), TEXT("\\MigrateUser"));
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigUserKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegEnumValue(hKey, 0, szValueName, &cbValueName, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
|
|
fRemoveRunKey = TRUE;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
fRemoveRunKey = TRUE;
|
|
|
|
|
|
if (fRemoveRunKey &&
|
|
(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hRunKey)) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(hRunKey, IME_REGISTRY_MIGRATION);
|
|
RegCloseKey(hRunKey);
|
|
}
|
|
}
|
|
|
|
//
|
|
// On upgrades from Win9x we are passed a string value representing the
|
|
// key under which we'll find the user's Control Panel\Appearance subkey.
|
|
// The string is in the form "HKCU\$$$". We first translate the root key
|
|
// descriptor into a true root key then pass that root and the "$$$"
|
|
// part onto RegOpenKeyEx. This function takes that string and opens
|
|
// the associated hive key.
|
|
//
|
|
DWORD OpenUserKeyForWin9xUpgrade(LPSTR pszUserKeyA, HKEY *phKey)
|
|
{
|
|
DWORD dwResult = ERROR_INVALID_PARAMETER;
|
|
|
|
if (NULL != pszUserKeyA && NULL != phKey)
|
|
{
|
|
typedef struct {
|
|
char *pszRootA;
|
|
HKEY hKeyRoot;
|
|
|
|
} REGISTRY_ROOTS, *PREGISTRY_ROOTS;
|
|
|
|
static REGISTRY_ROOTS rgRoots[] = {
|
|
{ "HKLM", HKEY_LOCAL_MACHINE },
|
|
{ "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
|
|
{ "HKCC", HKEY_CURRENT_CONFIG },
|
|
{ "HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG },
|
|
{ "HKU", HKEY_USERS },
|
|
{ "HKEY_USERS", HKEY_USERS },
|
|
{ "HKCU", HKEY_CURRENT_USER },
|
|
{ "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
|
|
{ "HKCR", HKEY_CLASSES_ROOT },
|
|
{ "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT }
|
|
};
|
|
|
|
char szUserKeyA[MAX_PATH]; // For a local copy.
|
|
LPSTR pszSubKeyA = szUserKeyA;
|
|
|
|
//
|
|
// Make a local copy that we can modify.
|
|
//
|
|
lstrcpynA(szUserKeyA, pszUserKeyA, ARRAYSIZE(szUserKeyA));
|
|
|
|
*phKey = NULL;
|
|
//
|
|
// Find the backslash.
|
|
//
|
|
while(*pszSubKeyA && '\\' != *pszSubKeyA)
|
|
pszSubKeyA++;
|
|
|
|
if ('\\' == *pszSubKeyA)
|
|
{
|
|
HKEY hkeyRoot = NULL;
|
|
int i;
|
|
//
|
|
// Replace backslash with nul to separate the root key and
|
|
// sub key strings in our local copy of the original argument
|
|
// string.
|
|
//
|
|
*pszSubKeyA++ = '\0';
|
|
//
|
|
// Now find the true root key in rgRoots[].
|
|
//
|
|
for (i = 0; i < ARRAYSIZE(rgRoots); i++)
|
|
{
|
|
if (0 == lstrcmpiA(rgRoots[i].pszRootA, szUserKeyA))
|
|
{
|
|
hkeyRoot = rgRoots[i].hKeyRoot;
|
|
break;
|
|
}
|
|
}
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
//
|
|
// Open the key.
|
|
//
|
|
dwResult = RegOpenKeyExA(hkeyRoot,
|
|
pszSubKeyA,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
phKey);
|
|
}
|
|
}
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RestoreMajorVersionRegistry
|
|
|
|
Restore IME major version reg value.
|
|
It could be overwritten during Win9x to NT upgrade.
|
|
---------------------------------------------------------------------------*/
|
|
void RestoreMajorVersionRegistry()
|
|
{
|
|
HKEY hKey;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Restore IME major version reg value.
|
|
// It could be overwritten during Win9x to NT upgrading.
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
CHAR szVersion[MAX_PATH];
|
|
DWORD cbVersion = MAX_PATH;
|
|
CHAR szMaxVersion[MAX_PATH];
|
|
FILETIME time;
|
|
float flVersion, flMaxVersion;
|
|
|
|
StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), "0");
|
|
for (int i=0; cbVersion = MAX_PATH, RegEnumKeyEx(hKey, i, szVersion, &cbVersion, NULL, NULL, NULL, &time) != ERROR_NO_MORE_ITEMS; i++)
|
|
{
|
|
if (lstrcmp(szVersion, szMaxVersion) > 0)
|
|
StringCchCopy(szMaxVersion, ARRAYSIZE(szMaxVersion), szVersion);
|
|
}
|
|
|
|
StringCchCopy(szVersion, ARRAYSIZE(szVersion), "0");
|
|
RegQueryValueEx(hKey, g_szVersion, NULL, NULL, (BYTE *)szVersion, &cbVersion);
|
|
flVersion = (float)atof(szVersion);
|
|
flMaxVersion = (float)atof(szMaxVersion);
|
|
|
|
if (flVersion < flMaxVersion)
|
|
RegSetValueEx(hKey, g_szVersion, 0, REG_SZ, (BYTE *)szMaxVersion, (sizeof(CHAR)*lstrlen(szMaxVersion)));
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CreateSecurityAttributes
|
|
---------------------------------------------------------------------------*/
|
|
PSECURITY_DESCRIPTOR CreateSD()
|
|
{
|
|
PSECURITY_DESCRIPTOR psd;
|
|
PACL pacl;
|
|
ULONG AclSize;
|
|
|
|
PSID psid1, psid2, psid3, psid4;
|
|
BOOL fResult;
|
|
|
|
psid1 = MyCreateSid(SECURITY_INTERACTIVE_RID);
|
|
if (psid1 == NULL)
|
|
return NULL;
|
|
|
|
psid2 = MyCreateSid(SECURITY_LOCAL_SYSTEM_RID);
|
|
if (psid2 == NULL)
|
|
goto Fail4;
|
|
|
|
psid3 = MyCreateSid(SECURITY_SERVICE_RID);
|
|
if (psid3 == NULL)
|
|
goto Fail3;
|
|
|
|
psid4 = MyCreateSid(SECURITY_NETWORK_RID);
|
|
if (psid4 == NULL)
|
|
goto Fail2;
|
|
|
|
//
|
|
// allocate and initialize an access control list (ACL) that will
|
|
// contain the SIDs we've just created.
|
|
//
|
|
AclSize = sizeof(ACL) +
|
|
(4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
|
|
GetLengthSid(psid1) +
|
|
GetLengthSid(psid2) +
|
|
GetLengthSid(psid3) +
|
|
GetLengthSid(psid4);
|
|
|
|
//
|
|
// allocate and initialize a new security descriptor plus ACL
|
|
//
|
|
psd = MEMALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
|
|
if (psd == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pacl = (PACL)((LPBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
fResult = InitializeAcl(pacl, AclSize, ACL_REVISION);
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for interactive users to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid1);
|
|
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid2);
|
|
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid3);
|
|
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid4);
|
|
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// Let's make sure that our ACL is valid.
|
|
//
|
|
if (!IsValidAcl(pacl))
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
|
|
if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
fResult = SetSecurityDescriptorDacl(psd, fTrue, pacl, fFalse );
|
|
|
|
// The discretionary ACL is referenced by, not copied
|
|
// into, the security descriptor. We shouldn't free up ACL
|
|
// after the SetSecurityDescriptorDacl call.
|
|
|
|
if (!fResult)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
if (!IsValidSecurityDescriptor(psd))
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// Those SIDs have been copied into the ACL. We don't need'em any more.
|
|
//
|
|
FreeSid(psid1);
|
|
FreeSid(psid2);
|
|
FreeSid(psid3);
|
|
FreeSid(psid4);
|
|
|
|
return psd;
|
|
|
|
Fail:
|
|
MEMFREE(psd);
|
|
FreeSid(psid4);
|
|
Fail2:
|
|
FreeSid(psid3);
|
|
Fail3:
|
|
FreeSid(psid2);
|
|
Fail4:
|
|
FreeSid(psid1);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PSID MyCreateSid(DWORD dwSubAuthority)
|
|
{
|
|
PSID psid;
|
|
BOOL fResult;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
//
|
|
// allocate and initialize an SID
|
|
//
|
|
fResult = AllocateAndInitializeSid(&SidAuthority,
|
|
1,
|
|
dwSubAuthority,
|
|
0,0,0,0,0,0,0,
|
|
&psid );
|
|
if (!fResult)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (!IsValidSid(psid))
|
|
{
|
|
FreeSid(psid);
|
|
return NULL;
|
|
}
|
|
|
|
return psid;
|
|
}
|
|
|
|
|
|
|