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
2131 lines
76 KiB
/**************************************************************************\
|
|
* Module Name: Winmain.cpp
|
|
*
|
|
* Copyright (C) 2000, Microsoft Corporation
|
|
*
|
|
* Korean IME 6.1 install utility
|
|
*
|
|
* History:
|
|
* 11-Dec-2000 CSLim Ported from Satori 8.1 code
|
|
\**************************************************************************/
|
|
|
|
#include "private.h"
|
|
#include <set>
|
|
#include "imkrinst.h"
|
|
#include "regtip.h"
|
|
#include "insert.h"
|
|
#include "..\tip\resource.h"
|
|
#include "..\version\verres.h"
|
|
|
|
// Safe String
|
|
#define STRSAFE_NO_DEPRECATE
|
|
#include "strsafe.h"
|
|
|
|
#define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x)
|
|
#define MEMFREE(x) LocalFree(x)
|
|
|
|
// Profile reg key
|
|
#define SZTIPREG_LANGPROFILE_TEMPLATE TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\%s\\LanguageProfile\\0x00000412")
|
|
#if defined(_WIN64)
|
|
#define SZTIPREG_LANGPROFILE_TEMPLATE_WOW64 TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\CTF\\TIP\\%s\\LanguageProfile\\0x00000412")
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
CCicCriticalSectionStatic g_cs;
|
|
#endif
|
|
|
|
// IA64 IME does not support IME Pad. So we just need to take care Wow64 IME in IA64.
|
|
#if !defined(_WIN64)
|
|
// Pad Applet Registry location
|
|
#define SZPADSHARE TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042")
|
|
#define SZAPPLETCLSID TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletCLSIDList")
|
|
#define SZAPPLETIID TEXT("SOFTWARE\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletIIDList")
|
|
#else
|
|
#define SZPADSHARE TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042")
|
|
#define SZAPPLETCLSID TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletCLSIDList")
|
|
#define SZAPPLETIID TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\TIP Shared\\1.1\\IMEPad\\1042\\AppletIIDList")
|
|
#endif
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Script run routines
|
|
BOOL CmdSetupDefaultParameters();
|
|
BOOL CmdSetVersion(LPCTSTR szParam);
|
|
BOOL CmdFileList(LPCTSTR szFormat);
|
|
BOOL CmdPreSetupCheck(LPCTSTR szParam);
|
|
BOOL CmdRenamePEFile(LPCTSTR szParam);
|
|
BOOL CmdRenameFile(LPCTSTR szParam);
|
|
BOOL CmdRegisterInterface(LPCTSTR szParam);
|
|
BOOL CmdRegisterInterfaceWow64(LPCTSTR szParam);
|
|
BOOL CmdRegisterIMEandTIP(LPCTSTR szParam);
|
|
BOOL CmdRegisterPackageVersion(void);
|
|
BOOL CmdRegisterPadOrder(void);
|
|
BOOL CmdAddToPreload(LPCTSTR szParam);
|
|
BOOL CmdPrepareMigration(LPCTSTR szParam);
|
|
BOOL CmdCreateDirectory(LPCTSTR szParam);
|
|
BOOL CmdRegisterHelpDirs();
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Private Functions
|
|
// Utility functions
|
|
static DWORD WINAPI ProcessScriptFile();
|
|
static void RegisterIMEWithFixedHKL(LPCTSTR szHKL, LPCTSTR szIMEFileName, LPCTSTR szIMEName);
|
|
static void cdecl LogOutDCPrintf(LPCTSTR lpFmt, va_list va);
|
|
static void DebugLog(LPCTSTR szFormat, ...);
|
|
static void ErrorLog(LPCTSTR szFormat, ...);
|
|
static INT ParseEnvVar(LPTSTR szBuffer, const UINT arg_nLength);
|
|
static void TrimString(LPTSTR szString);
|
|
static BOOL fExistFile(LPCTSTR szFilePath);
|
|
static BOOL fOldIMEsExist();
|
|
static BOOL WINAPI ReplaceFileOnReboot (LPCTSTR pszExisting, LPCTSTR pszNew);
|
|
static void GetPEFileVersion(LPTSTR szFilePath, DWORD *pdwMajorVersion, DWORD *pdwMiddleVersion, DWORD *pdwMinorVersion, DWORD *pdwBuildNumber);
|
|
static BOOL ActRenameFile(LPCTSTR szSrcPath, LPCTSTR tszDstPath, DWORD dwFileAttributes);
|
|
static void RegisterTIP(LPCTSTR szTIPName);
|
|
static void RegisterTIPWow64(LPCTSTR szTIPName);
|
|
static BOOL RegisterRUNKey(LPCTSTR szParam);
|
|
static BOOL MakeSIDList();
|
|
static PSECURITY_DESCRIPTOR CreateSD();
|
|
static PSID MyCreateSid(DWORD dwSubAuthority);
|
|
|
|
// HKL Helpers
|
|
static void HKLHelpSetDefaultKeyboardLayout(HKEY hKeyHKCU, HKL hKL, BOOL fSetToDefault);
|
|
static BOOL HKLHelp412ExistInPreload(HKEY hKeyCU);
|
|
static HKL GetHKLfromHKLM(LPTSTR argszIMEFile);
|
|
static void RestoreMajorVersionRegistry();
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global variables
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static TCHAR g_szCurrentDirectory[MAX_PATH] = {0}; // Directory in where this EXE resides.
|
|
static TCHAR g_szScriptFile[MAX_PATH] = {0}; // File name (not full path) of script file.
|
|
static TCHAR g_szSetupProgram[MAX_PATH] = {0}; // File name (not full path) of setup program.
|
|
static TCHAR g_szSystemDirectory[MAX_PATH] = {0}; // System directory.
|
|
static TCHAR g_szErrorMessage[200] = {0}; // Global buffer for last error message.
|
|
static BOOL g_fDebugLog = FALSE; // Dump debug message when true.
|
|
static BOOL g_fErrorLog = FALSE; // Dump error message when true.
|
|
|
|
static DWORD g_dwMajorVersion = 0; // Package version of this installation.
|
|
static DWORD g_dwMiddleVersion = 0;
|
|
static DWORD g_dwMinorVersion = 0;
|
|
static DWORD g_dwBuildNumber = 0;
|
|
|
|
static std::set <FLE> g_FileList; // FileListSet. Used to store set of file paths given by "CmdFileList"
|
|
// script command.
|
|
|
|
TCHAR g_szVersionKeyCur[MAX_PATH] = {0};
|
|
BOOL g_fExistNewerVersion = FALSE;
|
|
|
|
/*---------------------------------------------------------------------------
|
|
WinMain
|
|
---------------------------------------------------------------------------*/
|
|
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
LPTSTR szHitPtr;
|
|
LPTSTR szCommandLine;
|
|
size_t cchCommandLine;
|
|
|
|
if (FAILED(StringCchLength(GetCommandLine(), MAX_PATH, &cchCommandLine)))
|
|
return (0);
|
|
|
|
szCommandLine = new TCHAR[cchCommandLine + 1];
|
|
|
|
if (szCommandLine == NULL)
|
|
return (0);
|
|
|
|
// szCommandLine contains all command line.
|
|
// Will be modified by _tcstok.
|
|
StringCchCopy(szCommandLine, cchCommandLine+1, GetCommandLine());
|
|
|
|
// TEMP Code
|
|
// LogOutDCPrintf(TEXT("WinMain CommandLine arg: %s"), szCommandLine);
|
|
|
|
CoInitialize(NULL);
|
|
|
|
szHitPtr = _tcstok(szCommandLine, TEXT("\""));
|
|
// g_szCurrentDirectory has path for the process. (IMKRINST.EXE)
|
|
StringCchCopy(g_szCurrentDirectory, ARRAYSIZE(g_szCurrentDirectory), szHitPtr);
|
|
|
|
szHitPtr = _tcsrchr(g_szCurrentDirectory, TEXT('\\'));
|
|
// if g_szCurrentDirectory contains full path,
|
|
if (szHitPtr != NULL)
|
|
{
|
|
*szHitPtr = 0; // terminate with the last '\' character to obtain current directory,
|
|
StringCchCopy(g_szSetupProgram, ARRAYSIZE(g_szSetupProgram), szHitPtr + 1); // then copy the rest (after last '\') to g_szScriptFile.
|
|
}
|
|
else
|
|
{
|
|
StringCchCopy(g_szSetupProgram, ARRAYSIZE(g_szSetupProgram), g_szCurrentDirectory); // Otherwise (g_szCurrentDirectory is not full path), copy entire
|
|
GetCurrentDirectory(MAX_PATH, g_szCurrentDirectory); // to g_szScriptFile and obtain current directory by GetCurrentDirectory.
|
|
}
|
|
|
|
StringCchCopy(g_szScriptFile, ARRAYSIZE(g_szScriptFile), g_szSetupProgram);
|
|
szHitPtr = _tcsrchr(g_szScriptFile, TEXT('.'));
|
|
if (szHitPtr != NULL) // If g_szScriptFile contains '.' character, find the last one
|
|
*szHitPtr = 0; // and terminate string with it, then concatenate ".inf" to it.
|
|
// Usually it results ".exe" -> ".inf" replacement. If g_szScriptFile
|
|
|
|
// doesn't have '.' character, just concatenate ".ini".
|
|
lstrcat(g_szScriptFile, TEXT(".ini"));
|
|
|
|
// Get system32 dir
|
|
GetSystemDirectory(g_szSystemDirectory, ARRAYSIZE(g_szSystemDirectory));
|
|
|
|
// g_szCurrentDirectory, g_szSetupProgram, g_szSystemDirectory and g_szScriptFile are prepared.
|
|
// szCommandLine will be no longer used.
|
|
// We can use these environment variable in the process.
|
|
SetEnvironmentVariable(TEXT("SETUPSOURCE"), g_szCurrentDirectory);
|
|
SetEnvironmentVariable(TEXT("SETUPEXE"), g_szSetupProgram);
|
|
SetEnvironmentVariable(TEXT("SETUPINF"), g_szScriptFile);
|
|
SetEnvironmentVariable(TEXT("SYSTEMDIR"), g_szSystemDirectory);
|
|
|
|
delete[] szCommandLine;
|
|
szCommandLine = NULL;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Read and run Script file
|
|
switch (ProcessScriptFile())
|
|
{
|
|
case errNoError:
|
|
break;
|
|
case errPreSetupCheck:
|
|
{
|
|
#ifdef NEVER
|
|
for(set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++){
|
|
DebugLog(TEXT("Cleanup: Deleting Source file: %s"), itFLE->szFileName);
|
|
DeleteFile(itFLE->szFileName);
|
|
}
|
|
#endif // NEVER
|
|
}
|
|
break;
|
|
default:
|
|
DebugLog(g_szErrorMessage);
|
|
}
|
|
|
|
#ifdef NEVER
|
|
for (set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++)
|
|
{
|
|
ErrorLog(TEXT("Warning: File %s in CmdFileList will be removed without any processing"), itFLE->szFileName);
|
|
DeleteFile(itFLE->szFileName);
|
|
}
|
|
#endif // NEVER
|
|
|
|
CoUninitialize();
|
|
|
|
return(0);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Main Script Processing functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
inline LPCTSTR GetParameter(LPTSTR szLineBuffer)
|
|
{
|
|
return(szLineBuffer + lstrlen(szLineBuffer) + 1);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
ProcessScriptFile
|
|
Read script file. Dispatch commands for each line.
|
|
---------------------------------------------------------------------------*/
|
|
DWORD WINAPI ProcessScriptFile()
|
|
{
|
|
TCHAR szScriptFilePath[MAX_PATH];
|
|
FILE *fileScript;
|
|
|
|
wsprintf(szScriptFilePath, TEXT("%s\\%s"), g_szCurrentDirectory, g_szScriptFile);
|
|
|
|
fileScript = _tfopen(szScriptFilePath, TEXT("rt"));
|
|
|
|
if (fileScript != NULL)
|
|
{
|
|
TCHAR szLineBuffer[_cchBuffer];
|
|
LPTSTR szCommand;
|
|
|
|
// Parse command
|
|
// Command form <Command>:<Parameter>
|
|
while (_fgetts(szLineBuffer, _cchBuffer, fileScript) != NULL)
|
|
{
|
|
// Chop CR code.
|
|
szLineBuffer[lstrlen(szLineBuffer) - 1] = 0;
|
|
|
|
// Empty or Comment line
|
|
if (lstrlen(szLineBuffer) == 0 || (_tcsncmp(TEXT("//"), szLineBuffer, 2) == 0))
|
|
continue;
|
|
|
|
DebugLog(TEXT("Line: %s"), szLineBuffer);
|
|
|
|
szCommand = _tcstok(szLineBuffer, TEXT(":"));
|
|
|
|
if (szCommand == NULL)
|
|
{ // Dispatch each commands.
|
|
DebugLog(TEXT("Ignore line"));
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("DebugLogOn")) == 0)
|
|
{
|
|
g_fDebugLog = TRUE;
|
|
g_fErrorLog = TRUE;
|
|
DebugLog(TEXT("Turn on DebugLog"));
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("DebugLogOff")) == 0)
|
|
{
|
|
DebugLog(TEXT("Turn off DebugLog"));
|
|
g_fDebugLog = FALSE;
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("ErrorLogOn")) == 0)
|
|
{
|
|
g_fErrorLog = TRUE;
|
|
DebugLog(TEXT("Turn on DebugLog"));
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("ErrorLogOff")) == 0)
|
|
{
|
|
DebugLog(TEXT("Turn off DebugLog"));
|
|
g_fErrorLog = FALSE;
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("FileList")) == 0)
|
|
{
|
|
if (!CmdFileList(GetParameter(szCommand)))
|
|
return(errFileList);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("SetupDefaultParameters")) == 0)
|
|
{
|
|
if (!CmdSetupDefaultParameters())
|
|
return(errSetDefaultParameters);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("SetVersion")) == 0)
|
|
{
|
|
if (!CmdSetVersion(GetParameter(szCommand)))
|
|
return(errSetVersion);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("PreSetupCheck")) == 0)
|
|
{
|
|
if (!CmdPreSetupCheck(GetParameter(szCommand)))
|
|
return(errPreSetupCheck);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RenamePEFile")) == 0)
|
|
{
|
|
if (!CmdRenamePEFile(GetParameter(szCommand)))
|
|
return(errRenameFile);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RenameFile")) == 0)
|
|
{
|
|
if (!CmdRenameFile(GetParameter(szCommand)))
|
|
return(errRenameFile);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterIMEandTIP")) == 0)
|
|
{
|
|
if (!CmdRegisterIMEandTIP(GetParameter(szCommand)))
|
|
return(errRegisterIMEandTIP);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterPackageVersion")) == 0)
|
|
{
|
|
if (!CmdRegisterPackageVersion())
|
|
return(errRegisterPackageVersion);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterInterface")) == 0)
|
|
{
|
|
if (!CmdRegisterInterface(GetParameter(szCommand)))
|
|
return(errRegisterInterface);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterInterfaceWow64")) == 0)
|
|
{
|
|
if (!CmdRegisterInterfaceWow64(GetParameter(szCommand)))
|
|
return(errRegisterInterfaceWow64);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterPadOrder")) == 0)
|
|
{
|
|
if (!CmdRegisterPadOrder())
|
|
return(errRegisterPadOrder);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("AddToPreload")) == 0)
|
|
{
|
|
if (!CmdAddToPreload(GetParameter(szCommand)))
|
|
return(errAddToPreload);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("PrepareMigration")) == 0)
|
|
{
|
|
if (!CmdPrepareMigration(GetParameter(szCommand)))
|
|
return(errPrepareMigration);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("CreateDirectory")) == 0)
|
|
{
|
|
if (!CmdCreateDirectory(GetParameter(szCommand)))
|
|
return(errCmdCreateDirectory);
|
|
}
|
|
else if (lstrcmpi(szCommand, TEXT("RegisterHelpDirs")) == 0)
|
|
{
|
|
if (!CmdRegisterHelpDirs())
|
|
return(errCmdRegisterHelpDirs);
|
|
}
|
|
else
|
|
DebugLog(TEXT("Ignore line"));
|
|
}
|
|
|
|
fclose(fileScript);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(g_szErrorMessage, TEXT("Cannot open %s"), g_szScriptFile);
|
|
return(errNoFile);
|
|
}
|
|
|
|
return(errNoError);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Command handlers. Which are invoked from ProcessScriptFile
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdSetupDefaultParameters
|
|
Setup default parameters. For now, it only sets default ProductVersion value.
|
|
---------------------------------------------------------------------------*/
|
|
#define MAKE_STR(a) #a
|
|
#define MAKE_VERSTR(a, b, c, d) MAKE_STR(a.b.c.d)
|
|
|
|
#define VERRES_VERSIONSTR MAKE_VERSTR(VERRES_VERSION_MAJOR, VERRES_VERSION_MINOR, VERRES_VERSION_BUILD, VERRES_VERSION_REVISION)
|
|
|
|
BOOL CmdSetupDefaultParameters()
|
|
{
|
|
_stscanf(TEXT(VERRES_VERSIONSTR), TEXT("%d.%d.%d.%d"), &g_dwMajorVersion, &g_dwMiddleVersion, &g_dwMinorVersion, &g_dwBuildNumber);
|
|
|
|
wsprintf(g_szVersionKeyCur, "%s\\%d.%d\\%s", g_szVersionKey, g_dwMajorVersion, g_dwMiddleVersion, g_szVersion);
|
|
|
|
DebugLog(TEXT("CmdSetupDefaultParameters: Version Info : %d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdSetVersion
|
|
Overwrites default ProductVersion value with value provided in script file.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdSetVersion(LPCTSTR szParam)
|
|
{
|
|
int iNum = _stscanf(szParam, TEXT("%d.%d.%d.%d"), &g_dwMajorVersion, &g_dwMiddleVersion, &g_dwMinorVersion, &g_dwBuildNumber);
|
|
|
|
wsprintf(g_szVersionKeyCur, "%s\\%d.%d\\%s", g_szVersionKey, g_dwMajorVersion, g_dwMiddleVersion, g_szVersion);
|
|
|
|
if (iNum == 4)
|
|
{
|
|
DebugLog(TEXT("CmdSetVersion: Version Info : %d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
ErrorLog(TEXT("CmdSetVersion: Failed to retrieve version number from string [%s]"), szParam);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdSetVersion: Failed to retrieve version number from string [%s]"), szParam);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdFileList
|
|
Add file to the file list. Files in the file list will be deleted when they become no longer needed.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdFileList(LPCTSTR szFormat)
|
|
{
|
|
FLE flElem;
|
|
TCHAR szExpandedFileName[MAX_PATH];
|
|
|
|
flElem.fRemoved = FALSE;
|
|
StringCchCopy(flElem.szFileName, MAX_PATH, szFormat);
|
|
|
|
if (ExpandEnvironmentStrings(flElem.szFileName, szExpandedFileName, sizeof(szExpandedFileName)/sizeof(TCHAR)))
|
|
StringCchCopy(flElem.szFileName, MAX_PATH, szExpandedFileName);
|
|
|
|
// Add the element to file list set.
|
|
if (g_FileList.insert(flElem).second)
|
|
DebugLog(TEXT("Add to CmdFileList \"%s\" -> Added."), szFormat);
|
|
else
|
|
ErrorLog(TEXT("Add to CmdFileList \"%s\" -> Not added. Duplicate?"), szFormat);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdPreSetupCheck
|
|
Check whether the newer IME has been installed.
|
|
Return TRUE when we can proceed.
|
|
!!! FALSE will terminates setup. !!!
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdPreSetupCheck(LPCTSTR szParam)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szInstalledVersionString[30];
|
|
DWORD cbInstalledVersionString = sizeof(szInstalledVersionString);
|
|
DWORD dwInstalledMajorVersion, dwInstalledMiddleVersion, dwInstalledMinorVersion, dwInstalledBuildNumber;
|
|
|
|
BOOL fResult = TRUE;
|
|
|
|
RestoreMajorVersionRegistry();
|
|
|
|
//
|
|
// root
|
|
//
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
|
|
{
|
|
cbInstalledVersionString = sizeof(szInstalledVersionString);
|
|
|
|
RegQueryValueEx(hKey, g_szVersion, NULL, NULL, (LPBYTE)szInstalledVersionString, &cbInstalledVersionString);
|
|
|
|
if (_stscanf(szInstalledVersionString, TEXT("%d.%d"), &dwInstalledMajorVersion, &dwInstalledMiddleVersion) == 2)
|
|
{
|
|
if (VersionComparison2(g_dwMajorVersion, g_dwMiddleVersion) < VersionComparison2(dwInstalledMajorVersion, dwInstalledMiddleVersion))
|
|
{
|
|
DebugLog(TEXT("Newer version of IME has been already installed."));
|
|
wsprintf(g_szErrorMessage, TEXT("Newer version of IME has been already installed. but, continue to setup"));
|
|
g_fExistNewerVersion = TRUE;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
//
|
|
// current
|
|
//
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKeyCur, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
cbInstalledVersionString = sizeof(szInstalledVersionString);
|
|
|
|
RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)szInstalledVersionString, &cbInstalledVersionString);
|
|
if (_stscanf(szInstalledVersionString, TEXT("%d.%d.%d.%04d"),
|
|
&dwInstalledMajorVersion, &dwInstalledMiddleVersion, &dwInstalledMinorVersion, &dwInstalledBuildNumber) == 4)
|
|
{
|
|
if ( VersionComparison4(g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber)
|
|
< VersionComparison4(dwInstalledMajorVersion, dwInstalledMiddleVersion, dwInstalledMinorVersion, dwInstalledBuildNumber))
|
|
{
|
|
DebugLog(TEXT("Newer version of IME has been already installed."));
|
|
wsprintf(g_szErrorMessage, TEXT("Newer version of IME has been already installed."));
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRenamePEFile
|
|
Rename file with PE format version comparison.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRenamePEFile(LPCTSTR szParam)
|
|
{
|
|
TCHAR szSrc[MAX_PATH], szDst[MAX_PATH];
|
|
TCHAR szExpandedSrc[MAX_PATH], szExpandedDst[MAX_PATH];
|
|
LPTSTR szHitPtr;
|
|
DWORD dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
DWORD dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber;
|
|
DWORD dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber;
|
|
|
|
szHitPtr = _tcschr(szParam, TEXT(','));
|
|
if (szHitPtr == NULL)
|
|
{
|
|
ErrorLog(TEXT("CmdRenamePEFile: Invalid parameters (%s)"), szParam);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdRenamePEFile: Invalid parameters (%s)"), szParam);
|
|
return(FALSE);
|
|
}
|
|
*szHitPtr = 0;
|
|
StringCchCopy(szSrc, ARRAYSIZE(szSrc), szParam);
|
|
StringCchCopy(szDst, ARRAYSIZE(szDst), szHitPtr + 1); // Here, szDst may contain optional parameter.
|
|
|
|
szHitPtr = _tcschr(szDst, TEXT(','));
|
|
if (NULL != szHitPtr)
|
|
{
|
|
*szHitPtr = 0;
|
|
_stscanf(szHitPtr + 1, TEXT("%d"), &dwFileAttributes);
|
|
}
|
|
|
|
TrimString(szSrc);
|
|
TrimString(szDst);
|
|
|
|
ExpandEnvironmentStrings(szSrc, szExpandedSrc, sizeof(szExpandedSrc));
|
|
ExpandEnvironmentStrings(szDst, szExpandedDst, sizeof(szExpandedDst));
|
|
|
|
DebugLog(TEXT("CmdRenamePEFile: szExpandedSrc = %s, szExpandedDst = %s"), szExpandedSrc, szExpandedDst);
|
|
|
|
GetPEFileVersion(szExpandedSrc, &dwSrcMajorVersion, &dwSrcMiddleVersion, &dwSrcMinorVersion, &dwSrcBuildNumber);
|
|
GetPEFileVersion(szExpandedDst, &dwDstMajorVersion, &dwDstMiddleVersion, &dwDstMinorVersion, &dwDstBuildNumber);
|
|
|
|
DebugLog(TEXT("SrcVersion: (%d.%d.%d.%d), DstVersion: (%d.%d.%d.%d)"), dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber,
|
|
dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber);
|
|
if (VersionComparison4(0, 0, 0, 0) == VersionComparison4(dwSrcMajorVersion, dwSrcMinorVersion, dwSrcMiddleVersion, dwSrcBuildNumber))
|
|
ErrorLog(TEXT("Version of source file (%s) is 0.0.0.0. May be file not found."), szSrc);
|
|
|
|
if(VersionComparison4(dwSrcMajorVersion, dwSrcMiddleVersion, dwSrcMinorVersion, dwSrcBuildNumber) <
|
|
VersionComparison4(dwDstMajorVersion, dwDstMiddleVersion, dwDstMinorVersion, dwDstBuildNumber))
|
|
{
|
|
DebugLog(TEXT("CmdRenamePEFile: Source version is less than Destination. Copy skipped and Source will be deleted."));
|
|
|
|
if(DeleteFile(szSrc))
|
|
{
|
|
FLE fleKey;
|
|
StringCchCopy(fleKey.szFileName, MAX_PATH, szSrc);
|
|
g_FileList.erase(fleKey);
|
|
}
|
|
else
|
|
DebugLog(TEXT("CmdRenamePEFile: Failed to delete Source file (%s)"), szSrc);
|
|
}
|
|
else
|
|
{
|
|
DebugLog(TEXT("CmdRenamePEFile: Invoke ActRenameFile"));
|
|
ActRenameFile(szSrc, szDst, dwFileAttributes);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRenameFile
|
|
Rename file without version comparison
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRenameFile(LPCTSTR szParam)
|
|
{
|
|
TCHAR szSrc[MAX_PATH], szDst[MAX_PATH];
|
|
TCHAR szExpandedSrc[MAX_PATH], szExpandedDst[MAX_PATH];
|
|
LPTSTR szHitPtr;
|
|
DWORD dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
|
|
szHitPtr = _tcschr(szParam, TEXT(','));
|
|
if (szHitPtr == NULL)
|
|
{
|
|
ErrorLog(TEXT("CmdRenameFile: Invalid parameters (%s)"), szParam);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdRenameFile: Invalid parameters (%s)"), szParam);
|
|
return(FALSE);
|
|
}
|
|
*szHitPtr = 0;
|
|
StringCchCopy(szSrc, ARRAYSIZE(szSrc), szParam);
|
|
StringCchCopy(szDst, ARRAYSIZE(szDst), szHitPtr + 1); // Here, szDst may contain optional parameter.
|
|
|
|
szHitPtr = _tcschr(szDst, TEXT(','));
|
|
if (szHitPtr != NULL)
|
|
{
|
|
*szHitPtr = 0;
|
|
_stscanf(szHitPtr + 1, TEXT("%d"), &dwFileAttributes);
|
|
}
|
|
|
|
TrimString(szSrc);
|
|
TrimString(szDst);
|
|
|
|
ExpandEnvironmentStrings(szSrc, szExpandedSrc, sizeof(szExpandedSrc));
|
|
ExpandEnvironmentStrings(szDst, szExpandedDst, sizeof(szExpandedDst));
|
|
|
|
DebugLog(TEXT("RanemeFile: szExpandedSrc = %s, szExpandedDst = %s"), szExpandedSrc, szExpandedDst);
|
|
|
|
ActRenameFile(szExpandedSrc, szExpandedDst, dwFileAttributes);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RegisterIMEWithFixedHKL
|
|
---------------------------------------------------------------------------*/
|
|
void RegisterIMEWithFixedHKL(LPCTSTR szHKL, LPCTSTR szIMEFileName, LPCTSTR szIMEName)
|
|
{
|
|
HKEY hKeyKbdLayout;
|
|
HKEY hKeyOneIME;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"),
|
|
&hKeyKbdLayout) != ERROR_SUCCESS)
|
|
return;
|
|
|
|
if (RegCreateKey(hKeyKbdLayout,
|
|
szHKL,
|
|
&hKeyOneIME) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKeyKbdLayout);
|
|
return;
|
|
}
|
|
|
|
if (RegSetValueEx(hKeyOneIME,
|
|
TEXT("Ime File"),
|
|
0,
|
|
REG_SZ,
|
|
(CONST BYTE*)szIMEFileName,
|
|
(lstrlen(szIMEFileName) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
|
|
goto WriteImeLayoutFail;
|
|
|
|
if (RegSetValueEx(hKeyOneIME,
|
|
TEXT("Layout Text"),
|
|
0,
|
|
REG_SZ,
|
|
(CONST BYTE*)szIMEName,
|
|
(lstrlen(szIMEName) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
|
|
goto WriteImeLayoutFail;
|
|
|
|
WriteImeLayoutFail:
|
|
RegCloseKey(hKeyOneIME);
|
|
RegCloseKey(hKeyKbdLayout);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterInterface
|
|
Invoke SelfReg. If given file is DLL, call DllRegisterServer export function. If given file is EXE, run it with "/RegServer"
|
|
command line option.
|
|
---------------------------------------------------------------------------*/
|
|
typedef HRESULT (STDAPICALLTYPE *pfnDllRegisterServerType)(void);
|
|
BOOL CmdRegisterInterface(LPCTSTR szParam)
|
|
{
|
|
TCHAR szExpandedModulePath[MAX_PATH];
|
|
HRESULT hr = S_FALSE;
|
|
|
|
ExpandEnvironmentStrings(szParam, szExpandedModulePath, sizeof(szExpandedModulePath));
|
|
TrimString(szExpandedModulePath);
|
|
|
|
INT iLen = 0;
|
|
iLen = lstrlen(szExpandedModulePath);
|
|
|
|
if (iLen < 4)
|
|
{
|
|
ErrorLog(TEXT("CmdRegisterInterface: Too short szExpandedModulePath (%s)"), szExpandedModulePath);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdRegisterInterface: Invalid Parameters."));
|
|
return(FALSE);
|
|
}
|
|
|
|
if (lstrcmpi(TEXT(".dll"), &szExpandedModulePath[iLen - 4]) == 0)
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterface: DLL mode for %s"), szExpandedModulePath);
|
|
|
|
HINSTANCE hLib = LoadLibrary(szExpandedModulePath);
|
|
|
|
if (hLib != NULL)
|
|
{
|
|
pfnDllRegisterServerType pfnDllRegisterServer = (pfnDllRegisterServerType)GetProcAddress(hLib, "DllRegisterServer");
|
|
if (pfnDllRegisterServer != NULL)
|
|
{
|
|
hr = pfnDllRegisterServer();
|
|
ErrorLog(TEXT("CmdRegisterInterface: hResult=%x"), hr);
|
|
}
|
|
FreeLibrary(hLib);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (lstrcmpi(TEXT(".exe"), &szExpandedModulePath[iLen - 4]) == 0)
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterface: EXE mode for %s"), szExpandedModulePath);
|
|
|
|
TCHAR szCommandBuffer[MAX_PATH * 2];
|
|
wsprintf(szCommandBuffer, TEXT("%s /RegServer"), szExpandedModulePath);
|
|
|
|
STARTUPINFO si;
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_HIDE;
|
|
|
|
PROCESS_INFORMATION pi;
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
if (CreateProcess(NULL, szCommandBuffer, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi))
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterface: Running \"%s\". Waiting for the process termination."), szCommandBuffer);
|
|
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
|
|
DebugLog(TEXT("CmdRegisterInterface: \"%s\" terminates."), szCommandBuffer);
|
|
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
ErrorLog(TEXT("CmdRegisterInterface: CreateProcess(\"%s\") failed with error code = %d(%x)"), szCommandBuffer, dwError, dwError);
|
|
}
|
|
}
|
|
else
|
|
ErrorLog(TEXT("Cannot detect module type for %s. Skipped."), szExpandedModulePath);
|
|
}
|
|
|
|
return(SUCCEEDED(hr));
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterInterfaceWow64
|
|
Invoke SelfReg. If given file is DLL, call DllRegisterServer export function. If given file is EXE, run it with "/RegServer"
|
|
command line option.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRegisterInterfaceWow64(LPCTSTR szParam)
|
|
{
|
|
#if defined(_WIN64)
|
|
TCHAR szExpandedModulePath[MAX_PATH];
|
|
TCHAR szCommandBuffer[MAX_PATH * 2];
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ExpandEnvironmentStrings(szParam, szExpandedModulePath, sizeof(szExpandedModulePath));
|
|
TrimString(szExpandedModulePath);
|
|
|
|
INT iLen = 0;
|
|
iLen = lstrlen(szExpandedModulePath);
|
|
|
|
if (iLen < 4)
|
|
{
|
|
ErrorLog(TEXT("CmdRegisterInterfaceWow64: Too short szExpandedModulePath (%s)"), szExpandedModulePath);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdRegisterInterface: Invalid Parameters."));
|
|
return(FALSE);
|
|
}
|
|
|
|
if (lstrcmpi(TEXT(".dll"), &szExpandedModulePath[iLen - 4]) == 0)
|
|
{
|
|
// First get systemWow64Directory
|
|
TCHAR szSysWow64Dir[MAX_PATH] = TEXT("");
|
|
HMODULE hmod = GetModuleHandle(TEXT("kernel32.dll"));
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: DLL mode for %s"), szExpandedModulePath);
|
|
|
|
if (hmod == NULL)
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: Faile to load kernel32.dll"));
|
|
return (TRUE);
|
|
}
|
|
|
|
UINT (WINAPI* pfnGetSystemWow64Directory)(LPTSTR, UINT);
|
|
|
|
(FARPROC&)pfnGetSystemWow64Directory = GetProcAddress (hmod, "GetSystemWow64DirectoryA");
|
|
|
|
if (pfnGetSystemWow64Directory == NULL)
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: Faile to load GetSystemWow64DirectoryA API"));
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* if GetSystemWow64Directory fails and sets the last error to
|
|
* ERROR_CALL_NOT_IMPLEMENTED, we're on a 32-bit OS
|
|
*/
|
|
if (((pfnGetSystemWow64Directory)(szSysWow64Dir, ARRAYSIZE(szSysWow64Dir)) == 0) &&
|
|
(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: Failed to load GetSystemWow64DirectoryA API"));
|
|
return (TRUE);
|
|
}
|
|
|
|
wsprintf(szCommandBuffer, TEXT("%s\\regsvr32.exe \"%s\" /s"), szSysWow64Dir, szExpandedModulePath);
|
|
}
|
|
else
|
|
if (lstrcmpi(TEXT(".exe"), &szExpandedModulePath[iLen - 4]) == 0)
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: EXE mode for %s"), szExpandedModulePath);
|
|
wsprintf(szCommandBuffer, TEXT("\"%s\" /RegServer"), szExpandedModulePath);
|
|
}
|
|
else
|
|
{
|
|
ErrorLog(TEXT("Cannot detect module type for %s. Skipped."), szExpandedModulePath);
|
|
// Return true not to stop further processing.
|
|
return (TRUE);
|
|
}
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_HIDE;
|
|
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
if (CreateProcess(NULL, szCommandBuffer, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi))
|
|
{
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: Running \"%s\". Waiting for the process termination."), szCommandBuffer);
|
|
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
|
|
DebugLog(TEXT("CmdRegisterInterfaceWow64: \"%s\" terminates."), szCommandBuffer);
|
|
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
ErrorLog(TEXT("CmdRegisterInterfaceWow64: CreateProcess(\"%s\") failed with error code = %d(%x)"), szCommandBuffer, dwError, dwError);
|
|
}
|
|
#endif
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterIMEandTIP
|
|
Register IME using IMM API and TIP
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRegisterIMEandTIP(LPCTSTR szParam)
|
|
{
|
|
TCHAR szIMEFileName[MAX_PATH], szTIPName[MAX_PATH], szTIPNameWow64[MAX_PATH];
|
|
TCHAR *szHitPtr;
|
|
TCHAR *szHitPtr2;
|
|
HKL hIME61KL = 0;
|
|
TCHAR szHKL[10];
|
|
TCHAR szNonFullPath[MAX_PATH];
|
|
HKEY hKey;
|
|
|
|
szHitPtr = _tcschr(szParam, TEXT(','));
|
|
szHitPtr2 = _tcschr(szHitPtr + 1, TEXT(',')); // because there are three parameters
|
|
if (szHitPtr2 == NULL)
|
|
{
|
|
ErrorLog(TEXT("CmdRegisterIMEandTIP: Invalid parameters (%s)"), szParam);
|
|
wsprintf(g_szErrorMessage, TEXT("CmdRegisterIMEandTIP: Invalid parameters (%s)"), szParam);
|
|
return(FALSE);
|
|
}
|
|
*szHitPtr = 0;
|
|
*szHitPtr2 = 0;
|
|
StringCchCopy(szIMEFileName, ARRAYSIZE(szIMEFileName), szParam);
|
|
StringCchCopy(szTIPName, ARRAYSIZE(szTIPName), szHitPtr + 1);
|
|
StringCchCopy(szTIPNameWow64, ARRAYSIZE(szTIPNameWow64), szHitPtr2 + 1);
|
|
|
|
TrimString(szIMEFileName);
|
|
TrimString(szTIPName);
|
|
TrimString(szTIPNameWow64);
|
|
|
|
ParseEnvVar(szIMEFileName, MAX_PATH);
|
|
ParseEnvVar(szTIPName, MAX_PATH);
|
|
ParseEnvVar(szTIPNameWow64, MAX_PATH);
|
|
|
|
DebugLog(TEXT("CmdRegisterIMEandTIP: IMEFileName = %s, TIPFileName = %s szTIPNameWow64 = %s"), szIMEFileName, szTIPName, szTIPNameWow64);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IME registration
|
|
if ((szHitPtr = _tcsrchr(szIMEFileName, TEXT('\\'))) != NULL)
|
|
szHitPtr++;
|
|
else
|
|
szHitPtr = szIMEFileName;
|
|
|
|
StringCchCopy(szNonFullPath, ARRAYSIZE(szNonFullPath), szHitPtr);
|
|
|
|
hIME61KL = GetHKLfromHKLM(szNonFullPath);
|
|
|
|
if (hIME61KL == (HKL)0)
|
|
DebugLog(TEXT("CmdRegisterIMEandTIP: hIME61KL is zero %x -- error"), hIME61KL);
|
|
|
|
//if (hKL && HKLHelp412ExistInPreload(HKEY_CURRENT_USER))
|
|
// {
|
|
// HKLHelpSetDefaultKeyboardLayout(HKEY_CURRENT_USER, hKL, FALSE);
|
|
//hKL = ImmInstallIME(szIMEFileName, szLayoutText);
|
|
// }
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// TIP registration
|
|
// Regster wow64 TIP first to avoid regstry overwrite problem.
|
|
RegisterTIPWow64(szTIPNameWow64);
|
|
RegisterTIP(szTIPName);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IME and TIP - make substitution
|
|
TCHAR szTIPGuid[MAX_PATH];
|
|
TCHAR szLangProfile[MAX_PATH];
|
|
|
|
CLSIDToStringA(CLSID_KorIMX, szTIPGuid);
|
|
DebugLog(TEXT("CmdRegisterIMEandTIP: CLSID_KorIMX guid=%s"), szTIPGuid);
|
|
|
|
// make a reg key
|
|
wsprintf(szLangProfile, SZTIPREG_LANGPROFILE_TEMPLATE, szTIPGuid);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Add Substitute HKL value to the TIP registry
|
|
if (hIME61KL != 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, szLangProfile, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szSubKeyName[MAX_PATH], szHKL[MAX_PATH];
|
|
DWORD dwIndex;
|
|
HKEY hSubKey;
|
|
|
|
wsprintf(szHKL, TEXT("0x%x"), hIME61KL);
|
|
dwIndex = 0;
|
|
|
|
while (RegEnumKey(hKey, dwIndex, szSubKeyName, MAX_PATH) != ERROR_NO_MORE_ITEMS)
|
|
{
|
|
if (RegOpenKeyEx(hKey,szSubKeyName,0,KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx(hSubKey, TEXT("SubstituteLayout"), 0,REG_SZ,(BYTE *)szHKL, sizeof(TCHAR)*(lstrlen(szHKL)+1));
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
dwIndex++;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
// make a reg key
|
|
wsprintf(szLangProfile, SZTIPREG_LANGPROFILE_TEMPLATE_WOW64, szTIPGuid);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Add Substitute HKL value to the TIP registry
|
|
if (hIME61KL != 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, szLangProfile, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szSubKeyName[MAX_PATH], szHKL[MAX_PATH];
|
|
DWORD dwIndex;
|
|
HKEY hSubKey;
|
|
|
|
wsprintf(szHKL, TEXT("0x%x"), hIME61KL);
|
|
dwIndex = 0;
|
|
|
|
while (RegEnumKey(hKey, dwIndex, szSubKeyName, MAX_PATH) != ERROR_NO_MORE_ITEMS)
|
|
{
|
|
if (RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx(hSubKey, TEXT("SubstituteLayout"), 0, REG_SZ, (BYTE*)szHKL, sizeof(TCHAR)*(lstrlen(szHKL)+1));
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
dwIndex++;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
#endif
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterRUNKey
|
|
Register package version
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRegisterPackageVersion(void)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szVersionString[30];
|
|
|
|
// Write RootVersion reg only if this is latest IME.
|
|
if (g_fExistNewerVersion == FALSE)
|
|
{
|
|
if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
|
|
{
|
|
wsprintf(szVersionString, TEXT("%d.%d"), g_dwMajorVersion, g_dwMiddleVersion);
|
|
RegSetValueEx(hKey, g_szVersion, 0, REG_SZ, (CONST BYTE *)szVersionString, (lstrlen(szVersionString) + 1) * sizeof(TCHAR));
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
// Current
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, g_szVersionKeyCur, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
wsprintf(szVersionString, TEXT("%d.%d.%d.%d"), g_dwMajorVersion, g_dwMiddleVersion, g_dwMinorVersion, g_dwBuildNumber);
|
|
RegSetValueEx(hKey, NULL, 0, REG_SZ, (CONST BYTE *)szVersionString, (lstrlen(szVersionString) + 1) * sizeof(TCHAR));
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Register Applet order
|
|
//
|
|
|
|
#define FE_KOREAN // need Korean stuff
|
|
#include "../fecommon/imembx/guids.h"
|
|
|
|
|
|
typedef
|
|
struct tagAPPLETCLSID
|
|
{
|
|
const GUID *pguidClsid;
|
|
BOOL fNoUIM;
|
|
} APPLETCLSID;
|
|
|
|
typedef
|
|
struct tagAPPLETIID
|
|
{
|
|
const GUID *pguidIID;
|
|
} APPLETIID;
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterPadOrder
|
|
Not support WOW64.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRegisterPadOrder(void)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szClsid[MAX_PATH];
|
|
TCHAR szKey[MAX_PATH];
|
|
|
|
static const APPLETCLSID appletClsid[] =
|
|
{
|
|
{ &CLSID_ImePadApplet_MultiBox, FALSE },
|
|
{0},
|
|
};
|
|
|
|
static const APPLETIID appletIID[] =
|
|
{
|
|
{ &IID_MultiBox },
|
|
{0},
|
|
};
|
|
|
|
//
|
|
// Applet clsid
|
|
//
|
|
for (INT i = 0; appletClsid[i].pguidClsid; i++)
|
|
{
|
|
CLSIDToStringA(*appletClsid[i].pguidClsid, szClsid);
|
|
wsprintf(szKey, TEXT("%s\\%s"), SZAPPLETCLSID, szClsid);
|
|
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
if(appletClsid[i].fNoUIM)
|
|
{
|
|
DWORD dw = 1;
|
|
RegSetValueEx(hKey, TEXT("nouim"), 0, NULL, (BYTE*)&dw, sizeof(DWORD));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Applet iid
|
|
//
|
|
TCHAR szSubKey[MAX_PATH];
|
|
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZAPPLETIID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
for (INT i = 0; appletIID[i].pguidIID; i++)
|
|
{
|
|
CLSIDToStringA(*appletIID[i].pguidIID, szKey);
|
|
wsprintf(szSubKey, TEXT("%d"), i);
|
|
RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (BYTE*)szKey, (lstrlen(szKey)+1)*sizeof(TCHAR));
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdCreateDirectory
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdCreateDirectory(LPCTSTR szParam)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH], szExpandedDirectory[MAX_PATH];
|
|
|
|
StringCchCopy(szDirectory, ARRAYSIZE(szDirectory), szParam);
|
|
TrimString(szDirectory);
|
|
ExpandEnvironmentStrings(szDirectory, szExpandedDirectory, sizeof(szExpandedDirectory)/sizeof(TCHAR));
|
|
|
|
CreateDirectory(szExpandedDirectory, NULL);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdAddToPreload
|
|
Add HKL for given IMEFile to current user's preload. The HKL won't become default IME.
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdAddToPreload(LPCTSTR szParam)
|
|
{
|
|
TCHAR tszIMEFileName[MAX_PATH];
|
|
HKL hKL;
|
|
|
|
// If there is no Kor IME exist in preload, we shouldn't add Kor IME.
|
|
if (!HKLHelp412ExistInPreload(HKEY_CURRENT_USER))
|
|
{
|
|
DebugLog(TEXT("CmdAddToPreload: No 0412 HKL exist in HKCU\\Preload"));
|
|
return TRUE;
|
|
}
|
|
|
|
StringCchCopy(tszIMEFileName, ARRAYSIZE(tszIMEFileName), szParam);
|
|
TrimString(tszIMEFileName);
|
|
|
|
hKL = GetHKLfromHKLM(tszIMEFileName);
|
|
|
|
DebugLog(TEXT("CmdAddToPreload: Calling SetDefaultKeyboardLayout(HKEY_CURRENT_USER, %x, FALSE)"), hKL);
|
|
HKLHelpSetDefaultKeyboardLayout(HKEY_CURRENT_USER, hKL, FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
fOldIMEsExist
|
|
Register Run regi onl if old IME exist in system.
|
|
---------------------------------------------------------------------------*/
|
|
static BOOL fOldIMEsExist()
|
|
{
|
|
HKL hKL;
|
|
|
|
static LPCSTR m_szOldIMEs[] =
|
|
{
|
|
"msime95.ime", // Win 95 IME
|
|
"msime95k.ime", // NT 4 IME
|
|
"imekr98u.ime", // IME98
|
|
"imekr.ime", // Office 10 IME
|
|
""
|
|
};
|
|
|
|
CHAR** ppch = (CHAR**)&m_szOldIMEs[0];
|
|
|
|
while (ppch && **ppch)
|
|
{
|
|
hKL = GetHKLfromHKLM(*ppch);
|
|
if (hKL)
|
|
return TRUE; // existing
|
|
ppch++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
DisableTIP60ByDefault
|
|
---------------------------------------------------------------------------*/
|
|
VOID DisableTIP60ByDefault()
|
|
{
|
|
// 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 guidProfile60 =
|
|
// {E47ABB1E-46AC-45f3-8A89-34F9D706DA83}
|
|
{
|
|
0xe47abb1e,
|
|
0x46ac,
|
|
0x45f3,
|
|
{0x8a, 0x89, 0x34, 0xf9, 0xd7, 0x6, 0xda, 0x83}
|
|
};
|
|
|
|
// 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(CLSID_KorTIP60,
|
|
MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile60, FALSE);
|
|
|
|
pProfile->Release();
|
|
}
|
|
else
|
|
{
|
|
OurEnableLanguageProfileByDefault(CLSID_KorTIP60, MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), guidProfile60, FALSE);
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdPrepareMigration
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdPrepareMigration(LPCTSTR szParam)
|
|
{
|
|
// Disable TIP 6.0 from HKLM by default
|
|
// This will handle Office 10 install after Whistler mig exe removed from run reg.
|
|
DisableTIP60ByDefault();
|
|
|
|
// First user SID list
|
|
if (MakeSIDList() == FALSE)
|
|
return FALSE;
|
|
|
|
//Register IMEKRMIG.EXE to run reg Key on "Software\Microsoft\Windows\CurrentVersion\Run"
|
|
return RegisterRUNKey(szParam);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CmdRegisterHelpDirs
|
|
---------------------------------------------------------------------------*/
|
|
BOOL CmdRegisterHelpDirs()
|
|
{
|
|
TCHAR szFileNameFullPath[MAX_PATH], szFileName[MAX_PATH];
|
|
LPTSTR szExtension, szFileNamePtr;
|
|
HKEY hKey;
|
|
|
|
for (std::set<FLE>::iterator itFLE = g_FileList.begin(); itFLE != g_FileList.end(); itFLE++)
|
|
{
|
|
StringCchCopy(szFileNameFullPath, ARRAYSIZE(szFileNameFullPath), itFLE->szFileName);
|
|
szExtension = _tcsrchr(szFileNameFullPath, TEXT('.'));
|
|
if (szExtension == NULL)
|
|
continue;
|
|
|
|
if (lstrcmpi(szExtension, TEXT(".CHM")) == 0)
|
|
{
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\HTML Help"), 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
szFileNamePtr = _tcsrchr(szFileNameFullPath, TEXT('\\'));
|
|
// Get file name
|
|
StringCchCopy(szFileName, ARRAYSIZE(szFileName), szFileNamePtr+1);
|
|
// Get rid of file name we only need path.
|
|
*(szFileNamePtr+1) = 0;
|
|
RegSetValueEx(hKey, szFileName, 0, REG_SZ, (LPBYTE)szFileNameFullPath, (lstrlen(szFileNameFullPath)+1)*sizeof(TCHAR));
|
|
}
|
|
}
|
|
else
|
|
if (lstrcmpi(szExtension, TEXT(".HLP")) == 0)
|
|
{
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\Help"), 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
szFileNamePtr = _tcsrchr(szFileNameFullPath, TEXT('\\'));
|
|
// Get file name
|
|
StringCchCopy(szFileName, ARRAYSIZE(szFileName), szFileNamePtr+1);
|
|
// Get rid of file name we only need path.
|
|
*(szFileNamePtr+1) = 0;
|
|
RegSetValueEx(hKey, szFileName, 0, REG_SZ, (LPBYTE)szFileNameFullPath, (lstrlen(szFileNameFullPath)+1)*sizeof(TCHAR));
|
|
}
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Private functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Debug output routine.
|
|
//
|
|
void cdecl LogOutDCPrintf(LPCTSTR lpFmt, va_list va)
|
|
{
|
|
static INT DCLine = 0;
|
|
HDC hDC = GetDC((HWND)0);
|
|
TCHAR sz[512];
|
|
HANDLE hFile;
|
|
DWORD dwWrite;
|
|
|
|
wvsprintf(sz, lpFmt, va );
|
|
lstrcat(sz, TEXT("| "));
|
|
TextOut(hDC, 0, DCLine*16, sz, lstrlen(sz));
|
|
|
|
if (DCLine++ > 50)
|
|
DCLine = 0;
|
|
|
|
hFile = CreateFile(TEXT("\\IMKRINST.LOG"), GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
SetFilePointer(hFile, 0, NULL, FILE_END);
|
|
WriteFile(hFile, sz, lstrlen(sz), &dwWrite, NULL);
|
|
WriteFile(hFile, TEXT("\r\n"), 2, &dwWrite, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
ReleaseDC((HWND)0, hDC);
|
|
}
|
|
|
|
void DebugLog(LPCTSTR szFormat, ...)
|
|
{
|
|
va_list va;
|
|
|
|
va_start(va, szFormat);
|
|
|
|
if (g_fDebugLog)
|
|
LogOutDCPrintf(szFormat, va);
|
|
|
|
va_end(va);
|
|
}
|
|
|
|
void ErrorLog(LPCTSTR szFormat, ...)
|
|
{
|
|
va_list va;
|
|
|
|
va_start(va, szFormat);
|
|
|
|
if (g_fErrorLog)
|
|
LogOutDCPrintf(szFormat, va);
|
|
|
|
va_end(va);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
ParseEnvVar
|
|
Evaluate environment variable. Modiry given string.
|
|
---------------------------------------------------------------------------*/
|
|
INT ParseEnvVar(LPTSTR szBuffer, const UINT arg_nLength)
|
|
{
|
|
INT iTranslated=0, i, j;
|
|
TCHAR *pLParen, *pRParen, *pStart = szBuffer;
|
|
INT nLength = min(arg_nLength, MAX_PATH);
|
|
static TCHAR szInternalBuffer[MAX_PATH*2], szValue[MAX_PATH];
|
|
|
|
szInternalBuffer[0] = 0;
|
|
for (i=0; i<nLength; i++)
|
|
{
|
|
if (szBuffer[i] == 0)
|
|
break;
|
|
|
|
if (szBuffer[i] == '%')
|
|
{
|
|
pLParen = &(szBuffer[i]);
|
|
pRParen = NULL;
|
|
|
|
for (j=1; i+j<nLength; j++)
|
|
{
|
|
if (szBuffer[i+j] == 0)
|
|
break;
|
|
|
|
if (szBuffer[i+j] == TEXT('%'))
|
|
{
|
|
pRParen = &(szBuffer[i+j]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pRParen)
|
|
{
|
|
*pLParen = 0;
|
|
*pRParen = 0;
|
|
lstrcat(szInternalBuffer, pStart);
|
|
|
|
if (GetEnvironmentVariable(pLParen+1, szValue, sizeof(szValue)/sizeof(TCHAR)) == 0)
|
|
{
|
|
lstrcat(szInternalBuffer, TEXT("%"));
|
|
lstrcat(szInternalBuffer, pLParen+1);
|
|
lstrcat(szInternalBuffer, TEXT("%"));
|
|
}
|
|
else
|
|
{
|
|
lstrcat(szInternalBuffer, szValue);
|
|
iTranslated++;
|
|
}
|
|
pStart = pRParen+1;
|
|
i += j;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iTranslated)
|
|
{
|
|
lstrcat(szInternalBuffer, pStart);
|
|
lstrcpyn(szBuffer, szInternalBuffer, arg_nLength);
|
|
}
|
|
|
|
return(iTranslated);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
TrimString
|
|
Chop head/tail white space from given string. Given string will be modified.
|
|
---------------------------------------------------------------------------*/
|
|
void TrimString(LPTSTR szString)
|
|
{
|
|
INT iBuffSize = lstrlen(szString) + 1;
|
|
LPTSTR szBuffer = new TCHAR[iBuffSize];
|
|
|
|
if (szBuffer != NULL)
|
|
{
|
|
INT iHeadSpace, iTailSpace;
|
|
|
|
StringCchCopy(szBuffer, MAX_PATH, szString);
|
|
|
|
iHeadSpace = (INT)_tcsspn(szBuffer, TEXT(" \t"));
|
|
_tcsrev(szBuffer);
|
|
iTailSpace = (INT)_tcsspn(szBuffer, TEXT(" \t"));
|
|
_tcsrev(szBuffer);
|
|
|
|
szBuffer[lstrlen(szBuffer) - iTailSpace] = 0;
|
|
StringCchCopy(szString, MAX_PATH, szBuffer + iHeadSpace);
|
|
}
|
|
|
|
if (szBuffer != NULL)
|
|
{
|
|
delete[] szBuffer;
|
|
szBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
fExistFile
|
|
---------------------------------------------------------------------------*/
|
|
BOOL fExistFile(LPCTSTR szFilePath)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
|
|
if (GetFileAttributes(szFilePath) == -1)
|
|
fResult = FALSE;
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
ReplaceFileOnReboot
|
|
Writes wininit.ini rename section. Note that this function writes lines in reverse order (down to upper).
|
|
---------------------------------------------------------------------------*/
|
|
BOOL WINAPI ReplaceFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew)
|
|
{
|
|
if (MoveFileEx(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
GetPEFileVersion
|
|
Get version information from PE format.
|
|
---------------------------------------------------------------------------*/
|
|
void GetPEFileVersion(LPTSTR szFilePath, DWORD *pdwMajorVersion, DWORD *pdwMiddleVersion, DWORD *pdwMinorVersion, DWORD *pdwBuildNumber)
|
|
{
|
|
*pdwMajorVersion = *pdwMiddleVersion = *pdwMinorVersion = *pdwBuildNumber = 0;
|
|
|
|
DWORD dwDummy, dwVerResSize;
|
|
|
|
dwVerResSize = GetFileVersionInfoSize(szFilePath, &dwDummy);
|
|
if (dwVerResSize)
|
|
{
|
|
BYTE *pbData = new BYTE[dwVerResSize];
|
|
|
|
if (NULL != pbData)
|
|
{
|
|
if(GetFileVersionInfo(szFilePath, 0, dwVerResSize, pbData))
|
|
{
|
|
VS_FIXEDFILEINFO *pffiVersion;
|
|
UINT cbffiVersion;
|
|
|
|
if(VerQueryValue(pbData, TEXT("\\"), (LPVOID *)&pffiVersion, &cbffiVersion))
|
|
{
|
|
*pdwMajorVersion = HIWORD(pffiVersion->dwFileVersionMS);
|
|
*pdwMiddleVersion = LOWORD(pffiVersion->dwFileVersionMS);
|
|
*pdwMinorVersion = HIWORD(pffiVersion->dwFileVersionLS);
|
|
*pdwBuildNumber = LOWORD(pffiVersion->dwFileVersionLS);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL != pbData)
|
|
{
|
|
delete[] pbData;
|
|
pbData = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
ActRenameFile
|
|
MoveFile. If destination file exists, it will be overwritten. If existing destination file cannot be
|
|
overwritten in this session, file replacement is reserved to be held after rebooting.
|
|
---------------------------------------------------------------------------*/
|
|
|
|
BOOL ActRenameFile(LPCTSTR szSrcPath, LPCTSTR tszDstPath, DWORD dwFileAttributes)
|
|
{
|
|
BOOL fReplaceAfterReboot = FALSE;
|
|
BOOL fResult = TRUE;
|
|
|
|
FLE fleKey;
|
|
StringCchCopy(fleKey.szFileName, MAX_PATH, szSrcPath);
|
|
|
|
if (g_FileList.end() == g_FileList.find(fleKey))
|
|
ErrorLog(TEXT("ActRenameFile: WARNING: Cannot find source file [%s] in CmdFileList"), szSrcPath);
|
|
|
|
if (!fExistFile(szSrcPath))
|
|
{
|
|
ErrorLog(TEXT("ActRenameFile: Source file [%s] doesn't exist."), szSrcPath);
|
|
wsprintf(g_szErrorMessage, TEXT("ActRenameFile: Source file [%s] doesn't exist."), szSrcPath);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (fExistFile(tszDstPath))
|
|
{
|
|
SetFileAttributes(tszDstPath, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
if(!DeleteFile(tszDstPath))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
fReplaceAfterReboot = TRUE;
|
|
|
|
DebugLog(TEXT("ActRenameFile: Cannot delete destination file [%s] with error code = %d(%x)"), tszDstPath, dwError, dwError);
|
|
}
|
|
}
|
|
|
|
if (!fReplaceAfterReboot)
|
|
{
|
|
if(MoveFile(szSrcPath, tszDstPath))
|
|
{
|
|
SetFileAttributes(szSrcPath, dwFileAttributes);
|
|
DebugLog(TEXT("ActRenameFile: MoveFile(%s, %s) succeeded."), szSrcPath, tszDstPath);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
DebugLog(TEXT("ActRenameFile: MoveFile(%s, %s) failed with error code = %d(%x)."), szSrcPath, tszDstPath, dwError, dwError);
|
|
DebugLog(TEXT("ActRenameFile: Try again with fReplaceAfterReboot."));
|
|
fReplaceAfterReboot = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fReplaceAfterReboot)
|
|
{
|
|
SetFileAttributes(szSrcPath, dwFileAttributes); // In this case, change file attributes for Src path.
|
|
ReplaceFileOnReboot(szSrcPath, tszDstPath); // Since this function writes lines in reverse order, deletion of
|
|
DebugLog(TEXT("ActRenameFile: ReplaceFileOnReboot(%s, %s)."), szSrcPath, tszDstPath);
|
|
ReplaceFileOnReboot(tszDstPath, NULL); // tszDstPath will come first.
|
|
DebugLog(TEXT("ActRenameFile: ReplaceFileOnReboot(%s, NULL)."), tszDstPath);
|
|
}
|
|
|
|
if (fResult)
|
|
g_FileList.erase(fleKey);
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// This should sync with SERVER.CPP in TIP folder
|
|
// TIP Categories to be added
|
|
const REGISTERCAT c_rgRegCat[] =
|
|
{
|
|
{&GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &CLSID_KorIMX},
|
|
{&GUID_TFCAT_TIP_KEYBOARD, &CLSID_KorIMX},
|
|
{&GUID_TFCAT_PROPSTYLE_CUSTOM, &GUID_PROP_OVERTYPE},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
|
|
// TIP Profile name
|
|
const REGTIPLANGPROFILE c_rgProf[] =
|
|
{
|
|
{ MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), &GUID_Profile, SZ_TIPDISPNAME, SZ_TIPMODULENAME, (IDI_UNIKOR-IDI_ICONBASE), IDS_PROFILEDESC },
|
|
{0, &GUID_NULL, L"", L"", 0, 0}
|
|
};
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RegisterTIP
|
|
|
|
Write neccessary registry key and values for TIP
|
|
---------------------------------------------------------------------------*/
|
|
void RegisterTIP(LPCTSTR szTIPName)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szTIPGuid[MAX_PATH];
|
|
TCHAR szTIPProfileGuid[MAX_PATH];
|
|
TCHAR szSubKey[MAX_PATH];
|
|
DWORD dwValue;
|
|
|
|
DebugLog(TEXT("RegisterTIP: (%s)."), szTIPName);
|
|
|
|
// Run self reg
|
|
// If self reg fails, run custom TIP registration
|
|
if (!CmdRegisterInterface(szTIPName))
|
|
{
|
|
TCHAR szExpandedTIPPath[MAX_PATH];
|
|
|
|
DebugLog(TEXT("RegisterTIP: TIP self reg failed, Run custom reg"));
|
|
|
|
// Expand Env var
|
|
ExpandEnvironmentStrings(szTIPName, szExpandedTIPPath, sizeof(szExpandedTIPPath));
|
|
|
|
// Register TIP CLSID
|
|
if (!RegisterServer(CLSID_KorIMX, SZ_TIPSERVERNAME, szExpandedTIPPath, TEXT("Apartment"), NULL))
|
|
{
|
|
DebugLog(TEXT("RegisterTIP: RegisterServer failed"));
|
|
return;
|
|
}
|
|
|
|
if (!OurRegisterTIP(szExpandedTIPPath, CLSID_KorIMX, SZ_TIPNAME, c_rgProf))
|
|
{
|
|
DebugLog(TEXT("RegisterTIP: szExpandedTIPPath failed"));
|
|
return;
|
|
}
|
|
|
|
if (FAILED(OurRegisterCategories(CLSID_KorIMX, c_rgRegCat)))
|
|
{
|
|
DebugLog(TEXT("RegisterTIP: OurRegisterCategories failed"));
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
// Get String format GUIDs
|
|
CLSIDToStringA(CLSID_KorIMX, szTIPGuid);
|
|
CLSIDToStringA(GUID_Profile, szTIPProfileGuid);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// If no Kor IME is in .default user.
|
|
// Set HKLM [HKLM\Software\Microsoft\CTF\TIP\TIP classid\LanguageProfile\Language ID\Guid Profile]
|
|
// "Enable" = "0" (DWORD)
|
|
if (RegOpenKeyEx(HKEY_USERS, TEXT(".DEFAULT"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (!HKLHelp412ExistInPreload(hKey))
|
|
{
|
|
HKEY hKProfRegKey;
|
|
// Create "Software\Microsoft\CTF\TIP\{CLSID_KorIMX}\LanguageProfile\0x00000412\{CLSID_INPUTPROFILE}"
|
|
wsprintf(szSubKey, TEXT("%s%s\\LanguageProfile\\0x00000412\\%s"), TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\"), szTIPGuid, szTIPProfileGuid);
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_ALL_ACCESS, &hKProfRegKey) == ERROR_SUCCESS)
|
|
{
|
|
// Enabled
|
|
DebugLog(TEXT("RegisterTIP: IME HKL not exist in HKU\\.Default disable TIP"));
|
|
dwValue= 0;
|
|
RegSetValueEx(hKProfRegKey, TEXT("Enable"), 0, REG_DWORD, (BYTE*)&dwValue, sizeof(dwValue));
|
|
RegCloseKey(hKProfRegKey);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RegisterTIPWow64
|
|
|
|
Write neccessary registry key and values for TIP
|
|
---------------------------------------------------------------------------*/
|
|
void RegisterTIPWow64(LPCTSTR szTIPName)
|
|
{
|
|
#if defined(_WIN64)
|
|
// Run just selfreg. Cicero doesn't use "HKLM\Software\Wow6432Node\Microsoft\CTF\TIP\"
|
|
CmdRegisterInterfaceWow64(szTIPName);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// HKL Helper functions
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*---------------------------------------------------------------------------
|
|
GetHKLfromHKLM
|
|
---------------------------------------------------------------------------*/
|
|
HKL GetHKLfromHKLM(LPTSTR argszIMEFile)
|
|
{
|
|
HKL hklAnswer = 0;
|
|
HKEY hKey, hSubKey;
|
|
DWORD i, cbSubKey, cbIMEFile;
|
|
TCHAR szSubKey[MAX_PATH], szIMEFile[MAX_PATH];
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\Keyboard Layouts"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
for (i=0; ;i++)
|
|
{
|
|
cbSubKey = MAX_PATH;
|
|
if (RegEnumKeyEx(hKey, i, szSubKey, &cbSubKey, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
|
|
break;
|
|
|
|
RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey);
|
|
|
|
cbIMEFile=MAX_PATH;
|
|
if (RegQueryValueEx(hSubKey, TEXT("IME File"), NULL, NULL, (LPBYTE)szIMEFile, &cbIMEFile) == ERROR_SUCCESS)
|
|
{
|
|
if (lstrcmpi(argszIMEFile, szIMEFile) == 0)
|
|
{
|
|
RegCloseKey(hSubKey);
|
|
_stscanf(szSubKey, TEXT("%08x"), &hklAnswer);
|
|
break;
|
|
}
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return(hklAnswer);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
HKLHelpSetDefaultKeyboardLayout
|
|
---------------------------------------------------------------------------*/
|
|
void HKLHelpSetDefaultKeyboardLayout(HKEY hKeyHKCU, HKL hKL, BOOL fSetToDefault)
|
|
{
|
|
TCHAR szKL[20];
|
|
BYTE Data[MAX_PATH];
|
|
DWORD cbData;
|
|
TCHAR szSubKey[MAX_PATH];
|
|
HKEY hKey,hSubKey;
|
|
DWORD NumKL;
|
|
|
|
wsprintf(szKL, TEXT("%08x"), hKL);
|
|
|
|
RegOpenKeyEx(hKeyHKCU, TEXT("Keyboard Layout\\Preload"), 0, KEY_ALL_ACCESS, &hKey);
|
|
RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &NumKL, NULL, NULL, NULL, NULL);
|
|
|
|
for (DWORD i=0; i<NumKL; i++)
|
|
{
|
|
wsprintf(szSubKey, TEXT("%d"), i+1);
|
|
cbData = MAX_PATH;
|
|
RegQueryValueEx(hKey, szSubKey, NULL, NULL, Data, &cbData);
|
|
|
|
if (lstrcmpi((LPCTSTR)Data, szKL) == 0)
|
|
break;
|
|
}
|
|
|
|
// if hKL is not exist create it.
|
|
if (NumKL == i)
|
|
{
|
|
wsprintf(szSubKey, TEXT("%d"), i+1);
|
|
RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (const LPBYTE)szKL, (lstrlen(szKL)+1)*sizeof(TCHAR));
|
|
NumKL++;
|
|
}
|
|
|
|
// Set hKL as first, Shift down other.
|
|
if(fSetToDefault)
|
|
{
|
|
for(int j=i; j>0; j--)
|
|
{
|
|
wsprintf(szSubKey, TEXT("%d"),j);
|
|
|
|
cbData = MAX_PATH;
|
|
RegQueryValueEx(hKey, szSubKey, NULL, NULL, Data, &cbData);
|
|
|
|
wsprintf(szSubKey, TEXT("%d"),j+1);
|
|
RegSetValueEx(hKey, szSubKey, 0, REG_SZ, Data, cbData);
|
|
}
|
|
RegSetValueEx(hKey, TEXT("1"), 0, REG_SZ, (const LPBYTE)szKL, (lstrlen(szKL)+1)*sizeof(TCHAR));
|
|
}
|
|
RegCloseKey(hKey);
|
|
|
|
(void)LoadKeyboardLayout(szKL, KLF_ACTIVATE);
|
|
// To activate IME2002 right now without reboot.
|
|
if(fSetToDefault)
|
|
(void)SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKL, SPIF_SENDCHANGE);
|
|
}
|
|
|
|
|
|
#define MAX_NAME 100
|
|
|
|
/*---------------------------------------------------------------------------
|
|
HKLHelp412ExistInPreload
|
|
---------------------------------------------------------------------------*/
|
|
BOOL HKLHelp412ExistInPreload(HKEY hKeyCU)
|
|
{
|
|
HKEY hKey, hSubKey;
|
|
int i ,j;
|
|
DWORD cbName, cbData;
|
|
CHAR szName[MAX_NAME];
|
|
CHAR szData[MAX_NAME];
|
|
HKL hkl;
|
|
FILETIME ftLastWriteTime;
|
|
BOOL fResult = FALSE;
|
|
|
|
if (RegOpenKeyEx(hKeyCU, "Keyboard Layout\\Preload", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
for (j=0; cbName=MAX_NAME, cbData=MAX_NAME, RegEnumValue(hKey, j, szName, &cbName, NULL, NULL, (LPBYTE)szData, &cbData) != ERROR_NO_MORE_ITEMS; j++)
|
|
{
|
|
// See If Korean KL exist. Just compare last LCID part if it's 0x412.
|
|
// IME hkl set 0xE000 on hiword.
|
|
sscanf(szData, "%08x", &hkl);
|
|
if ((HIWORD(hkl) & 0xe000) && LOWORD(hkl) == 0x0412)
|
|
{
|
|
fResult = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RegisterRUNKey
|
|
Register IME using IMM API and TIP
|
|
---------------------------------------------------------------------------*/
|
|
BOOL RegisterRUNKey(LPCTSTR szParam)
|
|
{
|
|
TCHAR szKey[MAX_PATH];
|
|
TCHAR szFilename[MAX_PATH];
|
|
TCHAR *szHitPtr;
|
|
HKEY hRunKey;
|
|
|
|
szHitPtr = _tcschr(szParam, TEXT(','));
|
|
if (szHitPtr == NULL)
|
|
{
|
|
ErrorLog(TEXT("RegisterRUNKey: Invalid parameters (%s)"), szParam);
|
|
wsprintf(g_szErrorMessage, TEXT("RegisterRUNKey: Invalid parameters (%s)"), szParam);
|
|
return(FALSE);
|
|
}
|
|
*szHitPtr = 0;
|
|
StringCchCopy(szKey, ARRAYSIZE(szKey), szParam);
|
|
StringCchCopy(szFilename, ARRAYSIZE(szFilename), szHitPtr + 1);
|
|
|
|
TrimString(szKey);
|
|
TrimString(szFilename);
|
|
|
|
ParseEnvVar(szKey, MAX_PATH);
|
|
ParseEnvVar(szFilename, MAX_PATH);
|
|
|
|
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)
|
|
{
|
|
RegSetValueEx(hRunKey, szKey, 0, REG_SZ, (CONST BYTE *)szFilename, (lstrlen(szFilename)+1)*sizeof(TCHAR));
|
|
RegCloseKey(hRunKey);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
MakeSIDList
|
|
Gets all users' SID and list that in the reg for migration
|
|
---------------------------------------------------------------------------*/
|
|
BOOL MakeSIDList()
|
|
{
|
|
HKEY hKey, hUserList;
|
|
DWORD i, cbName;
|
|
BOOL fNoMoreSID = FALSE;
|
|
TCHAR szMigRegKey[MAX_PATH], szName[500];
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"), 0, KEY_READ, &hKey) ==ERROR_SUCCESS)
|
|
{
|
|
StringCchCopy(szMigRegKey, ARRAYSIZE(g_szIMERootKey), g_szIMERootKey);
|
|
lstrcat(szMigRegKey, TEXT("\\MigrateUser"));
|
|
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szMigRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hUserList, NULL) == ERROR_SUCCESS)
|
|
{
|
|
for (i=0; !fNoMoreSID; i++)
|
|
{
|
|
cbName = 500;
|
|
if (RegEnumKeyEx(hKey, i, szName, &cbName, NULL, NULL, NULL, NULL) == ERROR_NO_MORE_ITEMS)
|
|
fNoMoreSID = TRUE;
|
|
else
|
|
{
|
|
// Do not add Local Service and Network Service pid
|
|
if (lstrlen(szName) > 8)
|
|
RegSetValueEx(hUserList, szName, 0, REG_SZ, (BYTE *)TEXT(""), sizeof(TCHAR)*2);
|
|
}
|
|
}
|
|
|
|
//Change MigrateUser List security settings
|
|
PSECURITY_DESCRIPTOR pSD = CreateSD();
|
|
if (pSD)
|
|
{
|
|
RegSetKeySecurity(hUserList, DACL_SECURITY_INFORMATION, pSD);
|
|
MEMFREE(pSD);
|
|
}
|
|
RegCloseKey(hUserList);
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
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;
|
|
}
|
|
|
|
|