Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5553 lines
175 KiB

////////////////////////////////////////////////////////////////////////////
//
// MUISetup.cpp
//
// This file contains the WinMain() and the UI handling of MUISetup.
//
// MUISetup is compiled as an Unicode application.
//
////////////////////////////////////////////////////////////////////////////
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <userenv.h>
#include <shellapi.h>
#include <regstr.h>
#include <wmistr.h>
#include <wmiumkm.h>
#include <setupapi.h>
#include <shlwapi.h>
#include "sxsapi.h"
#include "muisetup.h"
#define STRSAFE_LIB
#include <strsafe.h>
//
// Context Help IDs
//
//
// Context Help Ids.
//
STDAPI_(BOOL) IsUserAnAdmin();
static int aMuisetupHelpIds[] =
{
207, IDH_COMM_GROUPBOX, // Group Box
IDC_LIST1, IDH_MUISETUP_UILANGUAGE_LIST, // UI Language ListView
IDC_DEF_UI_LANG_COMBO, IDH_MUISETUP_UILANGUAGECOMBO, // UI ComboBox selection
IDC_CHECK_LOCALE, IDH_MUISETUP_CHECKLOCALE, // Match system locale with UI language
IDC_CHECK_UIFONT, IDH_MUISETUP_MATCHUIFONT, // Match system locale with UI language
0, 0
};
//
// Global variables
//
BOOL g_bMatchUIFont;
// Store the special directories listed under [Directories] in mui.inf
TCHAR DirNames[MFL][MAX_PATH],DirNames_ie[MFL][MAX_PATH];
TCHAR szWindowsDir[MAX_PATH];
// The FOLDER where MUISetup.exe is executed.
TCHAR g_szMUISetupFolder[MAX_PATH];
// The FULL PATH for MUISetup.exe.
TCHAR g_szMuisetupPath[MAX_PATH];
// The full path where MUI.inf is located.
TCHAR g_szMUIInfoFilePath[MAX_PATH];
TCHAR g_szVolumeName[MAX_PATH],g_szVolumeRoot[MAX_PATH];
TCHAR g_szMUIHelpFilePath[MAX_PATH],g_szPlatformPath[16],g_szCDLabel[MAX_PATH];
// Windows directory
TCHAR g_szWinDir[MAX_PATH];
TCHAR g_AddLanguages[BUFFER_SIZE];
HANDLE ghMutex = NULL;
HINSTANCE ghInstance;
HWND ghProgDialog; // The progress dialog showed during installation/uninstallation.
HWND ghProgress; // The progress bar in the progress dialog
LANGID gUserUILangId, gSystemUILangId;
BOOL gbIsWorkStation,gbIsServer,gbIsAdvanceServer,gbIsDataCenter,gbIsDomainController;
HINSTANCE g_hUserEnvDll = NULL;
HMODULE g_hAdvPackDll = NULL;
HMODULE g_hSxSDll = NULL;
DWORD g_dwVolumeSerialNo;
BOOL g_InstallCancelled,g_IECopyError,g_bRemoveDefaultUI,g_bRemoveUserUI,g_bCmdMatchLocale,g_bCmdMatchUIFont, g_bReboot;
UILANGUAGEGROUP g_UILanguageGroup;
int g_cdnumber;
// Number of MUI languges to insatll
int gNumLanguages,gNumLanguages_Install,gNumLanguages_Uninstall;
// Flag to indicate whether a language group is found for the locale or not.
BOOL gFoundLangGroup;
LGRPID gLangGroup;
LCID gLCID;
// The language groups installed in the system.
LGRPID gLanguageGroups[32] ;
int gNumLanguageGroups;
PFILERENAME_TABLE g_pFileRenameTable;
int g_nFileRename;
PTYPENOTFALLBACK_TABLE g_pNotFallBackTable;
int g_nNotFallBack;
BOOL g_bSilent=FALSE; // indicate that muisetup should need no user interaction
BOOL g_bNoUI=FALSE; // indicate that muisetup should install with no UI displayed and no user interaction
BOOL g_bRunFromOSSetup=FALSE; // indicated that muisetup is called as part of NT setup/upgrade
BOOL g_bLipLanguages;
BOOL g_bLipAllowSwitch;
//
// Required pfns
//
pfnNtSetDefaultUILanguage gpfnNtSetDefaultUILanguage;
pfnGetUserDefaultUILanguage gpfnGetUserDefaultUILanguage;
pfnGetSystemDefaultUILanguage gpfnGetSystemDefaultUILanguage;
pfnIsValidLanguageGroup gpfnIsValidLanguageGroup;
pfnEnumLanguageGroupLocalesW gpfnEnumLanguageGroupLocalesW;
pfnEnumSystemLanguageGroupsW gpfnEnumSystemLanguageGroupsW;
pfnRtlAdjustPrivilege gpfnRtlAdjustPrivilege;
pfnProcessIdToSessionId gpfnProcessIdToSessionId;
pfnGetDefaultUserProfileDirectoryW gpfnGetDefaultUserProfileDirectoryW = NULL;
pfnLaunchINFSection gpfnLaunchINFSection = NULL;
PSXS_INSTALL_W gpfnSxsInstallW = NULL;
PSXS_UNINSTALL_ASSEMBLYW gpfnSxsUninstallW = NULL;
//
// GetWindowsDirectory stuff
//
UINT WINAPI NT4_GetWindowsDir(LPWSTR pBuf, UINT uSize)
{
return GetWindowsDirectoryW(pBuf, uSize);
}
//
// shlwapi StrToIntEx doesn't work for us
//
DWORD HexStrToInt(LPTSTR lpsz)
{
DWORD dw = 0L;
TCHAR c;
if (! lpsz)
{
return dw;
}
while(*lpsz)
{
c = *lpsz++;
if (c >= TEXT('A') && c <= TEXT('F'))
{
c -= TEXT('A') - 0xa;
}
else if (c >= TEXT('0') && c <= TEXT('9'))
{
c -= TEXT('0');
}
else if (c >= TEXT('a') && c <= TEXT('f'))
{
c -= TEXT('a') - 0xa;
}
else
{
break;
}
dw *= 0x10;
dw += c;
}
return(dw);
}
UINT (WINAPI *pfnGetWindowsDir)(LPWSTR pBuf, UINT uSize) = NT4_GetWindowsDir;
void InitGetWindowsDirectoryPFN(HMODULE hMod)
{
pfnGetWindowsDir = (UINT (WINAPI *) (LPWSTR pBuf, UINT uSize)) GetProcAddress(hMod, "GetSystemWindowsDirectoryW");
if (!pfnGetWindowsDir)
{
pfnGetWindowsDir = NT4_GetWindowsDir;
}
}
////////////////////////////////////////////////////////////////////////////
//
// GetLanguageDisplayName
//
// Get the display name (in the form of "Language (Region)") for the specified
// language ID.
//
// Parameters:
// [IN] langID Language ID
// [OUT] lpBuffer the buffer to receive the display name.
// [IN] nBufferSize the size of buffer, in TCHAR.
//
// Return Values:
// TRUE if succeed. FALSE if the buffer is not big enough.
//
//
// 01-11-2001 YSLin Created.
//
////////////////////////////////////////////////////////////////////////////
BOOL GetLanguageDisplayName(LANGID langID, LPTSTR lpBuffer, int nBufferSize)
{
TCHAR lpLangName[BUFFER_SIZE];
TCHAR lpRegionName[BUFFER_SIZE];
int nCharCount = 0;
HRESULT hresult = S_OK;
nCharCount = GetLocaleInfo(langID, LOCALE_SENGLANGUAGE, lpLangName, ARRAYSIZE(lpLangName)-1);
nCharCount += GetLocaleInfo(langID, LOCALE_SENGCOUNTRY , lpRegionName, ARRAYSIZE(lpRegionName)-1);
nCharCount += 3;
if (nCharCount > nBufferSize)
{
if (nBufferSize)
//*STRSAFE* lstrcpy(lpBuffer, TEXT(""));
hresult = StringCchCopy(lpBuffer , nBufferSize, TEXT(""));
if (!SUCCEEDED(hresult))
{
return FALSE;
}
return (FALSE);
}
//*STRSAFE* wsprintf(lpBuffer, TEXT("%s (%s)"), lpLangName, lpRegionName);
hresult = StringCchPrintf(lpBuffer , nBufferSize, TEXT("%s (%s)"), lpLangName, lpRegionName);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
return (TRUE);
}
//
// Our Message Box
//
int DoMessageBox(HWND hwndParent, UINT uIdString, UINT uIdCaption, UINT uType)
{
TCHAR szString[MAX_PATH+MAX_PATH];
TCHAR szCaption[MAX_PATH];
szString[0] = szCaption[0] = TEXT('\0');
if (uIdString)
LoadString(NULL, uIdString, szString, MAX_PATH+MAX_PATH-1);
if (uIdCaption)
LoadString(NULL, uIdCaption, szCaption, MAX_PATH-1);
return MESSAGEBOX(hwndParent, szString, szCaption, uType);
}
////////////////////////////////////////////////////////////////////////////
//
// DoMessageBoxFromResource
//
// Load a format string from resource, and format the string using the
// specified arguments. Display a message box using the formatted string.
//
// Parameters:
//
// Return Values:
// The return value from MessageBox.
//
// Remarks:
// The length of the formatted string is limited by BUFFER_SIZE.
//
// 08-07-2000 YSLin Created.
//
////////////////////////////////////////////////////////////////////////////
int DoMessageBoxFromResource(HWND hwndParent, HMODULE hInstance, UINT uIdString, LONG_PTR* lppArgs, UINT uIdCaption, UINT uType)
{
TCHAR szString[BUFFER_SIZE];
TCHAR szCaption[BUFFER_SIZE];
szString[0] = szCaption[0] = TEXT('\0');
if (uIdCaption)
LoadString(hInstance, uIdCaption, szCaption, MAX_PATH-1);
FormatStringFromResource(szString, sizeof(szString)/sizeof(TCHAR), hInstance, uIdString, lppArgs);
return (MESSAGEBOX(hwndParent, szString, szCaption, uType));
}
BOOL IsMatchingPlatform(void)
{
BOOL bx86Image = FALSE;
BOOL bRet = TRUE;
TCHAR szWOW64Path[MAX_PATH];
#ifdef _X86_
bx86Image = TRUE;
#endif
if (GetSystemWow64Directory(szWOW64Path, ARRAYSIZE(szWOW64Path)) &&
bx86Image)
bRet = FALSE;
return bRet;
}
//
// Program Entry Point
//
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
int result = 0;
BOOL bForwardCall=FALSE;
TCHAR lpCommandLine[BUFFER_SIZE+1];
HMODULE hMod;
int error,nNumArgs=0,i;
LONG_PTR lppArgs[3];
LPWSTR *pszArgv=NULL;
HRESULT hresult;
if (!IsUserAnAdmin())
{
//
// "You must have administrator right to run muisetup.\n\n"
// "If you want to switch your UI language, please use the regional option from control panel."
//
LogFormattedMessage(ghInstance, IDS_ADMIN_L, NULL);
DoMessageBox(NULL, IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
return result;
}
//
// Bail out if image doesn't match the running platform
//
if (!IsMatchingPlatform())
{
DoMessageBox(NULL, IDS_WRONG_IMAGE, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
return result;
}
ghInstance = hInstance;
//
// Let make sure this NT5, and let's initialize all our pfns
//
if (!InitializePFNs())
{
//
// Not an NT5 system. The following should be ANSI to work on Win9x.
//
CHAR szString[MAX_PATH];
CHAR szCaption[MAX_PATH];
LoadStringA(NULL, IDS_ERROR_NT5_ONLY, szString, MAX_PATH-1);
LoadStringA(NULL, IDS_MAIN_TITLE, szCaption, MAX_PATH-1);
MessageBoxA(NULL, szString, szCaption, MB_OK | MB_ICONINFORMATION);
result = 1;
goto Exit;
}
//
// Check if the program has already been running ?
//
if (CheckMultipleInstances())
{
result = 1;
goto Exit;
}
//
// Initialize any global vars
//
InitGlobals();
//
// Check if I'm launching from previous version of muisetup
//
// I.E. muisetup /$_transfer_$ path_of_MUI_installation_files
//
pszArgv = CommandLineToArgvW((LPCWSTR) GetCommandLineW(), &nNumArgs);
lpCommandLine[0]=TEXT('\0');
if (pszArgv)
{
for (i=1; i<nNumArgs;i++)
{
if (!_tcsicmp(pszArgv[i],MUISETUP_FORWARDCALL_TAG) && ((i+1) < nNumArgs) )
{
Set_SourcePath_FromForward(pszArgv[i+1]);
bForwardCall=TRUE;
i++;
}
else
{
//*STRSAFE* _tcscat(lpCommandLine,pszArgv[i]);
hresult = StringCchCat(lpCommandLine , ARRAYSIZE(lpCommandLine), pszArgv[i]);
if (!SUCCEEDED(hresult))
{
result = 1;
goto Exit;
}
//*STRSAFE* _tcscat(lpCommandLine,TEXT(" "));
hresult = StringCchCat(lpCommandLine , ARRAYSIZE(lpCommandLine), TEXT(" "));
if (!SUCCEEDED(hresult))
{
result = 1;
goto Exit;
}
}
}
}
//
// Check if there is a new version of muisetup.exe at %windir%\mui
//
// If it's the case, transfer all the control to it
//
if (!bForwardCall)
{
if ( MUIShouldSwitchToNewVersion(lpCommandLine) )
{
result = 0;
goto Exit;;
}
}
InitCommonControls();
BeginLog();
//
// Block the installation of Personal and Professional
// NOTE: this is here for only the .NET server release, re-enable pro sku after this.
//
#ifdef MUI_MAGIC
if (CheckProductType(MUI_IS_WIN2K_PERSONAL) || CheckProductType(MUI_IS_WIN2K_PRO))
#else
if (CheckProductType(MUI_IS_WIN2K_PERSONAL))
#endif
{
//
// "Windows XP MultiLanguage Version cannot be installed on this platform."
//
DoMessageBox(NULL, IDS_ERROR_NT5_ONLY, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
result = 1;
goto Exit;
}
//
// Check to see if a command line has been used
//
if(lpCommandLine && NextCommandTag(lpCommandLine))
{
lppArgs[0] = (LONG_PTR)lpCommandLine;
LogFormattedMessage(NULL, IDS_COMMAND_LOG, lppArgs);
LogMessage(TEXT("")); //Add a carriage return and newline
ParseCommandLine(lpCommandLine);
}
else
{
//
// MUI version needs to match OS version
//
if (!checkversion(TRUE))
{
DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
result = 1;
goto Exit;
}
if (WelcomeDialog(0))
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), 0, DialogFunc);
}
result = 1;
}
Exit:
//
// Cleanup
//
if ( pszArgv)
{
GlobalFree((HGLOBAL) pszArgv);
}
Muisetup_Cleanup();
return result;
}
////////////////////////////////////////////////////////////////////////////////////
//
// CheckMultipleInstances
//
// Checks if another instance is running, and if so, it switches to it.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckMultipleInstances(void)
{
ghMutex = CreateMutex(NULL, TRUE, TEXT("Muisetup_Mutex"));
if (ghMutex && (GetLastError() == ERROR_ALREADY_EXISTS))
{
const int idsTitles[] = {IDS_MAIN_TITLE, IDS_INSTALL_TITLE, IDS_PROG_TITLE_2, IDS_PROG_TITLE_3, IDS_UNINSTALL_TITLE};
HWND hWnd;
TCHAR szTitle[MAX_PATH];
int i;
//
// Find the running instance by searching possible Window titles
//
for (i=0; i<ARRAYSIZE(idsTitles); i++)
{
LoadString(NULL, idsTitles[i], szTitle, MAX_PATH-1);
hWnd = FindWindow(NULL,szTitle);
if (hWnd && IsWindow(hWnd))
{
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
break;
}
}
//
// Always bail out if there is another running instance
//
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// InitializePFNs
//
// Initialize NT5 specific pfns
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InitializePFNs()
{
HMODULE hModule;
SYSTEM_INFO SystemInfo;
LONG_PTR lppArgs[2];
HRESULT hresult;
//
// Determine platform
//
GetSystemInfo( &SystemInfo );
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ||
SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
{
#if defined(_AMD64_)
//*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("amd64\\"));
hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("amd64\\"));
if (!SUCCEEDED(hresult))
{
return FALSE;
}
#elif defined(_IA64_)
//*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("ia64\\"));
hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("ia64\\"));
if (!SUCCEEDED(hresult))
{
return FALSE;
}
#else
//*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("i386\\"));
hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("i386\\"));
if (!SUCCEEDED(hresult))
{
return FALSE;
}
#endif
}
else
{
// This is NOT supported yet
return FALSE;
}
//
// Let's bring ntdll!NtSetDefaultUILanguage
//
hModule = GetModuleHandle(TEXT("ntdll.dll"));
if (!hModule)
return FALSE;
gpfnNtSetDefaultUILanguage =
(pfnNtSetDefaultUILanguage)GetProcAddress(hModule,
"NtSetDefaultUILanguage");
if (!gpfnNtSetDefaultUILanguage)
return FALSE;
gpfnRtlAdjustPrivilege =
(pfnRtlAdjustPrivilege)GetProcAddress(hModule,
"RtlAdjustPrivilege");
if (!gpfnRtlAdjustPrivilege)
return FALSE;
//
// Let's get out from kernel32.dll :
// - GetUserDefaultUILanguage
// - GetSystemDefaultUILanguage
// - EnumLanguageGroupLocalesW
//
hModule = GetModuleHandle(TEXT("kernel32.dll"));
if (!hModule)
return FALSE;
gpfnGetUserDefaultUILanguage =
(pfnGetUserDefaultUILanguage)GetProcAddress(hModule,
"GetUserDefaultUILanguage");
if (!gpfnGetUserDefaultUILanguage)
return FALSE;
gpfnGetSystemDefaultUILanguage =
(pfnGetSystemDefaultUILanguage)GetProcAddress(hModule,
"GetSystemDefaultUILanguage");
if (!gpfnGetSystemDefaultUILanguage)
return FALSE;
gpfnIsValidLanguageGroup =
(pfnIsValidLanguageGroup)GetProcAddress(hModule,
"IsValidLanguageGroup");
if (!gpfnIsValidLanguageGroup)
return FALSE;
gpfnEnumLanguageGroupLocalesW =
(pfnEnumLanguageGroupLocalesW)GetProcAddress(hModule,
"EnumLanguageGroupLocalesW");
if (!gpfnEnumLanguageGroupLocalesW)
return FALSE;
gpfnEnumSystemLanguageGroupsW =
(pfnEnumSystemLanguageGroupsW)GetProcAddress(hModule,
"EnumSystemLanguageGroupsW");
if (!gpfnEnumSystemLanguageGroupsW)
return FALSE;
gpfnProcessIdToSessionId =
(pfnProcessIdToSessionId) GetProcAddress(hModule,
"ProcessIdToSessionId");
//
// Initialize the pfnGetWindowsDirectory
//
InitGetWindowsDirectoryPFN(hModule);
//
// Try to load userenv.dll
//
g_hUserEnvDll = LoadLibrary(TEXT("userenv.dll"));
if (g_hUserEnvDll)
{
gpfnGetDefaultUserProfileDirectoryW =
(pfnGetDefaultUserProfileDirectoryW)GetProcAddress(g_hUserEnvDll,
"GetDefaultUserProfileDirectoryW");
}
else
{
LogFormattedMessage(ghInstance, IDS_LOAD_USERENV_L, NULL);
return (FALSE);
}
g_hAdvPackDll = LoadLibrary(TEXT("AdvPack.dll"));
if (g_hAdvPackDll == NULL)
{
LogFormattedMessage(ghInstance, IDS_LOAD_ADVPACK_L, NULL);
return (FALSE);
}
gpfnLaunchINFSection = (pfnLaunchINFSection)GetProcAddress(g_hAdvPackDll, "LaunchINFSection");
if (gpfnLaunchINFSection == NULL)
{
lppArgs[0] = (LONG_PTR)TEXT("LaunchINFSection");
LogFormattedMessage(ghInstance, IDS_LOAD_ADVPACK_API_L, lppArgs);
return (FALSE);
}
g_hSxSDll = LoadLibrary(TEXT("SxS.dll"));
if (g_hSxSDll)
{
gpfnSxsInstallW = (PSXS_INSTALL_W)GetProcAddress(g_hSxSDll, SXS_INSTALL_W);
gpfnSxsUninstallW = (PSXS_UNINSTALL_ASSEMBLYW)GetProcAddress(g_hSxSDll, SXS_UNINSTALL_ASSEMBLYW);
}
else
{
LogFormattedMessage(ghInstance, IDS_LOAD_SXS_L, NULL);
return (FALSE);
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// Find the path of execution file and set path for MUI.INF
//
//
////////////////////////////////////////////////////////////////////////////////////
void SetSourcePath(LPTSTR lpszPreviousMUIPath)
{
UINT_PTR cb;
LPTSTR lpszPath,lpszNext=NULL;
TCHAR szHelpPath[MAX_PATH+1],szHelpFile[MAX_PATH+1];
HRESULT hresult;
if (!lpszPreviousMUIPath)
{
g_szMUISetupFolder[0]=TEXT('\0');
cb = GetModuleFileName (ghInstance, g_szMuisetupPath, MAX_PATH);
//*STRSAFE* _tcscpy(g_szMUISetupFolder,g_szMuisetupPath);
hresult = StringCchCopy(g_szMUISetupFolder , ARRAYSIZE(g_szMUISetupFolder), g_szMuisetupPath);
if (!SUCCEEDED(hresult))
{
return;
}
//
// Get folder for MUISetup.
//
lpszPath = g_szMUISetupFolder;
while ( (lpszNext=_tcschr(lpszPath,TEXT('\\'))) )
{
lpszPath = lpszNext+1;
}
*lpszPath=TEXT('\0');
}
else
{
//*STRSAFE* _tcscpy(g_szMUISetupFolder,lpszPreviousMUIPath);
hresult = StringCchCopy(g_szMUISetupFolder , ARRAYSIZE(g_szMUISetupFolder), lpszPreviousMUIPath);
if (!SUCCEEDED(hresult))
{
return ;
}
}
//*STRSAFE* _tcscpy(g_szMUIInfoFilePath,g_szMUISetupFolder);
hresult = StringCchCopy(g_szMUIInfoFilePath , ARRAYSIZE(g_szMUIInfoFilePath), g_szMUISetupFolder);
if (!SUCCEEDED(hresult))
{
return;
}
//*STRSAFE* _tcscat(g_szMUIInfoFilePath,MUIINFFILENAME);
hresult = StringCchCat(g_szMUIInfoFilePath , ARRAYSIZE(g_szMUIInfoFilePath), MUIINFFILENAME);
if (!SUCCEEDED(hresult))
{
return ;
}
//
// Check the location of help file
//
//*STRSAFE* _tcscpy(szHelpPath,g_szMUISetupFolder);
hresult = StringCchCopy(szHelpPath , ARRAYSIZE(szHelpPath), g_szMUISetupFolder);
if (!SUCCEEDED(hresult))
{
return ;
}
LoadString(NULL, IDS_HELPFILE,szHelpFile,MAX_PATH);
//*STRSAFE* _tcscat(szHelpPath,szHelpFile);
hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), szHelpFile);
if (!SUCCEEDED(hresult))
{
return;
}
if (!FileExists(szHelpPath))
{
pfnGetWindowsDir(szHelpPath, MAX_PATH);
//*STRSAFE* _tcscat(szHelpPath, TEXT("\\"));
hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return ;
}
//*STRSAFE* _tcscat(szHelpPath,HELPDIR); // HELP\MUI
hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), HELPDIR);
if (!SUCCEEDED(hresult))
{
return ;
}
//*STRSAFE* _tcscat(szHelpPath, TEXT("\\"));
hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return ;
}
//*STRSAFE* _tcscat(szHelpPath,szHelpFile);
hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), szHelpFile);
if (!SUCCEEDED(hresult))
{
return ;
}
if (FileExists(szHelpPath))
{
//*STRSAFE* _tcscpy(g_szMUIHelpFilePath,szHelpPath);
hresult = StringCchCopy(g_szMUIHelpFilePath , ARRAYSIZE(g_szMUIHelpFilePath), szHelpPath);
if (!SUCCEEDED(hresult))
{
return ;
}
}
}
else
{
//*STRSAFE* _tcscpy(g_szMUIHelpFilePath,szHelpPath);
hresult = StringCchCopy(g_szMUIHelpFilePath , ARRAYSIZE(g_szMUIHelpFilePath), szHelpPath);
if (!SUCCEEDED(hresult))
{
return ;
}
}
if(g_szMUIInfoFilePath[1] == TEXT(':'))
{
_tcsncpy(g_szVolumeRoot,g_szMUIInfoFilePath,3);
g_szVolumeRoot[3]=TEXT('\0');
GetVolumeInformation(g_szVolumeRoot, g_szVolumeName, sizeof(g_szVolumeName)/sizeof(TCHAR),
&g_dwVolumeSerialNo, 0, 0, 0, 0);
}
if (!GetPrivateProfileString( MUI_CDLAYOUT_SECTION,
MUI_CDLABEL,
TEXT(""),
g_szCDLabel,
MAX_PATH-1,
g_szMUIInfoFilePath))
{
LoadString(NULL, IDS_CHANGE_CDROM, g_szCDLabel, MAX_PATH-1);
}
}
//
// Set MUI installation source path from the instance that transfer control to this instance
//
void Set_SourcePath_FromForward(LPCTSTR lpszPath)
{
TCHAR szMUIPath[MAX_PATH+1];
int nidx=0;
if (!lpszPath)
{
return;
}
while (*lpszPath)
{
if (*lpszPath == MUI_FILLER_CHAR)
{
szMUIPath[nidx++]=TEXT(' ');
}
else
{
szMUIPath[nidx++]=*lpszPath;
}
lpszPath++;
}
szMUIPath[nidx]=TEXT('\0');
SetSourcePath(szMUIPath);
}
//
// Check if the version of current instance is older than that in %windir%\mui.
// If it's the case, then we transfer control to %windir%\mui\muisetup.
//
BOOL MUIShouldSwitchToNewVersion(LPTSTR lpszCommandLine)
{
BOOL bResult=FALSE;
TCHAR szTarget[ MAX_PATH+1 ];
HRESULT hresult;
ULONG ulHandle,ulBytes;
pfnGetWindowsDir(szTarget, MAX_PATH); //%windir% //
//*STRSAFE* _tcscat(szTarget, TEXT("\\"));
hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return bResult;
}
//*STRSAFE* _tcscat(szTarget, MUIDIR); // \MUI //
hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
if (!SUCCEEDED(hresult))
{
return bResult;
}
//*STRSAFE* _tcscat(szTarget, TEXT("\\"));
hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return bResult;
}
//*STRSAFE* _tcscat(szTarget,MUISETUP_EXECUTION_FILENAME);
hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUISETUP_EXECUTION_FILENAME);
if (!SUCCEEDED(hresult))
{
return bResult;
}
//
// If %windir%\mui\muisetup.exe doesn't exist or current muisetup.exe is launched from %windir%\mui then
// do nothing
//
if (!FileExists(szTarget) || !_tcsicmp(szTarget,g_szMuisetupPath))
{
return bResult;
}
//
// If %windir%mui\muisetup.exe is not a execuatble then do nothing
//
ulBytes = GetFileVersionInfoSize( szTarget, &ulHandle );
if ( ulBytes == 0 )
return bResult;
//
// Compare the version stamp
//
// if version of g_szMuisetupPath (cuurent process) < %windir%\mui\muisetup
// then switch control to it
//
if (CompareMuisetupVersion(g_szMuisetupPath,szTarget))
{
bResult = TRUE;
MUI_TransferControlToNewVersion(szTarget,lpszCommandLine);
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////
//
// MUI_TransferControlToNewVersion
//
// Call %windir%\mui\muisetup.exe /$_transfer_$ mui_installation_file_path command_line
//
////////////////////////////////////////////////////////////////////////////////////
BOOL MUI_TransferControlToNewVersion(LPTSTR lpszExecutable,LPTSTR lpszCommandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR szAppName[BUFFER_SIZE],szDropPath[MAX_PATH];
int nIdx,nLen;
BOOL bResult=FALSE;
HRESULT hresult;
if (!lpszExecutable)
{
return bResult;
}
nLen=_tcslen(g_szMUISetupFolder);
for (nIdx=0; nIdx <nLen ; nIdx++)
{
if (g_szMUISetupFolder[nIdx]==TEXT(' '))
{
szDropPath[nIdx]=MUI_FILLER_CHAR;
}
else
{
szDropPath[nIdx]=g_szMUISetupFolder[nIdx];
}
}
szDropPath[nIdx]=TEXT('\0');
//*STRSAFE* wsprintf(szAppName,TEXT("%s %s %s %s"),lpszExecutable,MUISETUP_FORWARDCALL_TAG,szDropPath,lpszCommandLine);
hresult = StringCchPrintf(szAppName , ARRAYSIZE(szAppName), TEXT("%s %s %s %s"),lpszExecutable,MUISETUP_FORWARDCALL_TAG,szDropPath,lpszCommandLine);
if (!SUCCEEDED(hresult))
{
return bResult;
}
//
// Run the process
//
memset( &si, 0x00, sizeof(si));
si.cb = sizeof(STARTUPINFO);
if (!CreateProcess(NULL,
szAppName,
NULL,
NULL,
FALSE,
0L,
NULL, NULL,
&si,
&pi) )
return bResult;
bResult =TRUE;
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////
//
// CheckVolumeChange
//
// Make sure that MUI CD-ROM is put in the CD drive.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckVolumeChange()
{
BOOL bResult = FALSE;
TCHAR szVolumeName[MAX_PATH],szCaption[MAX_PATH+1],szMsg[MAX_PATH+1],szMsg00[MAX_PATH+1],szMsg01[MAX_PATH+1];
DWORD dwVolumeSerialNo;
BOOL bInit=TRUE;
LONG_PTR lppArgs[3];
if( *g_szVolumeName &&
GetVolumeInformation(g_szVolumeRoot, szVolumeName, ARRAYSIZE(szVolumeName),
&dwVolumeSerialNo, 0, 0, 0, 0) )
{
while( lstrcmp(szVolumeName,g_szVolumeName) || (dwVolumeSerialNo != g_dwVolumeSerialNo) )
{
if (bInit)
{
szCaption[0]=szMsg00[0]=szMsg01[0]=TEXT('\0');
LoadString(NULL, IDS_MAIN_TITLE, szCaption, MAX_PATH);
lppArgs[0] = (LONG_PTR)g_szCDLabel;
lppArgs[1] = (LONG_PTR)g_cdnumber;
FormatStringFromResource(szMsg, ARRAYSIZE(szMsg), ghInstance, IDS_CHANGE_CDROM2, lppArgs);
bInit=FALSE;
}
if (MESSAGEBOX(NULL, szMsg,szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
{
return TRUE;
}
GetVolumeInformation(g_szVolumeRoot, szVolumeName, ARRAYSIZE(szVolumeName),
&dwVolumeSerialNo, 0, 0, 0, 0);
}
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////
//
// InitGlobals
//
// Initialize global variables
//
////////////////////////////////////////////////////////////////////////////////////
void InitGlobals(void)
{
// User UI Language Id
gUserUILangId = gpfnGetUserDefaultUILanguage();
gSystemUILangId = gpfnGetSystemDefaultUILanguage();
// System Windows directory
szWindowsDir[0] = TEXT('\0');
pfnGetWindowsDir(szWindowsDir, MAX_PATH);
// Does this have admin privliges ?
gbIsWorkStation=CheckProductType(MUI_IS_WIN2K_PRO);
gbIsServer= CheckProductType(MUI_IS_WIN2K_SERVER);
gbIsAdvanceServer= (CheckProductType(MUI_IS_WIN2K_ADV_SERVER_OR_DATACENTER) || CheckProductType(MUI_IS_WIN2K_ENTERPRISE));
gbIsDataCenter=(CheckProductType(MUI_IS_WIN2K_DATACENTER) || CheckProductType(MUI_IS_WIN2K_DC_DATACENTER));
gbIsDomainController=CheckProductType(MUI_IS_WIN2K_DC);
if (gbIsDomainController)
{
if ( (!gbIsWorkStation) && (!gbIsServer) && (!gbIsAdvanceServer))
{
gbIsServer=TRUE;
}
}
// Fill in system supported language groups
gpfnEnumSystemLanguageGroupsW(EnumLanguageGroupsProc, LGRPID_SUPPORTED, 0);
pfnGetWindowsDir(g_szWinDir, sizeof(g_szWinDir));
g_AddLanguages[0]=TEXT('\0');
g_szVolumeName[0]=TEXT('\0');
g_szVolumeRoot[0]=TEXT('\0');
g_szMUIHelpFilePath[0]=TEXT('\0');
g_szCDLabel[0]=TEXT('\0');
g_dwVolumeSerialNo = 0;
gNumLanguages=0;
gNumLanguages_Install=0;
gNumLanguages_Uninstall=0;
g_InstallCancelled = FALSE;
g_bRemoveDefaultUI=FALSE;
g_cdnumber=0;
g_pFileRenameTable=NULL;
g_nFileRename=0;
g_pNotFallBackTable=NULL;
g_nNotFallBack=0;
// Detect source path for installation
SetSourcePath(NULL);
// Initialize the context for diamond FDI
Muisetup_InitDiamond();
// Get all installed UI languages
MUIGetAllInstalledUILanguages();
}
BOOL CALLBACK EnumLanguageGroupsProc(
LGRPID LanguageGroup, // language group identifier
LPTSTR lpLanguageGroupString, // pointer to language group identifier string
LPTSTR lpLanguageGroupNameString, // pointer to language group name string
DWORD dwFlags, // flags
LONG_PTR lParam) // user-supplied parameter
{
gLanguageGroups[gNumLanguageGroups] = LanguageGroup;
gNumLanguageGroups++;
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// Muisetup_Cleanup
//
// Muisetup cleanup code.
//
////////////////////////////////////////////////////////////////////////////////////
void Muisetup_Cleanup()
{
//
// Free userenv.dll, if needed
//
if (g_hUserEnvDll)
{
FreeLibrary(g_hUserEnvDll);
}
if (g_hAdvPackDll)
{
FreeLibrary(g_hAdvPackDll);
}
if (g_hSxSDll)
{
FreeLibrary(g_hSxSDll);
}
if (ghMutex)
{
CloseHandle(ghMutex);
}
// Free/release diamond DLL
Muisetup_FreeDiamond();
return;
}
////////////////////////////////////////////////////////////////////////////////////
//
// OpenMuiKey
//
// Opens the Registry Key where installed languages are stored
//
////////////////////////////////////////////////////////////////////////////////////
HKEY OpenMuiKey(REGSAM samDesired)
{
DWORD dwDisposition;
HKEY hKey;
TCHAR lpSubKey[BUFFER_SIZE];
HRESULT hresult;
//*STRSAFE* _tcscpy(lpSubKey, REG_MUI_PATH);
hresult = StringCchCopy(lpSubKey , ARRAYSIZE(lpSubKey), REG_MUI_PATH);
if (!SUCCEEDED(hresult))
{
return NULL;
}
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
lpSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
samDesired,
NULL,
&hKey,
&dwDisposition) != ERROR_SUCCESS)
{
hKey = NULL;
}
return hKey;
}
void DialogCleanUp(HWND hwndDlg)
{
HWND hList = GetDlgItem(hwndDlg, IDC_LIST1);
int iCount = ListView_GetItemCount(hList);
LVITEM lvItem;
PMUILANGINFO pMuiLangInfo;
while (iCount--)
{
lvItem.mask = LVIF_PARAM;
lvItem.iItem = iCount;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = 0;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
lvItem.lParam = 0;
ListView_GetItem(hList, &lvItem);
pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
if (pMuiLangInfo)
{
if (pMuiLangInfo->lpszLcid)
LocalFree(pMuiLangInfo->lpszLcid);
LocalFree(pMuiLangInfo);
}
}
}
////////////////////////////////////////////////////////////////////////////////////
//
// DialogFunc
//
// Callback function for main dialog (102)
//
////////////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK DialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
SendMessage(hwndDlg, WM_SETICON , (WPARAM)ICON_BIG, (LPARAM)LoadIcon(ghInstance,MAKEINTRESOURCE(MUI_ICON)));
SendMessage(hwndDlg, WM_SETICON , (WPARAM)ICON_SMALL, (LPARAM)LoadIcon(ghInstance,MAKEINTRESOURCE(MUI_ICON)));
InitializeInstallDialog(hwndDlg, uMsg, wParam, lParam);
return TRUE;
case WM_HELP:
{
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
g_szMUIHelpFilePath,
HELP_WM_HELP,
(DWORD_PTR)(LPTSTR)aMuisetupHelpIds );
break;
}
case WM_CONTEXTMENU: // right mouse click
{
WinHelp( (HWND)wParam,
g_szMUIHelpFilePath,
HELP_CONTEXTMENU,
(DWORD_PTR)(LPTSTR)aMuisetupHelpIds );
break;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EnableWindow(hwndDlg, FALSE);
if (StartGUISetup(hwndDlg))
{
EndDialog(hwndDlg, 0);
}
else
{
EnableWindow(hwndDlg, TRUE);
SetFocus(hwndDlg);
}
return TRUE;
case IDCANCEL:
EndDialog(hwndDlg, 0);
return TRUE;
case IDC_DEF_UI_LANG_COMBO:
switch(HIWORD(wParam))
{
case CBN_SELCHANGE:
UpdateCombo(hwndDlg);
return TRUE;
default:
break;
}
break;
case IDC_CHECK_LOCALE:
if (BST_CHECKED == IsDlgButtonChecked( hwndDlg, IDC_CHECK_LOCALE))
{
EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), TRUE);
}
else
{
CheckDlgButton(hwndDlg, IDC_CHECK_UIFONT, BST_UNCHECKED);
EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), FALSE);
}
break;
}
//
// End of WM_COMMAND case
//
break;
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code)
{
case(NM_CUSTOMDRAW):
ListViewCustomDraw(hwndDlg, (LPNMLVCUSTOMDRAW)lParam);
return TRUE;
break;
case (LVN_ITEMCHANGING):
return ListViewChanging( hwndDlg,
IDC_LIST1,
(NM_LISTVIEW *)lParam);
break;
case (LVN_ITEMCHANGED) :
ListViewChanged( hwndDlg,
IDC_LIST1,
(NM_LISTVIEW *)lParam );
break;
default:
return FALSE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
case WM_DESTROY:
DialogCleanUp(hwndDlg);
return TRUE;
default:
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// ListViewChanging
//
// Processing for a LVN_ITEMCHANGING message
//
////////////////////////////////////////////////////////////////////////////////////
BOOL ListViewChanging(HWND hDlg, int iID, NM_LISTVIEW *pLV)
{
HWND hwndLV = GetDlgItem(hDlg, iID);
PMUILANGINFO pMuiLangInfo;
//
// Make sure it's a state change message
//
if ((!(pLV->uChanged & LVIF_STATE)) || ((pLV->uNewState & 0x3000) == 0))
return FALSE;
//
// Don't let the System Default be unchecked
//
GetMuiLangInfoFromListView(hwndLV, pLV->iItem, &pMuiLangInfo);
if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
return TRUE;
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// ListViewChanged
//
// Processing for a LVN_ITEMCHANGED message
//
////////////////////////////////////////////////////////////////////////////////////
BOOL ListViewChanged(HWND hDlg, int iID, NM_LISTVIEW *pLV)
{
HWND hwndLV = GetDlgItem(hDlg, iID);
PMUILANGINFO pMuiLangInfo;
int iCount;
BOOL bChecked;
//
// Make sure it's a state change message.
//
if ((!(pLV->uChanged & LVIF_STATE)) ||
((pLV->uNewState & 0x3000) == 0))
{
return (FALSE);
}
//
// Get the state of the check box for the currently selected item.
//
bChecked = ListView_GetCheckState(hwndLV, pLV->iItem) ? TRUE : FALSE;
//
// Don't let the System Default or the current user UI language be unchecked
//
GetMuiLangInfoFromListView(hwndLV, pLV->iItem, &pMuiLangInfo);
if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
{
//
// Set Default check state
//
if (bChecked == FALSE)
{
ListView_SetCheckState( hwndLV,
pLV->iItem,
TRUE );
}
return FALSE;
}
//
// Deselect all items.
//
iCount = ListView_GetItemCount(hwndLV);
while (iCount > 0)
{
iCount--;
ListView_SetItemState( hwndLV,
iCount,
0,
LVIS_FOCUSED | LVIS_SELECTED );
}
//
// Make sure this item is selected.
//
ListView_SetItemState( hwndLV,
pLV->iItem,
LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED );
//
// Update the combo box
//
PostMessage( hDlg,
WM_COMMAND,
MAKEWPARAM(IDC_DEF_UI_LANG_COMBO, CBN_SELCHANGE),
0L);
//
// Return success.
//
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// ListViewCustomDraw
//
// Processing for list view WM_CUSTOMDRAW notification.
//
////////////////////////////////////////////////////////////////////////////////////
void ListViewCustomDraw(HWND hDlg, LPNMLVCUSTOMDRAW pDraw)
{
HWND hwndLV = GetDlgItem(hDlg, IDC_LIST1);
PMUILANGINFO pMuiLangInfo;
//
// Tell the list view to notify me of item draws.
//
if (pDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
return;
}
//
// Handle the Item Prepaint.
//
if (pDraw->nmcd.dwDrawStage & CDDS_ITEMPREPAINT)
{
//
// Check to see if the item being drawn is the system default or
// the current active ui language
//
GetMuiLangInfoFromListView(hwndLV, (int)pDraw->nmcd.dwItemSpec, &pMuiLangInfo);
if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
{
pDraw->clrText = (GetSysColor(COLOR_GRAYTEXT));
}
}
//
// Do the default action.
//
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_DODEFAULT);
}
////////////////////////////////////////////////////////////////////////////////////
//
// StartGUISetup
//
// Creates dialog with progress bar for installation
//
////////////////////////////////////////////////////////////////////////////////////
BOOL StartGUISetup(HWND hwndDlg)
{
LONG_PTR lppArgs[3];
ULONG ulParam[2];
TCHAR lpMessage[BUFFER_SIZE];
TCHAR szBuf[BUFFER_SIZE];
INT64 ulSizeNeed,ulSizeAvailable;
BOOL success;
HWND hList;
HWND hCombo;
int iIndex;
TCHAR lpAddLanguages[BUFFER_SIZE];
TCHAR lpRemoveLanguages[BUFFER_SIZE];
TCHAR lpDefaultUILang[BUFFER_SIZE];
TCHAR szPostParameter[BUFFER_SIZE];
int installLangCount; // The number of MUI languages to be installed
int uninstallLangCount; // The number of MUI langauges to be uninstalled.
LANGID langID;
HRESULT hresult;
INSTALL_LANG_GROUP installLangGroup;
//
// (0) Check available disk space
//
if(!IsSpaceEnough(hwndDlg,&ulSizeNeed,&ulSizeAvailable))
{
ulParam[0] = (ULONG) (ulSizeNeed/1024);
ulParam[1] = (ULONG) (ulSizeAvailable/1024);
LoadString(ghInstance, IDS_DISKSPACE_NOTENOUGH, lpMessage, ARRAYSIZE(lpMessage)-1);
LoadString(ghInstance, IDS_ERROR_DISKSPACE, szBuf, ARRAYSIZE(szBuf)-1);
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
lpMessage,
0,
0,
lpMessage,
ARRAYSIZE(lpMessage)-1,
(va_list *)ulParam);
LogMessage(lpMessage);
MESSAGEBOX(NULL, lpMessage, szBuf, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
//
// Let User has another chance to reselect
//
return FALSE;
}
installLangGroup.bFontLinkRegistryTouched = FALSE;
installLangGroup.NotDeleted = 0;
//
// (1) Install Language Group First
//
ConvertMUILangToLangGroup(hwndDlg, &installLangGroup);
hList=GetDlgItem(hwndDlg, IDC_LIST1);
hCombo=GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
installLangCount = EnumSelectedLanguages(hList, lpAddLanguages);
memmove(g_AddLanguages,lpAddLanguages,ARRAYSIZE(lpAddLanguages));
uninstallLangCount = EnumUnselectedLanguages(hList, lpRemoveLanguages);
//
// Let's read the user's UI language selection,
// and then call the kernel to update the registry.
//
hList = GetDlgItem(hwndDlg, IDC_LIST1);
hCombo = GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
iIndex = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
return FALSE;
}
langID = LANGIDFROMLCID((LCID) SendMessage(hCombo, CB_GETITEMDATA, iIndex, 0L));
//*STRSAFE* wsprintf(lpDefaultUILang, TEXT("%X"), langID);
hresult = StringCchPrintf(lpDefaultUILang , ARRAYSIZE(lpDefaultUILang), TEXT("%X"), langID);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
DEBUGMSGBOX(NULL, TEXT("About to do setup"), NULL, MB_OK);
success = DoSetup(
hwndDlg,
uninstallLangCount, lpRemoveLanguages,
installLangGroup,
installLangCount, lpAddLanguages,
g_bLipLanguages? lpAddLanguages:lpDefaultUILang,
TRUE, TRUE, TRUE);
return (success);
}
////////////////////////////////////////////////////////////////////////////////////
//
// ProgressDialogFunc
//
// Callback function for progresss dialog
//
////////////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK ProgressDialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwndDlg, 0);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
case WM_DESTROY:
EndDialog(hwndDlg, 0);
return TRUE;
default:
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// InitializeInstallDialog
//
// Sets contents of list view and combo box in installation dialog
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InitializeInstallDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hList, hCombo;
PTSTR lpLanguages;
TCHAR tchBuffer[BUFFER_SIZE];
TCHAR lpDefaultSystemLanguage[BUFFER_SIZE],lpUILanguage[BUFFER_SIZE];
TCHAR lpMessage[BUFFER_SIZE];
int iIndex;
int iChkIndex,iCnt,iMUIDirectories=0;
HRESULT hresult;
lpLanguages = tchBuffer;
SetWindowTitleFromResource(hwndDlg, IDS_MAIN_TITLE);
hList = GetDlgItem(hwndDlg, IDC_LIST1);
hCombo=GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
InitializeListView(hList);
//
// Insert the default system language in the list view
//
//*STRSAFE* _stprintf(lpDefaultSystemLanguage, TEXT("%04x"), gSystemUILangId);
hresult = StringCchPrintf(lpDefaultSystemLanguage , ARRAYSIZE(lpDefaultSystemLanguage), TEXT("%04x"), gSystemUILangId);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
iIndex=InsertLanguageInListView(hList, lpDefaultSystemLanguage, TRUE);
//
// Insert the languages in MUI.INF in the list view
//
if ( ( (iMUIDirectories =EnumLanguages(lpLanguages)) == 0) && (g_UILanguageGroup.iCount == 0 ) )
{
//
// No languages found in MUI.INF
//
LoadString(ghInstance, IDS_NO_LANG_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
return FALSE;
}
while (*lpLanguages != TEXT('\0'))
{
if (CheckLanguageIsQualified(lpLanguages))
{
InsertLanguageInListView(hList, lpLanguages, FALSE);
}
lpLanguages = _tcschr(lpLanguages, '\0');
lpLanguages++;
}
//
// We should also check all installed UI languages
//
for (iCnt=0; iCnt<g_UILanguageGroup.iCount; iCnt++)
{
if (!GetLcidItemIndexFromListView(hList, g_UILanguageGroup.lcid[iCnt], &iChkIndex))
{
//*STRSAFE* _stprintf(lpUILanguage, TEXT("%04x"), g_UILanguageGroup.lcid[iCnt]);
hresult = StringCchPrintf(lpUILanguage , ARRAYSIZE(lpUILanguage), TEXT("%04x"), g_UILanguageGroup.lcid[iCnt]);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
if (CheckLanguageIsQualified(lpUILanguage))
{
InsertLanguageInListView(hList, lpUILanguage, FALSE);
}
}
}
//
// Let's detect which language groups are installed
//
DetectLanguageGroups(hwndDlg);
SelectInstalledLanguages(hList);
SetDefault(hCombo);
//
// Deselect all items.
//
iIndex = ListView_GetItemCount(hList);
while (iIndex > 0)
{
iIndex--;
ListView_SetItemState( hList,
iIndex,
0,
LVIS_FOCUSED | LVIS_SELECTED );
}
//
// Select the first one in the list.
//
ListView_SetItemState( hList,
0,
LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED );
//
// Match system locale with the default UI language
//
if (CheckMUIRegSetting(MUI_MATCH_LOCALE))
{
CheckDlgButton(hwndDlg, IDC_CHECK_LOCALE, BST_CHECKED);
//
// Match UI font with the default UI language
//
if (g_bMatchUIFont = CheckMUIRegSetting(MUI_MATCH_UIFONT))
{
CheckDlgButton(hwndDlg, IDC_CHECK_UIFONT, BST_CHECKED);
}
}
else
{
SetMUIRegSetting(MUI_MATCH_UIFONT, FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), FALSE);
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// CheckForUsingCountryName
//
// Fetch MUIINF file if the selected UI lang needs to be displayed as a language
// name or a country name.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckForUsingCountryName(PMUILANGINFO pMuiLangInfo)
{
TCHAR szSource[MAX_PATH];
szSource[0] = TEXT('\0');
//
// Try check if there is a value for it under [UseCountryName]
//
GetPrivateProfileString( MUI_COUNTRYNAME_SECTION,
pMuiLangInfo->lpszLcid,
TEXT(""),
szSource,
MAX_PATH,
g_szMUIInfoFilePath);
if (szSource[0] == TEXT('1'))
{
return (TRUE);
}
return (FALSE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetDisplayName
//
// Fetch MUIINF file if the selected UI lang needs to be displayed using the
// name specified in [LanguageDisplayName] section of mui.inf.
// Otherwise, get the display name according to the values in [UseCountryName].
// If the value for the specified LCID is 1, use the country name. Otherwise,
// use the locale name.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetDisplayName(PMUILANGINFO pMuiLangInfo)
{
//
// Try check if there is a customized display name for the specified LCID under [LanguageDisplayName].
//
pMuiLangInfo->szDisplayName[0] = L'\0';
if (pMuiLangInfo->lpszLcid)
{
GetPrivateProfileString( MUI_DISPLAYNAME_SECTION,
pMuiLangInfo->lpszLcid,
TEXT(""),
pMuiLangInfo->szDisplayName,
MAX_PATH,
g_szMUIInfoFilePath);
}
if (pMuiLangInfo->szDisplayName[0] == L'\0')
{
//
// There is no entry in [LanguageDisplayName]. Use the country name or locale name.
//
Muisetup_GetLocaleLanguageInfo( pMuiLangInfo->lcid,
pMuiLangInfo->szDisplayName,
ARRAYSIZE(pMuiLangInfo->szDisplayName)-1,
CheckForUsingCountryName(pMuiLangInfo));
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetLanguageGroupDisplayName
// Get language group display name for MUI install/uninstall dialog
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetLanguageGroupDisplayName(LANGID LangId, LPTSTR lpBuffer, int nSize)
{
BOOL bRet = FALSE;
MUILANGINFO MuiLangInfo = {0};
HRESULT hresult;
if ( (!lpBuffer) || (nSize == 0))
{
return bRet;
}
MuiLangInfo.lcid = MAKELCID(LangId, SORT_DEFAULT);
MuiLangInfo.lgrpid = GetLanguageGroup(MuiLangInfo.lcid);
if (GetDisplayName(&MuiLangInfo) &&
nSize >= lstrlen(MuiLangInfo.szDisplayName))
{
//*STRSAFE* lstrcpy(lpBuffer, MuiLangInfo.szDisplayName);
hresult = StringCchCopy(lpBuffer , nSize, MuiLangInfo.szDisplayName);
if (!SUCCEEDED(hresult))
{
return bRet;
}
bRet = TRUE;
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////
//
// Get UI, IE and LPK files size for the lcid
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetUIFileSize(PMUILANGINFO pMuiLangInfo)
{
TCHAR szSize[MAX_PATH];
int nCD;
pMuiLangInfo->ulUISize = 0;
pMuiLangInfo->ulLPKSize = 0;
#if defined(_IA64_)
BOOL bIA64 = TRUE;
#else
BOOL bIA64 = FALSE;
#endif
if (!pMuiLangInfo)
{
return FALSE;
}
szSize[0] = TEXT('\0');
//
// Try to get UI files size under [FileSize_UI]
//
if (GetPrivateProfileString( bIA64? MUI_UIFILESIZE_SECTION_IA64 : MUI_UIFILESIZE_SECTION,
pMuiLangInfo->lpszLcid,
TEXT(""),
szSize,
MAX_PATH,
g_szMUIInfoFilePath))
{
pMuiLangInfo->ulUISize =_wtoi64(szSize);
}
szSize[0] = TEXT('\0');
//
// Try to get LPK files size under [FileSize_LPK]
//
if (GetPrivateProfileString( bIA64? MUI_LPKFILESIZE_SECTION_IA64 : MUI_LPKFILESIZE_SECTION,
pMuiLangInfo->lpszLcid,
TEXT(""),
szSize,
MAX_PATH,
g_szMUIInfoFilePath))
{
pMuiLangInfo->ulLPKSize =_wtoi64(szSize);
}
//
// Try to get CD # under [CD_LAYOUT]
//
nCD=GetPrivateProfileInt(bIA64? MUI_CDLAYOUT_SECTION_IA64 : MUI_CDLAYOUT_SECTION,
pMuiLangInfo->lpszLcid,
0,
g_szMUIInfoFilePath);
if (nCD)
{
pMuiLangInfo->cd_number = nCD;
if (g_cdnumber == 0)
{
g_cdnumber = pMuiLangInfo->cd_number;
}
}
else
{
pMuiLangInfo->cd_number = DEFAULT_CD_NUMBER;
}
return TRUE;
}
BOOL GetUIFileSize_commandline(LPTSTR lpszLcid, INT64 *ulUISize,INT64 *ulLPKSize)
{
TCHAR szSize[MAX_PATH];
*ulUISize = 0;
*ulLPKSize = 0;
#if defined(_IA64_)
BOOL bIA64 = TRUE;
#else
BOOL bIA64 = FALSE;
#endif
if ( (!lpszLcid) || (!ulUISize) || (!ulLPKSize))
{
return FALSE;
}
szSize[0] = TEXT('\0');
//
// Try to get UI files size under [FileSize_UI]
//
if (GetPrivateProfileString( bIA64? MUI_UIFILESIZE_SECTION_IA64 : MUI_UIFILESIZE_SECTION,
lpszLcid,
TEXT(""),
szSize,
MAX_PATH,
g_szMUIInfoFilePath))
{
*ulUISize =_wtoi64(szSize);
}
szSize[0] = TEXT('\0');
//
// Try to get LPK files size under [FileSize_LPK]
//
if (GetPrivateProfileString( bIA64? MUI_LPKFILESIZE_SECTION_IA64 : MUI_LPKFILESIZE_SECTION,
lpszLcid,
TEXT(""),
szSize,
MAX_PATH,
g_szMUIInfoFilePath))
{
*ulLPKSize =_wtoi64(szSize);
}
// Try to get CD # under [CD_LAYOUT]
//
if (g_cdnumber == 0)
{
g_cdnumber=GetPrivateProfileInt( bIA64? MUI_CDLAYOUT_SECTION_IA64 : MUI_CDLAYOUT_SECTION,
lpszLcid,
0,
g_szMUIInfoFilePath);
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// InitializeListView
//
// Gets the list view ready for inserting items
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InitializeListView(HWND hList)
{
DWORD dwExStyle;
LV_COLUMN Column;
RECT Rect;
GetClientRect(hList, &Rect);
Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
Column.fmt = LVCFMT_LEFT;
Column.cx = Rect.right - GetSystemMetrics(SM_CYHSCROLL);
Column.pszText = NULL;
Column.cchTextMax = 0;
Column.iSubItem = 0;
ListView_InsertColumn(hList, 0, &Column);
dwExStyle = ListView_GetExtendedListViewStyle(hList);
ListView_SetExtendedListViewStyle(hList, dwExStyle | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
//
// Check if specified language can install on the target machine.
// I.E. Arabic, Turkish, Greek and Hebrew MUI can only install on NT Workstation;
// They are not allowed on NT Server
//
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckLanguageIsQualified(LPTSTR lpLanguage)
{
#ifdef XCHECK_LANGUAGE_FOR_PLATFORM
BOOL bResult = FALSE;
LANGID LgLang;
if (!lpLanguage)
{
return bResult;
}
LgLang = (LANGID)_tcstol(lpLanguage, NULL, 16);
LgLang = PRIMARYLANGID(LgLang);
if(gbIsAdvanceServer)
{
if (LgLang == LANG_GERMAN || LgLang == LANG_FRENCH || LgLang == LANG_SPANISH ||
LgLang == LANG_JAPANESE || LgLang == LANG_KOREAN || LgLang == LANG_CHINESE)
{
bResult = TRUE;
}
}
else if(gbIsServer)
{
if (LgLang == LANG_GERMAN || LgLang == LANG_FRENCH || LgLang == LANG_SPANISH ||
LgLang == LANG_JAPANESE || LgLang == LANG_KOREAN || LgLang == LANG_CHINESE ||
LgLang == LANG_SWEDISH || LgLang == LANG_ITALIAN || LgLang == LANG_DUTCH ||
LgLang == LANG_PORTUGUESE || LgLang == LANG_CZECH || LgLang == LANG_HUNGARIAN ||
LgLang == LANG_POLISH || LgLang == LANG_RUSSIAN || LgLang == LANG_TURKISH)
{
bResult = TRUE;
}
}
else if(gbIsWorkStation)
{
bResult = TRUE;
}
return bResult;
#else
return TRUE;
#endif
}
////////////////////////////////////////////////////////////////////////////////////
//
// InsertLanguageInListView
//
// Returns the index of the item in the list view after inserting it.
//
////////////////////////////////////////////////////////////////////////////////////
int InsertLanguageInListView(HWND hList, LPTSTR lpLanguage, BOOL bCheckState)
{
LANGID LgLang;
LV_ITEM lvItem;
PMUILANGINFO pMuiLangInfo;
int iIndex;
HRESULT hresult;
if (!lpLanguage)
{
return -1;
}
lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = LVIS_STATEIMAGEMASK;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
//
// Allocate enough space to hold pszLcid and MUILANGINFO
//
pMuiLangInfo = (PMUILANGINFO) LocalAlloc(LPTR, sizeof(MUILANGINFO));
if (pMuiLangInfo == NULL)
{
ExitFromOutOfMemory();
}
else
{
pMuiLangInfo->lpszLcid = (LPTSTR) LocalAlloc(LMEM_FIXED, (_tcslen(lpLanguage) + 1) * sizeof(TCHAR));
}
if (pMuiLangInfo->lpszLcid == NULL)
{
ExitFromOutOfMemory();
}
else
{
//
// Init pszLcid
//
lvItem.lParam = (LPARAM)pMuiLangInfo;
//*STRSAFE* _tcscpy((LPTSTR)pMuiLangInfo->lpszLcid, lpLanguage);
hresult = StringCchCopy((LPTSTR)pMuiLangInfo->lpszLcid ,_tcslen(lpLanguage) + 1 , lpLanguage);
if (!SUCCEEDED(hresult))
{
return -1;
}
}
//
// Init lcid
//
LgLang = (LANGID)_tcstol(lpLanguage, NULL, 16);
pMuiLangInfo->lcid = MAKELCID(LgLang, SORT_DEFAULT);
if (pMuiLangInfo->szDisplayName[0] == L'\0')
{
GetDisplayName(pMuiLangInfo);
}
lvItem.pszText = pMuiLangInfo->szDisplayName;
GetUIFileSize(pMuiLangInfo);
iIndex = ListView_InsertItem(hList, &lvItem);
if (iIndex >= 0)
{
ListView_SetCheckState(hList, iIndex, bCheckState);
}
return iIndex;
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetMuiLangInfoFromListView
//
// Get the MuiLangInfo of the corresponding ListView Item
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetMuiLangInfoFromListView(HWND hList, int i, PMUILANGINFO *ppMuiLangInfo)
{
LVITEM lvItem;
if (!ppMuiLangInfo)
{
return FALSE;
}
//
// Check if Language Group is installed
//
lvItem.mask = LVIF_PARAM;
lvItem.iItem = i;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = 0;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
lvItem.lParam = 0;
ListView_GetItem(hList, &lvItem);
*ppMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// Muisetup_GetLocaleLanguageInfo
//
// Read the locale info of the language or country name.
//
////////////////////////////////////////////////////////////////////////////////////
int Muisetup_GetLocaleLanguageInfo(LCID lcid, PTSTR pBuf, int iLen, BOOL fUseCountryName)
{
TCHAR tchBuf[ MAX_PATH ] ;
int iRet;
HRESULT hresult;
if ( (!pBuf) || (iLen == 0))
{
return 0;
}
//
// If this is either 0x0404 or 0x0804, then mark them specially
//
if (0x0404 == lcid)
{
iRet = LoadString(ghInstance, IDS_MUI_CHT, pBuf, iLen);
}
else if (0x0804 == lcid)
{
iRet = LoadString(ghInstance, IDS_MUI_CHS, pBuf, iLen);
}
else
{
iRet = GetLocaleInfo( lcid,
LOCALE_SENGLANGUAGE,
pBuf,
iLen);
if (fUseCountryName)
{
iRet = GetLocaleInfo( lcid,
LOCALE_SENGCOUNTRY,
tchBuf,
(sizeof(tchBuf)/sizeof(TCHAR)));
if (iRet)
{
//*STRSAFE* _tcscat(pBuf, TEXT(" ("));
hresult = StringCchCat(pBuf , iLen, TEXT(" ("));
if (!SUCCEEDED(hresult))
{
return 0;
}
//*STRSAFE* _tcscat(pBuf, tchBuf);
hresult = StringCchCat(pBuf , iLen, tchBuf);
if (!SUCCEEDED(hresult))
{
return 0;
}
//*STRSAFE* _tcscat(pBuf, TEXT(")"));
hresult = StringCchCat(pBuf , iLen, TEXT(")"));
if (!SUCCEEDED(hresult))
{
return 0;
}
}
}
}
return iRet;
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetLcidFromComboBox
//
// Retreives the index of the combo box item that corresponds to this UI Language
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetLcidFromComboBox(HWND hCombo, LCID lcid, int *piIndex)
{
LCID ItemLcid;
int i;
int iCount = (int)SendMessage(hCombo, CB_GETCOUNT, 0L, 0L);
if (!piIndex)
{
return FALSE;
}
if (CB_ERR != iCount)
{
i = 0;
while (i < iCount)
{
ItemLcid = (LCID)SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)i, (LPARAM)0);
if ((CB_ERR != ItemLcid) && (ItemLcid == lcid))
{
*piIndex = i;
return TRUE;
}
i++;
}
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetMuiLangInfoFromListView
//
// Retreives the index of the listview item that corresponds to this UI Language
//
////////////////////////////////////////////////////////////////////////////////////
BOOL GetLcidItemIndexFromListView(HWND hList, LCID lcid, int *piIndex)
{
int iCount = ListView_GetItemCount(hList);
int i;
PMUILANGINFO pMuiLangInfo;
LVITEM lvItem;
if (!piIndex)
{
return FALSE;
}
i = 0;
while (i < iCount)
{
//
// Check if Language Group is installed
//
lvItem.mask = LVIF_PARAM;
lvItem.iItem = i;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = 0;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
lvItem.lParam = 0;
ListView_GetItem(hList, &lvItem);
pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
if (pMuiLangInfo->lcid == lcid)
{
*piIndex = i;
return TRUE;
}
i++;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// SelectInstalledLanguages
//
// Sets the list view check state for insalled languages
//
// TODO: We should perhaps use the MSI to check for installed packages instead...
////////////////////////////////////////////////////////////////////////////////////
BOOL SelectInstalledLanguages(HWND hList)
{
DWORD dwData;
DWORD dwIndex;
DWORD dwValue;
HKEY hKey;
LANGID LgLang;
LONG rc;
TCHAR lpItemString[BUFFER_SIZE];
TCHAR szData[BUFFER_SIZE];
TCHAR szValue[BUFFER_SIZE];
int iIndex;
int nLvIndex;
if (hKey = OpenMuiKey(KEY_READ))
{
dwIndex = 0;
rc = ERROR_SUCCESS;
iIndex = ListView_GetItemCount(hList);
while(rc==ERROR_SUCCESS)
{
dwValue=sizeof(szValue)/sizeof(TCHAR);
szValue[0]=TEXT('\0');
dwData = sizeof(szData);
szData[0] = TEXT('\0');
DWORD dwType;
rc = RegEnumValue(hKey, dwIndex, szValue, &dwValue, 0, &dwType, (LPBYTE)szData, &dwData);
if (rc == ERROR_SUCCESS)
{
if (dwType != REG_SZ)
{
dwIndex++;
continue;
}
LgLang=(WORD)_tcstol(szValue, NULL, 16);
if (GetLcidItemIndexFromListView(hList, MAKELCID(LgLang, SORT_DEFAULT), &nLvIndex))
{
ListView_SetCheckState(hList, nLvIndex, TRUE);
}
}
dwIndex++;
}
RegCloseKey(hKey);
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// UpdateCombo
//
// Updates the combo box to correspond to the languages selected in the list view
//
////////////////////////////////////////////////////////////////////////////////////
BOOL UpdateCombo(HWND hwndDlg)
{
BOOL bDefaultSet=FALSE;
HWND hCombo;
HWND hList;
TCHAR lpBuffer[BUFFER_SIZE];
TCHAR lpSystemDefault[BUFFER_SIZE];
int i;
int iIndex;
int iLbIndex;
int iListIndex;
WPARAM iPrevDefault;
LCID lcidPrev;
PMUILANGINFO pMuiLangInfo;
hList = GetDlgItem(hwndDlg, IDC_LIST1);
hCombo = GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
//
// If the Previous Default is still selected, keep it as the default
//
iPrevDefault = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
if (iPrevDefault == CB_ERR)
return FALSE;
lcidPrev = (LCID) SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)iPrevDefault, 0);
//
// Get the text of the currently selected default
//
GetLcidItemIndexFromListView(hList, lcidPrev, &iLbIndex);
SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
iIndex = ListView_GetItemCount(hList);
iListIndex = 0;
//
// See if we can preserve the default.
//
i = 0;
while (i < iIndex)
{
if (ListView_GetCheckState(hList, i))
{
ListView_GetItemText(hList, i, 0, lpBuffer, ARRAYSIZE(lpBuffer)-1);
iListIndex = (int) SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)lpBuffer);
if (CB_ERR != iListIndex)
{
GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
SendMessage(hCombo, CB_SETITEMDATA, iListIndex, (LPARAM)(LCID)pMuiLangInfo->lcid);
if (pMuiLangInfo->lcid == lcidPrev)
{
SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iListIndex, 0);
bDefaultSet = TRUE;
}
}
}
i++;
}
//
// If no default, force the system default.
//
if (!bDefaultSet)
{
lcidPrev = MAKELCID(gSystemUILangId, SORT_DEFAULT);
if (!GetLcidFromComboBox(hCombo, lcidPrev, &iIndex))
{
GetLocaleInfo(lcidPrev,
LOCALE_SENGLANGUAGE,
lpSystemDefault,
ARRAYSIZE(lpSystemDefault)-1);
iIndex = (int) SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)lpSystemDefault);
SendMessage(hCombo, CB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)(LCID)lcidPrev);
}
SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iIndex, 0);
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// SetDefault
//
// Sets the default user setting in the combo box
//
////////////////////////////////////////////////////////////////////////////////////
BOOL SetDefault(HWND hCombo)
{
int iIndex;
TCHAR lpBuffer[BUFFER_SIZE];
LCID lcid = MAKELCID(GetDotDefaultUILanguage(), SORT_DEFAULT);
GetLocaleInfo(lcid,
LOCALE_SENGLANGUAGE,
lpBuffer,
ARRAYSIZE(lpBuffer)-1);
iIndex = (int)SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)lpBuffer);
if (CB_ERR != iIndex)
{
SendMessage(hCombo, CB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)(DWORD) lcid);
SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iIndex, 0);
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// SetUserDefaultLanguage
//
// Sets the default language in the registry
//
////////////////////////////////////////////////////////////////////////////////////
BOOL SetUserDefaultLanguage(LANGID langID, BOOL bApplyCurrentUser, BOOL bApplyAllUsers)
{
TCHAR szCommands[BUFFER_SIZE];
TCHAR szBuf[BUFFER_SIZE];
BOOL success;
LONG_PTR lppArgs[2];
HRESULT hresult;
//
// Set the UI language now
//
// status = gpfnNtSetDefaultUILanguage(LANGIDFROMLCID(langID));
szCommands[0] = TEXT('\0');
if (bApplyCurrentUser)
{
// E.g. MUILanguage = "0411".
//*STRSAFE* wsprintf(szCommands, TEXT("MUILanguage=\"%x\"\n"), langID);
hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("MUILanguage=\"%x\"\n"), langID);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
}
if (bApplyAllUsers)
{
//*STRSAFE* wsprintf(szBuf, TEXT("MUILanguage_DefaultUser = \"%x\""), langID);
hresult = StringCchPrintf(szBuf , ARRAYSIZE(szBuf), TEXT("MUILanguage_DefaultUser = \"%x\""), langID);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* _tcscat(szCommands, szBuf);
hresult = StringCchCat(szCommands , ARRAYSIZE(szCommands), szBuf);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
}
success = RunRegionalOptionsApplet(szCommands);
lppArgs[0] = langID;
if (success)
{
if (bApplyCurrentUser)
{
LogFormattedMessage(NULL, IDS_SET_UILANG_CURRENT, lppArgs);
}
if (bApplyAllUsers)
{
LogFormattedMessage(NULL, IDS_SET_UILANG_ALLUSERS, lppArgs);
}
} else
{
if (bApplyCurrentUser)
{
LogFormattedMessage(NULL, IDS_ERROR_SET_UILANG_CURRENT, lppArgs);
}
if (bApplyAllUsers)
{
LogFormattedMessage(NULL, IDS_ERROR_SET_UILANG_ALLUSERS, lppArgs);
}
}
return (success);
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetDotDefaultUILanguage
//
// Retrieve the UI language stored in the HKCU\.Default.
// This is the default UI language for new users.
//
////////////////////////////////////////////////////////////////////////////////////
LANGID GetDotDefaultUILanguage()
{
HKEY hKey;
DWORD dwKeyType;
DWORD dwSize;
BOOL success = FALSE;
TCHAR szBuffer[BUFFER_SIZE];
LANGID langID;
//
// Get the value in .DEFAULT.
//
if (RegOpenKeyEx( HKEY_USERS,
TEXT(".DEFAULT\\Control Panel\\Desktop"),
0L,
KEY_READ,
&hKey ) == ERROR_SUCCESS)
{
dwSize = sizeof(szBuffer);
if (RegQueryValueEx( hKey,
TEXT("MultiUILanguageId"),
0L,
&dwKeyType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS)
{
if (dwKeyType == REG_SZ)
{
langID = (LANGID)_tcstol(szBuffer, NULL, 16);
success = TRUE;
}
}
RegCloseKey(hKey);
}
// here, check to see if the key is actually meaningful, if not, return SystemDefaultUILanguage
if (success && (!IsInstalled(szBuffer)))
{
success = FALSE;
}
if (!success)
{
langID = GetSystemDefaultUILanguage();
}
return (langID);
}
////////////////////////////////////////////////////////////////////////////////////
//
// CheckLangGroupCommandLine
//
// Command line version of CheckSupport
//
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckLangGroupCommandLine(PINSTALL_LANG_GROUP pInstallLangGroup, LPTSTR lpArg)
{
int i = 0;
int iArg;
LGRPID lgrpid;
if ( (!pInstallLangGroup) || (!lpArg))
{
return FALSE;
}
iArg = _tcstol(lpArg, NULL, 16);
//
// See if the lang group for this MUI lang is installed or not
//
lgrpid = GetLanguageGroup(MAKELCID(iArg, SORT_DEFAULT));
if (AddMUILangGroup(pInstallLangGroup, lgrpid))
{
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// SetWindowTitleFromResource
//
// Set the window title using the specified resource string ID.
//
////////////////////////////////////////////////////////////////////////////////////
void SetWindowTitleFromResource(HWND hwnd, int resourceID)
{
TCHAR szBuffer[BUFFER_SIZE];
LoadString(NULL, resourceID, szBuffer, sizeof(szBuffer)/sizeof(TCHAR));
SetWindowText(hwnd, szBuffer);
}
BOOL RemoveFileReadOnlyAttribute(LPTSTR lpszFileName)
{
BOOL bResult = FALSE;
DWORD dwAttrib;
if (! lpszFileName)
{
return bResult;
}
dwAttrib = GetFileAttributes (lpszFileName);
if ( dwAttrib & FILE_ATTRIBUTE_READONLY )
{
dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
SetFileAttributes (lpszFileName, dwAttrib);
bResult=TRUE;
}
return bResult;
}
BOOL MUI_DeleteFile(LPTSTR lpszFileName)
{
if (!lpszFileName)
{
return FALSE;
}
RemoveFileReadOnlyAttribute(lpszFileName);
return DeleteFile(lpszFileName);
}
BOOL DeleteSideBySideMUIAssemblyIfExisted(LPTSTR Languages, TCHAR pszLogFile[BUFFER_SIZE])
{
HRESULT hresult;
if (!Languages)
{
return FALSE;
}
//*STRSAFE* lstrcpy(pszLogFile, g_szWinDir); // c:\windows
hresult = StringCchCopy(pszLogFile , BUFFER_SIZE, g_szWinDir);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(pszLogFile, MUISETUP_PATH_SEPARATOR); // c:\windows
hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_PATH_SEPARATOR);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(pszLogFile, MUIDIR); // c:\windows\mui
hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUIDIR);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(pszLogFile, MUISETUP_PATH_SEPARATOR); // c:\windows\mui
hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_PATH_SEPARATOR);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(pszLogFile, MUISETUP_ASSEMBLY_INSTALLATION_LOG_FILENAME); // c:\windows\mui\muisetup.log.
hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_ASSEMBLY_INSTALLATION_LOG_FILENAME);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(pszLogFile, Languages); // c:\windows\mui\muisetup.log.1234
hresult = StringCchCat(pszLogFile , BUFFER_SIZE, Languages);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
if (GetFileAttributes(pszLogFile) != 0xFFFFFFFF) // existed
{
// open it and delete assemblies in the list
SXS_UNINSTALLW UninstallData = {sizeof(UninstallData)};
UninstallData.dwFlags = SXS_UNINSTALL_FLAG_USE_INSTALL_LOG;
UninstallData.lpInstallLogFile = pszLogFile;
return gpfnSxsUninstallW(&UninstallData,NULL);
}else
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// InstallSelected
//
// Install the languages specified
//
// Return:
// TURE if the operation succeeds. Otherwise FALSE.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InstallSelected(LPTSTR Languages, BOOL *lpbFontLinkRegistryTouched)
{
TCHAR lpMessage[BUFFER_SIZE];
if (!Languages)
{
return FALSE;
}
//
// Next step is to create a list of install directories from layout
// the directories are listed in the [Directories] section of MUI.INF
//
if (!EnumDirectories())
{
//
// "LOG: Error reading directory list."
//
LoadString(ghInstance, IDS_DIRECTORY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
return (FALSE);
}
EnumFileRename();
EnumTypeNotFallback();
//
// Copy the common files
//
if (Languages)
{
//
// Copy MUI files for the selected languages.
//
#ifdef MUI_MAGIC
if (!g_bNoUI)
{
SetWindowTitleFromResource(ghProgDialog, IDS_INSTALL_TITLE);
}
#endif
if (!CopyFiles(ghProgDialog, Languages))
{
//
// "LOG: Error copying files."
//
// stop install if copy fails
//
LoadString(ghInstance, IDS_COPY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
#ifndef IGNORE_COPY_ERRORS
gNumLanguages_Install = 0;
return (FALSE);
#endif
}
#ifndef MUI_MAGIC
CopyRemoveMuiItself(TRUE);
#endif
}
#ifndef MUI_MAGIC
//
// register MUI as installed in registry
//
if (!UpdateRegistry(Languages,lpbFontLinkRegistryTouched))
{
//
// LOG: Error updating registry
//
LoadString(ghInstance, IDS_REGISTRY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
return (FALSE);
}
if (!InstallExternalComponents(Languages))
{
return (FALSE);
}
#endif
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// UninstallSelected
//
// Uninstall the languages specified
//
// Return:
// TRUE if the operation succeeds. Otherwise FALSE.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL UninstallSelected(LPTSTR Languages,int *lpNotDeleted)
{
TCHAR lpMessage[BUFFER_SIZE];
BOOL bResult = TRUE;
HRESULT hresult;
if (!Languages)
{
return FALSE;
}
//
// Next step is to create a list of install directories
// the directories are listed in the [Directories] section
//
//
// this enumerates the directories and fills the array DirNames
//
if (!EnumDirectories())
{
//
// "LOG: Error reading directory list."
//
LoadString(ghInstance, IDS_DIRECTORY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
return (FALSE);
}
#ifndef MUI_MAGIC
UninstallExternalComponents(Languages);
if (!g_bNoUI)
{
SetWindowTitleFromResource(ghProgDialog, IDS_UNINSTALL_TITLE);
}
#endif
//
// Copy the common files
//
if (!DeleteFiles(Languages,lpNotDeleted))
{
//
// "LOG: Error deleting files"
//
LoadString(ghInstance, IDS_DELETE_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
bResult = FALSE; // even though something failed, we will continue to try to uninstall the product here so upgrade uninstallation will continue clean up
}
//
// register MUI as installed in registry, the function logs messages already, so we don't need to log another one here.
//
UninstallUpdateRegistry(Languages);
//
// Delete sxs Assembly
//
if (gpfnSxsUninstallW)
{
TCHAR pszLogFile[BUFFER_SIZE];
if ( ! DeleteSideBySideMUIAssemblyIfExisted(Languages, pszLogFile))
{
TCHAR errInfo[BUFFER_SIZE];
//*STRSAFE* swprintf(errInfo, TEXT("Assembly UnInstallation of %s failed"), pszLogFile);
hresult = StringCchPrintf(errInfo , ARRAYSIZE(errInfo), TEXT("Assembly UnInstallation of %s failed"), pszLogFile);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
OutputDebugString(errInfo);
}
}
return (bResult);
}
////////////////////////////////////////////////////////////////////////////////////
//
// UninstallUpdateRegistry
//
// Update the Registry to account for languages that have been uninstalled
//
////////////////////////////////////////////////////////////////////////////////////
BOOL UninstallUpdateRegistry(LPTSTR Languages)
{
LPTSTR Language;
HKEY hKeyMUI = 0;
HKEY hKeyFileVersions = 0;
DWORD dwDisp;
BOOL bRet = TRUE;
TCHAR tcMessage[BUFFER_SIZE];
if (!Languages)
{
return FALSE;
}
if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
REG_MUI_PATH,
0,
TEXT("REG_SZ"),
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS,
NULL,
&hKeyMUI,
&dwDisp) != ERROR_SUCCESS)
{
bRet = FALSE;
goto Exit;
}
if (RegCreateKeyEx( HKEY_CURRENT_USER,
REG_FILEVERSION_PATH,
0,
TEXT("REG_SZ"),
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS,
NULL,
&hKeyFileVersions,
&dwDisp) != ERROR_SUCCESS)
{
bRet = FALSE;
goto Exit;
}
Language = Languages;
while (*Language)
{
//
// Don't remove system UI language for registry
//
if (HexStrToInt(Language) != gSystemUILangId)
{
//
// Delete UI Language key, subkeys and values.
//
if (RegDeleteValue(hKeyMUI, Language) != ERROR_SUCCESS)
{
bRet = FALSE;
}
if (DeleteRegTree(hKeyFileVersions, Language) != ERROR_SUCCESS)
{
bRet = FALSE;
}
}
//
// Attempt to delete the Windows installer regkey entry if we are in OS upgrade setup
//
if (TRUE == g_bRunFromOSSetup)
{
DeleteMSIRegSettings(Language);
}
while (*Language++) // go to the next language and repeat
{
}
} // of while (*Language)
//
// Delete Match UI Font and Match locale Key
//
DeleteMUIRegSetting();
Exit:
//
// Clean up
//
if (hKeyMUI)
RegCloseKey(hKeyMUI);
if (hKeyFileVersions)
RegCloseKey(hKeyFileVersions);
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////
//
// EnumSelectedLanguages
//
// Enumerate the languages marked for installation
//
// Return:
// The total number of MUI languages to be added.
//
////////////////////////////////////////////////////////////////////////////////////
int EnumSelectedLanguages(HWND hList, LPTSTR lpAddLanguages)
{
TCHAR szBuffer[BUFFER_SIZE];
TCHAR *p;
LPTSTR lpszLcid;
int iIndex;
int i = 0;
PMUILANGINFO pMuiLangInfo;
int installLangCount = 0;
iIndex = ListView_GetItemCount(hList);
HRESULT hresult;
if (!lpAddLanguages)
{
return 0;
}
*lpAddLanguages=TEXT('\0');
while(i<iIndex)
{
if(ListView_GetCheckState(hList, i))
{
GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
lpszLcid = pMuiLangInfo->lpszLcid;
if (!IsInstalled(lpszLcid) && HaveFiles(lpszLcid))
{
//*STRSAFE* _tcscat(lpAddLanguages, lpszLcid);
hresult = StringCchCat(lpAddLanguages , BUFFER_SIZE, lpszLcid);
if (!SUCCEEDED(hresult))
{
return 0;
}
//*STRSAFE* _tcscat(lpAddLanguages, TEXT("*"));
hresult = StringCchCat(lpAddLanguages , BUFFER_SIZE, TEXT("*"));
if (!SUCCEEDED(hresult))
{
return 0;
}
//
// Count how many languages are being installed/uninstalled for the progress bar
//
gNumLanguages++;
gNumLanguages_Install++;
installLangCount++;
}
}
i++;
}
p = lpAddLanguages;
while (p=_tcschr(p, TEXT('*')))
{
*p=TEXT('\0');
p++;
}
return (installLangCount);
}
////////////////////////////////////////////////////////////////////////////////////
//
// EnumUnselectedLanguages
//
// Enumerate the languages marked for removal
//
// Return:
// The total number of MUI languages to be added.
//
////////////////////////////////////////////////////////////////////////////////////
int EnumUnselectedLanguages(HWND hList, LPTSTR lpRemoveLanguages)
{
LPTSTR p;
TCHAR szBuffer[BUFFER_SIZE];
LPTSTR lpszLcid;
int iIndex;
int i = 0;
PMUILANGINFO pMuiLangInfo;
int uninstallLangCount = 0;
HRESULT hresult;
iIndex = ListView_GetItemCount(hList);
if (!lpRemoveLanguages)
{
return 0;
}
*lpRemoveLanguages=TEXT('\0');
g_bRemoveDefaultUI=FALSE;
while (i < iIndex)
{
if (!ListView_GetCheckState(hList, i))
{
GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
lpszLcid = pMuiLangInfo->lpszLcid;
if (IsInstalled(lpszLcid))
{
//*STRSAFE* _tcscat(lpRemoveLanguages, lpszLcid);
hresult = StringCchCat(lpRemoveLanguages , BUFFER_SIZE, lpszLcid);
if (!SUCCEEDED(hresult))
{
return 0;
}
//*STRSAFE* _tcscat(lpRemoveLanguages, TEXT("*"));
hresult = StringCchCat(lpRemoveLanguages , BUFFER_SIZE, TEXT("*"));
if (!SUCCEEDED(hresult))
{
return 0;
}
if (GetDotDefaultUILanguage() == pMuiLangInfo->lcid)
{
g_bRemoveDefaultUI=TRUE;
}
if (GetUserDefaultUILanguage() == pMuiLangInfo->lcid)
{
g_bRemoveUserUI = TRUE;
}
//
// Count how many languages are being installed/uninstalled for the progress bar
//
gNumLanguages++;
gNumLanguages_Uninstall++;
uninstallLangCount++;
}
}
i++;
}
p = lpRemoveLanguages;
while (p=_tcschr(p, TEXT('*')))
{
*p = TEXT('\0');
p++;
}
return (uninstallLangCount);
}
////////////////////////////////////////////////////////////////////////////////////
//
// SkipBlanks
//
// Skips spaces and tabs in string. Returns pointer to next character
//
////////////////////////////////////////////////////////////////////////////////////
PTCHAR SkipBlanks(PTCHAR pszText)
{
if (!pszText)
{
return NULL;
}
while (*pszText==TEXT(' ') || *pszText==TEXT('\t'))
{
pszText++;
}
return pszText;
}
////////////////////////////////////////////////////////////////////////////////////
//
// NextCommandTag
//
// pointing to next command tag (TEXT('-') or TEXT('/')
//
////////////////////////////////////////////////////////////////////////////////////
LPTSTR NextCommandTag(LPTSTR lpcmd)
{
LPTSTR p=NULL;
if(!lpcmd)
{
return (p);
}
while(*lpcmd)
{
if ((*lpcmd == TEXT('-')) || (*lpcmd == TEXT('/')))
{
// Skip to the character after the '-','/'.
p = lpcmd + 1;
break;
}
lpcmd++;
}
return (p);
}
////////////////////////////////////////////////////////////////////////////////////
//
// IsInInstallList
//
// Check if a target is in the string list
//
// Structure of string list:
//
// <string 1><NULL><string 2><NULL>......<string n><NULL><NULL>
//
////////////////////////////////////////////////////////////////////////////////////
BOOL IsInInstallList(LPTSTR lpList,LPTSTR lpTarget)
{
BOOL bResult=FALSE;
if (!lpList || !lpTarget)
return bResult;
while (*lpList)
{
if (!_tcsicmp(lpList,lpTarget))
{
bResult=TRUE;
break;
}
while (*lpList++) // move to next
{
}
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////
//
// CreateProgressDialog
//
// Globals affected:
// ghProgDialog
// ghProgress
//
////////////////////////////////////////////////////////////////////////////////////
void CreateProgressDialog(HWND hwnd)
{
ghProgDialog = CreateDialog(ghInstance,
MAKEINTRESOURCE(IDD_DIALOG_INSTALL_PROGRESS),
hwnd,
ProgressDialogFunc);
ghProgress = GetDlgItem(ghProgDialog, IDC_PROGRESS1);
}
////////////////////////////////////////////////////////////////////////////////////
//
// CheckLanguageGroupInstalled
// Check if the Language groups for specified languages is installed correctly.
//
// Parameters:
// [IN] lpLanguages The double-null-terminated string which contains the hex LCID
// strings to be checked.
// Return:
// TURE if all the required language packs are installed in the system. Otherwise, FALSE is
// returned.
//
// CheckLanguageGroupInstalled
// Check if the Language groups for specified languages is installed correctly.
//
// Parameters:
// [IN] lpLanguages The double-null-terminated string which contains the hex LCID
// strings to be checked.
// Return:
// TURE if all the required language packs are installed in the system. Otherwise, FALSE is
// returned.
//
// Remarks:
// 01-18-2001 YSLin Created.
////////////////////////////////////////////////////////////////////////////////////
BOOL CheckLanguageGroupInstalled(LPTSTR lpLanguages)
{
LANGID langID;
LGRPID lgrpID;
if (!lpLanguages)
{
return FALSE;
}
while (*lpLanguages != TEXT('\0'))
{
langID = (LANGID)TransNum(lpLanguages);
lgrpID = GetLanguageGroup(langID);
if (!gpfnIsValidLanguageGroup(lgrpID, LGRPID_INSTALLED))
{
return (FALSE);
}
// Go to the null character.
lpLanguages = _tcschr(lpLanguages, TEXT('\0'));
// Skip to next char after the null character.
lpLanguages++;
}
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// DoSetup
//
// Parameters:
// hwnd The hwnd of the MUISetup main dialog. Pass null if the muisetup is run from command line.
// UnistallLangCount The number of languages to be uninstalled.
// lpUninstall The double-null-terminated string which contains the hex LCID strings for the
// languages to be uninstalled.
// installLangGroup
// InstallLangCount The number of languages to be installed.
// lpInstall The double-null-terminated string which contains the hex LCID strings for the
// languages to be installed.
// lpDefaultUILang The language to be set as system default UI language. Pass NULL if the system default
// UI language is not changed.
// fAllowReboot The flag to indicate if this function should check if reboot is necessary.
// bInteractive TRUE if run in interactive mode, or FALSE if run in silent mode.
// bDisplayUI TRUE if UI is desired, FALSE if UI is to be suppressed
//
//
// Return:
// TRUE if installation is successful. Otherwise FALSE.
//
// Notes:
// This functions serves as the entry point of the real installation process, shared by both the GUI setup
// and the command line mode setup.
//
// There are several steps in doing MUI setup.
// 1. Uninstall the selected MUI languages.
// 2. Install the necessary language packs according to the selected MUI languges(if any).
// 3. Install the selected MUI languages.
// 4. Change the default UI language.
// 5. Check for rebooting.
//
// Please note that to save space, we do the uninstallation first, then do the installation.
////////////////////////////////////////////////////////////////////////////////////
BOOL DoSetup(
HWND hwnd,
int UninstallLangCount, LPTSTR lpUninstall,
INSTALL_LANG_GROUP installLangGroup,
int InstallLangCount, LPTSTR lpInstall,
LPTSTR lpDefaultUILang,
BOOL fAllowReboot, BOOL bInteractive, BOOL bDisplayUI)
{
LONG_PTR lppArgs[3];
TCHAR lpMessage[BUFFER_SIZE];
TCHAR lpForceUILang[BUFFER_SIZE];
TCHAR lpTemp[BUFFER_SIZE];
TCHAR lpTemp2[BUFFER_SIZE];
LANGID defaultLangID;
HCURSOR hCurSave;
int NotDeleted;
BOOL bDefaultUIChanged = FALSE;
BOOL bErrorOccurred = FALSE;
LANGID lidSys = GetSystemDefaultLangID();
BOOL isReboot;
ghProgDialog = NULL;
ghProgress = NULL;
HRESULT hresult;
if ( (! lpUninstall) || (!lpInstall) )
{
return FALSE;
}
hCurSave=SetCursor(LoadCursor(NULL, IDC_WAIT));
if(UninstallLangCount > 0)
{
#ifndef MUI_MAGIC
if (bDisplayUI)
{
CreateProgressDialog(hwnd);
SendMessage(ghProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, UninstallLangCount * INSTALLED_FILES));
SendMessage(ghProgress, PBM_SETPOS, (WPARAM)0, 0);
SetWindowTitleFromResource(ghProgDialog, IDS_UNINSTALL_TITLE);
}
#endif
//
// Uninstall MUI languages
//
if (!UninstallSelected(lpUninstall, &NotDeleted))
{
#ifndef MUI_MAGIC
if (bDisplayUI)
{
DestroyWindow(ghProgDialog);
ghProgDialog = NULL;
}
#endif
// prompt a messagebox about uninstallation error
if (bDisplayUI)
{
DoMessageBoxFromResource(hwnd, ghInstance, IDS_ERROR_UNINSTALL_LANG, lppArgs, IDS_MAIN_TITLE, MB_OK);
SetCursor(hCurSave);
}
bErrorOccurred = TRUE;
goto PostSetup;
}
#ifndef MUI_MAGIC
if (bDisplayUI)
{
SendMessage(ghProgress, PBM_SETPOS, (WPARAM)(UninstallLangCount * INSTALLED_FILES), 0);
}
#endif
}
if(InstallLangCount > 0)
{
#ifndef MUI_MAGIC
//
// Install Language Group First
//
if (!InstallLanguageGroups(&installLangGroup))
{
if (bDisplayUI)
{
DestroyWindow(ghProgDialog);
ghProgDialog = NULL;
}
if (bDisplayUI)
{
SetCursor(hCurSave);
}
bErrorOccurred = TRUE;
goto PostSetup;
}
//
// Check if language group in installLangGroup is installed correctly
//
if (!CheckLanguageGroupInstalled(lpInstall))
{
LogFormattedMessage(NULL, IDS_LG_NOT_INSTALL_L, NULL);
if (bDisplayUI || bInteractive)
{
DoMessageBox(NULL, IDS_LG_NOT_INSTALL, IDS_MAIN_TITLE, MB_OK);
}
return (FALSE);
}
#endif
//
// Make sure MUI CD-ROM is put in the CD-ROM drive.
//
if(CheckVolumeChange())
{
if (bDisplayUI)
{
#ifndef MUI_MAGIC
DestroyWindow(ghProgDialog);
ghProgDialog = NULL;
#endif
SetCursor(hCurSave);
}
return (FALSE);
}
#ifndef MUI_MAGIC
if (bDisplayUI)
{
if (ghProgDialog == NULL)
{
CreateProgressDialog(hwnd);
}
SendMessage(ghProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, InstallLangCount * INSTALLED_FILES));
SendMessage(ghProgress, PBM_SETPOS, (WPARAM)0, 0);
SetWindowTitleFromResource(ghProgDialog, IDS_INSTALL_TITLE);
}
#endif
if (!InstallSelected(lpInstall,&installLangGroup.bFontLinkRegistryTouched))
{
if (bDisplayUI)
{
DoMessageBoxFromResource(hwnd, ghInstance, IDS_ERROR_INSTALL_LANG, lppArgs, IDS_MAIN_TITLE, MB_OK);
#ifndef MUI_MAGIC
DestroyWindow(ghProgDialog);
ghProgDialog = NULL;
#endif
SetCursor(hCurSave);
}
bErrorOccurred = TRUE;
goto PostSetup;
}
#ifndef MUI_MAGIC
if (bDisplayUI)
{
SendMessage(ghProgress, PBM_SETPOS, (WPARAM)((UninstallLangCount+InstallLangCount) * INSTALLED_FILES), 0);
}
#endif
}
if (bDisplayUI)
{
#ifndef MUI_MAGIC
DestroyWindow(ghProgDialog);
ghProgDialog = NULL;
#endif
SetCursor(hCurSave);
}
if (UninstallLangCount + InstallLangCount > 0)
{
//
// "Installation Complete"
// "Installation was completed successfully."
//
if (bInteractive || bDisplayUI)
{
DoMessageBox(hwnd, InstallLangCount > 0 ? IDS_MUISETUP_SUCCESS : IDS_MUISETUP_UNINSTALL_SUCCESS, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
}
}
//
// In command line mode, if "/D" is specified, we should ask user to confirm making default UI language change.
// In command line mode, if "/D" is NOT specified, we should NOT try to change the default UI language.
// In command line mode, if "/D" & "/S" are specified, we will NOT ask user's confirmation.
// In GUI mode, we always ask user to confirm making default UI language change.
//
//
// Special case:
// If the current default UI language is going to be removed and user doesn't choose a new UI language,
// we will force to set the default UI language to be the system UI language.
//
if(g_bRemoveDefaultUI)
{
//
// Delete shell cache for the current user
//
SHDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache"));
}
if (lpDefaultUILang)
{
defaultLangID = (LANGID)_tcstol(lpDefaultUILang, NULL, 16);
if (IsInstalled(lpDefaultUILang))
{
//
// If the assigned UI language ID (defaultLangID) is already the default user UI language,
// we don't do anything. Otherwise, change the default user UI langauge.
//
if (defaultLangID != GetDotDefaultUILanguage())
{
if (SetUserDefaultLanguage(defaultLangID, FALSE, TRUE))
{
bDefaultUIChanged = TRUE;
} else
{
if (bInteractive)
{
DoMessageBox(hwnd, IDS_DEFAULT_USER_ERROR, IDS_MAIN_TITLE, (MB_OK | MB_ICONEXCLAMATION));
}
}
} else
{
// Do nothing here. I leave this here intentionally to highlight that
// we don't do antying if the specified defaultLangID is already the default UI language.
}
//
// Make sure registry is set correctly
//
if(BST_CHECKED == IsDlgButtonChecked( hwnd, IDC_CHECK_LOCALE ))
{
SetMUIRegSetting(MUI_MATCH_LOCALE, TRUE);
SetMUIRegSetting(MUI_MATCH_UIFONT, BST_CHECKED == IsDlgButtonChecked(hwnd, IDC_CHECK_UIFONT));
}
else
{
SetMUIRegSetting(MUI_MATCH_LOCALE, FALSE);
SetMUIRegSetting(MUI_MATCH_UIFONT, FALSE);
}
//
// Notify intl.cpl if we have system locale or UI font setting change
//
if ((BST_CHECKED == IsDlgButtonChecked( hwnd, IDC_CHECK_LOCALE) || g_bCmdMatchLocale || g_bLipLanguages) &&
defaultLangID != lidSys)
{
TCHAR szCommands[BUFFER_SIZE];
//
// Invoke intl.cpl to change system locale to match the default UI language
//
//*STRSAFE* wsprintf(szCommands, TEXT("SystemLocale = \"%x\""), defaultLangID);
hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("SystemLocale = \"%x\""), defaultLangID);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//
// Always reboot if system locale is changed
//
if (RunRegionalOptionsApplet(szCommands))
{
g_bReboot = TRUE;
}
}
else if (g_bMatchUIFont != (BST_CHECKED == IsDlgButtonChecked(hwnd, IDC_CHECK_UIFONT)) ||
g_bCmdMatchUIFont)
{
TCHAR szCommands[BUFFER_SIZE];
//
// We're not really changing system locale here, it is used to invoke intl.cpl for font setting changes
//
//*STRSAFE* wsprintf(szCommands, TEXT("SystemLocale = \"%x\""), lidSys);
hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("SystemLocale = \"%x\""), lidSys);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
if (RunRegionalOptionsApplet(szCommands) && defaultLangID == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
{
// Don't prompt for reboot, intl.cpl will cause muisetup to lose focus if we do so.
// Need to fix this in XP server release
g_bReboot = TRUE;
}
}
//
// Change user locale for LIP languages
//
if (g_bLipLanguages)
{
TCHAR szCommands[BUFFER_SIZE];
//
// Invoke intl.cpl to change system locale to match the default UI language
//
//*STRSAFE* wsprintf(szCommands, TEXT("UserLocale = \"%x\"\x0d\x0aUserLocale_DefaultUser = \"%x\"\x0d\x0aMUILanguage=\"%x\""), defaultLangID, defaultLangID, defaultLangID);
hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("UserLocale = \"%x\"\x0d\x0aUserLocale_DefaultUser = \"%x\"\x0d\x0aMUILanguage=\"%x\""), defaultLangID, defaultLangID, defaultLangID);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
if (RunRegionalOptionsApplet(szCommands) && defaultLangID == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
{
// Don't prompt for reboot, intl.cpl will cause muisetup to loose focus if we do so.
// Need to fix this in XP server release
g_bReboot = TRUE;
}
}
} else
{
//
// "ERROR: %1 was not set as the default. It is not installed.\r\nNo default UI language change."
//
lppArgs[0] = (LONG_PTR)lpDefaultUILang;
LogFormattedMessage(NULL, IDS_DEFAULT_L, lppArgs);
return (FALSE);
}
}
PostSetup:
//
// Check for reboot, and if we are allowed to do so.
//
if (fAllowReboot)
{
//
// Check if we need to reboot?
//
if (!CheckForReboot(hwnd, &installLangGroup))
{
//
// Check if we recommend a reboot?
//
if ((bInteractive || bDisplayUI) && bDefaultUIChanged)
{
GetLanguageDisplayName(defaultLangID, lpTemp, ARRAYSIZE(lpTemp)-1);
lppArgs[0] = (LONG_PTR)lpTemp;
if (lidSys == defaultLangID)
{
if (bDisplayUI)
{
isReboot = (DoMessageBoxFromResource(hwnd, ghInstance, IDS_CHANGE_UI_NEED_RBOOT, lppArgs, IDS_MAIN_TITLE, MB_YESNO) == IDYES);
}
else
{
isReboot = TRUE;
}
} else
{
GetLanguageDisplayName(lidSys, lpTemp2, ARRAYSIZE(lpTemp2)-1);
lppArgs[1] = (LONG_PTR)lpTemp2;
if (bDisplayUI)
{
isReboot = (DoMessageBoxFromResource(hwnd, ghInstance, IDS_CHANGE_UI_NEED_RBOOT_SYSTEM_LCID, lppArgs, IDS_MAIN_TITLE, MB_YESNO) == IDYES);
}
else
{
isReboot = TRUE;
}
}
if (isReboot)
{
Muisetup_RebootTheSystem();
}
}
}
}
if (bErrorOccurred)
return (FALSE);
return (TRUE);
}
int ParseUninstallLangs(LPTSTR p, LPTSTR lpUninstall, int cchUninstall, INT64* pulUISize, INT64* pulLPKSize, INT64* pulSpaceNeed, BOOL* pbLogError)
{
int iCopied;
TCHAR lpBuffer[BUFFER_SIZE];
LONG_PTR lppArgs[2];
int cLanguagesToUnInstall = 0;
LANGID LgId;
LPTSTR pU = lpUninstall;
if ((!p) || (! lpUninstall) || (!pulUISize) || (!pulLPKSize) || (!pulSpaceNeed) || (!pbLogError))
{
return FALSE;
}
p = SkipBlanks(p);
if (!p)
return FALSE;
iCopied = 0;
while((*p != TEXT('-')) && (*p != TEXT('/')) && (*p != TEXT('\0')))
{
iCopied = CopyArgument(lpBuffer, p);
if(!HaveFiles(lpBuffer, FALSE))
{
//
// "LOG: %1 was not installed. It is not listed in MUI.INF."
//
lppArgs[0] = (LONG_PTR)lpBuffer;
LogFormattedMessage(NULL, IDS_NOT_LISTED_L, lppArgs);
*pbLogError = TRUE;
} else if (!IsInstalled(lpBuffer))
{
//
// "LOG: %1 was not uninstalled, because it is not installed. "
//
lppArgs[0] = (LONG_PTR)lpBuffer;
LogFormattedMessage(NULL, IDS_IS_NOT_INSTALLED_L, lppArgs);
*pbLogError = TRUE;
} else if (!IsInInstallList(lpUninstall,lpBuffer))
{
iCopied = CopyArgument(pU, p);
//
// Check if we are going to remove the current UI language
//
LgId = (LANGID)_tcstol(pU, NULL, 16);
if (LgId == GetDotDefaultUILanguage())
{
g_bRemoveDefaultUI = TRUE;
}
if (LgId == GetUserDefaultUILanguage())
{
g_bRemoveUserUI = TRUE;
}
//
// Calculate the space required
//
GetUIFileSize_commandline(lpBuffer, pulUISize,pulLPKSize);
*pulSpaceNeed-=*pulUISize;
pU += iCopied;
pU++; //skip over NULL
cLanguagesToUnInstall++;
}
p += iCopied;
p = SkipBlanks(p);
}
//
// Uninstall all MUI languages if there is no language argument after /U
//
if (iCopied == 0)
{
cLanguagesToUnInstall = GetInstalledMUILanguages(lpUninstall, cchUninstall);
if (cLanguagesToUnInstall == 0)
{
LogFormattedMessage(ghInstance, IDS_NO_MUI_LANG, NULL);
*pbLogError = TRUE;
}
else
{
if (0x0409 != GetDotDefaultUILanguage())
{
g_bRemoveDefaultUI = TRUE;
}
if (0x0409 != GetUserDefaultUILanguage())
{
g_bRemoveUserUI = TRUE;
}
}
}
else
{
*pU=TEXT('\0');
}
return (cLanguagesToUnInstall);
}
////////////////////////////////////////////////////////////////////////////
//
// GetCDNameFromLang
//
// Given a langange ID (in hex string), return the CD name where the language
// installation folder exist.
// This can also be used to check if the language is supported MUI language.
//
// Parameters:
// [IN] lpLangName the language to be installed in hex string.
// [OUT] lpCDName the number of the CD (e.g. "2" or "3").
// [IN] nCDNameSize the size of lpCDName, in TCHAR.
//
// Return Values:
// TRUE if lpLangName is a supported MUI language. lpCDName will contain
// the name of the CD.
// FALSE if the language ID is not a supported langauge. lpCDNAme will be
// empty string.
//
// Remarks:
//
// 01-01-2001 YSLin Created.
//
////////////////////////////////////////////////////////////////////////////
BOOL GetCDNameFromLang(LPTSTR lpLangName, LPTSTR lpCDName, int nCDNameSize)
{
if (!GetPrivateProfileString(
MUI_CDLAYOUT_SECTION,
lpLangName,
TEXT(""),
lpCDName,
nCDNameSize,
g_szMUIInfoFilePath))
{
return (FALSE);
}
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// ParseCommandLine
//
// Runs installation functions with command line specifications
//
////////////////////////////////////////////////////////////////////////////////////
BOOL ParseCommandLine(LPTSTR lpCommandLine)
{
BOOL bSetDefaultUI=FALSE; // Specify if the /D switch is used to change the user default UI language.
BOOL bInstall=FALSE;
BOOL bLogError=FALSE;
BOOL bFELangpackAdded=FALSE;
BOOL bResult = FALSE;
DWORD dwDisp;
LANGID LgId;
TCHAR lpBuffer[BUFFER_SIZE];
TCHAR lpDefault[BUFFER_SIZE];
TCHAR lpDefaultText[MAX_PATH];
TCHAR lpInstall[BUFFER_SIZE];
TCHAR lpMessage[BUFFER_SIZE];
TCHAR lpUninstall[BUFFER_SIZE];
TCHAR lpSystemDefault[BUFFER_SIZE];
TCHAR lpTemp[BUFFER_SIZE];
TCHAR szWinDir[MAX_PATH];
INSTALL_LANG_GROUP installLangGroup;
LONG_PTR lppArgs[4];
PTCHAR pI;
PTCHAR pD;
PTCHAR p;
BOOL fAllowReboot = TRUE;
int cLanguagesToInstall = 0L;
int cLanguagesToUnInstall = 0L;
int iCopied;
TCHAR chOpt;
INT64 ulSpaceNeed=0,ulSpaceAvailable=0,ulUISize=0,ulLPKSize=0;
ULONG ulParam[2];
ULARGE_INTEGER ulgiFreeBytesAvailableToCaller;
ULARGE_INTEGER ulgiTotalNumberOfBytes;
BOOL bHasLangArgs = FALSE;
BOOL bHelpDisplayed=FALSE;
//PREFAST TCHAR lpCDName[BUFFER_SIZE];
LPTSTR lpCDName=NULL;
if (!lpCommandLine)
{
return FALSE;
}
//
// Allocate space for Heap variable
//
lpCDName = new TCHAR[BUFFER_SIZE];
if (! lpCDName)
{
goto exit_ParseCommandLine;
}
//
// Initialize Lang-Groups to install
//
installLangGroup.iCount = 0L;
installLangGroup.NotDeleted = 0L;
installLangGroup.bFontLinkRegistryTouched = FALSE;
lpInstall[0] = TEXT('\0');
lpUninstall[0] = TEXT('\0');
lpDefault[0] = TEXT('\0');
pI = lpInstall;
pD = lpDefault;
p = lpCommandLine;
CharLower(p);
while(p=NextCommandTag(p))
{
chOpt = *p++;
switch (chOpt)
{
case '?':
case 'h':
if (!bHelpDisplayed)
{
DisplayHelpWindow();
bHelpDisplayed=TRUE;
}
// if we encountered a help switch, after displaying the window, we just exit
bResult = TRUE;
goto exit_ParseCommandLine;
// p = SkipBlanks(p);
break;
case 'i':
if (!FileExists(g_szMUIInfoFilePath))
{
//
// "The file MUI.INF cannot be found."
//
DoMessageBox(NULL, IDS_NO_MUI_FILE, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
break;
}
//
// MUI version needs to match OS version
//
if (!checkversion(TRUE))
{
DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
break;
}
p = SkipBlanks(p);
while ((*p != TEXT('-')) && (*p != TEXT('/')) && (*p != TEXT('\0')))
{
bHasLangArgs = TRUE;
iCopied=CopyArgument(lpBuffer, p);
if (!IsInstalled(lpBuffer) &&
CheckLanguageIsQualified(lpBuffer) &&
HaveFiles(lpBuffer) && (!IsInInstallList(lpInstall,lpBuffer)) )
{
//
// Calculate the space required
//
GetUIFileSize_commandline(lpBuffer, &ulUISize,&ulLPKSize);
ulSpaceNeed+=ulUISize;
if(CheckLangGroupCommandLine(&installLangGroup, lpBuffer))
{
if (IS_FE_LANGPACK(_tcstol(lpBuffer, NULL, 16)))
{
if (!bFELangpackAdded)
{
ulSpaceNeed+=ulLPKSize;
bFELangpackAdded = TRUE;
}
}else
{
ulSpaceNeed+=ulLPKSize;
}
}
AddExtraLangGroupsFromINF(lpBuffer, &installLangGroup);
iCopied=CopyArgument(pI, p);
pI += iCopied;
pI++; //skip over NULL
bInstall = TRUE;
cLanguagesToInstall++;
}
else
{
lppArgs[0]=(LONG_PTR)lpBuffer;
if(IsInstalled(lpBuffer)|| IsInInstallList(lpInstall,lpBuffer))
{
// "LOG: %1 was not installed, because it is already installed. "
LogFormattedMessage(ghInstance, IDS_IS_INSTALLED_L, lppArgs);
}
if(!HaveFiles(lpBuffer))
{
if (!GetCDNameFromLang(lpBuffer, lpCDName, ARRAYSIZE(lpCDName)))
{
// lpBuffer is not a supported MUI language.
// "LOG: %1 was not installed, because it is not listed in MUI.INF. Please check if it is a valid UI language ID."
LogFormattedMessage(ghInstance, IDS_NOT_LISTED_L, lppArgs);
} else
{
// lpBuffer is a supported MUI language, ask user to change CD and
// rerun setup.
LoadString(ghInstance, IDS_CHANGE_CDROM, lpTemp, ARRAYSIZE(lpTemp)-1);
lppArgs[1] = (LONG_PTR)lpTemp;
lppArgs[2] = (LONG_PTR)lpCDName;
// "ERROR: %1 was not installed, because it is located in %2 %3. Please insert that CD and rerun MUISetup."
LogFormattedMessage(ghInstance, IDS_LANG_IN_ANOTHER_CD_L, lppArgs);
}
}
if(!CheckLanguageIsQualified(lpBuffer))
{
// "LOG: %1 was not installed, because it cannot be installed on this platform\n"
LogFormattedMessage(ghInstance, IDS_NOT_QUALIFIED_L, lppArgs);
}
bLogError = TRUE;
}
p += iCopied;
p = SkipBlanks(p);
}
if (!bHasLangArgs)
{
lppArgs[0] = (LONG_PTR)TEXT("/I");
FormatStringFromResource(lpMessage, sizeof(lpMessage)/sizeof(TCHAR), ghInstance, IDS_ERROR_NO_LANG_ARG, lppArgs);
LogMessage(lpMessage);
bLogError = TRUE;
}
*pI = TEXT('\0');
break;
case 'u':
if (!checkversion(FALSE))
{
DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
break;
}
cLanguagesToUnInstall = ParseUninstallLangs(p, lpUninstall, ARRAYSIZE(lpUninstall), &ulUISize, &ulLPKSize, &ulSpaceNeed, &bLogError);
break;
case 'd':
if (!checkversion(FALSE))
{
DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
break;
}
bSetDefaultUI = TRUE;
p = SkipBlanks(p);
if (CopyArgument(lpDefault, p) == 0)
{
lppArgs[0] = (LONG_PTR)TEXT("/D");
FormatStringFromResource(lpMessage, sizeof(lpMessage)/sizeof(TCHAR),
ghInstance, IDS_ERROR_NO_LANG_ARG, lppArgs);
LogMessage(lpMessage);
bLogError = FALSE;
}
break;
case 'r':
fAllowReboot = FALSE;
break;
case 's' :
g_bSilent = TRUE;
// check if desktop is interactive or not, if not, hide all UI
if (FALSE == IsWindowVisible(GetDesktopWindow()))
{
g_bNoUI = TRUE;
}
break;
case 't' :
// use this switch to totally suppress all the possible UI that can be popped up by muisetup and the processes it
// launches.
g_bSilent = TRUE;
g_bNoUI = TRUE;
break;
case 'l':
g_bCmdMatchLocale = TRUE;
break;
case 'f':
g_bCmdMatchUIFont = TRUE;
break;
case 'o':
g_bRunFromOSSetup = TRUE;
break;
default:
// if we encounter an invalid switch at any stage, treat it the same as help and quit afterwards
if (!bHelpDisplayed)
{
DisplayHelpWindow();
bHelpDisplayed=TRUE;
}
// if we encountered a help switch, after displaying the window, we just exit
bResult = TRUE;
goto exit_ParseCommandLine;
break;
}
}
//
// UI Font depends on system locale
//
if (!g_bCmdMatchLocale && g_bCmdMatchUIFont)
{
g_bCmdMatchUIFont = FALSE;
}
//
// Check the disk space
//
//
pfnGetWindowsDir( szWinDir, MAX_PATH);
szWinDir[3]=TEXT('\0');
if (GetDiskFreeSpaceEx(szWinDir,
&ulgiFreeBytesAvailableToCaller,
&ulgiTotalNumberOfBytes,
NULL))
{
ulSpaceAvailable= ulgiFreeBytesAvailableToCaller.QuadPart;
if ( ulSpaceAvailable < ulSpaceNeed )
{
ulParam[0] = (ULONG) (ulSpaceNeed/1024);
ulParam[1] = (ULONG) (ulSpaceAvailable/1024);
LoadString(ghInstance, IDS_DISKSPACE_NOTENOUGH, lpMessage, ARRAYSIZE(lpMessage)-1);
LoadString(ghInstance, IDS_ERROR_DISKSPACE, lpTemp, ARRAYSIZE(lpTemp)-1);
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
lpMessage,
0,
0,
lpMessage,
ARRAYSIZE(lpMessage)-1,
(va_list *) ulParam);
LogMessage(lpMessage);
bLogError = TRUE;
MESSAGEBOX(NULL, lpMessage, lpTemp, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
bInstall = FALSE;
cLanguagesToUnInstall = 0;
}
}
if (!bLogError)
{
//
// Let's set the default UI language
//
if (!DoSetup(
NULL,
cLanguagesToUnInstall, lpUninstall,
installLangGroup,
cLanguagesToInstall, lpInstall,
(bSetDefaultUI ? lpDefault : NULL),
fAllowReboot, !g_bSilent, !g_bNoUI))
{
bLogError = TRUE;
}
}
if (bLogError && !g_bSilent && !g_bNoUI)
{
//
// "Installation Error"
// "One or more errors occurred during installation.
// Please see %1\muisetup.log for more information."
//
lppArgs[0] = (LONG_PTR)szWindowsDir;
DoMessageBoxFromResource(NULL, ghInstance, IDS_ERROR, lppArgs, IDS_ERROR_T, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
}
bResult = TRUE;
exit_ParseCommandLine:
if (lpCDName)
{
delete [] lpCDName;
}
return bResult;
}
////////////////////////////////////////////////////////////////////////////////////
//
// DisplayHelpWindow
//
// Displays help window for command line version
//
////////////////////////////////////////////////////////////////////////////////////
void DisplayHelpWindow()
{
STARTUPINFO si;
PROCESS_INFORMATION pi = {0};
TCHAR Appname[MAX_PATH+MAX_PATH+1],szFilePath[MAX_PATH+1];
HRESULT hresult;
int nLen;
szFilePath[0] = UNICODE_NULL;
if (!pfnGetWindowsDir(szFilePath, MAX_PATH))
{
return;
}
nLen = lstrlen(szFilePath);
if (szFilePath[nLen-1] != TEXT('\\'))
{
hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return;
}
}
hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), WINHELP32PATH);
if (!SUCCEEDED(hresult))
{
return ;
}
if (FileExists(g_szMUIHelpFilePath))
{
//*STRSAFE* wsprintf(Appname,TEXT("\"%s\" -n%d %s"),szFilePath,IDH_MUISETUP_COMMANDLINE,g_szMUIHelpFilePath);
hresult = StringCchPrintf(Appname , ARRAYSIZE(Appname), TEXT("\"%s\" -n%d %s"),szFilePath, IDH_MUISETUP_COMMANDLINE,g_szMUIHelpFilePath);
if (!SUCCEEDED(hresult))
{
return;
}
memset( &si, 0x00, sizeof(si));
si.cb = sizeof(STARTUPINFO);
if (!CreateProcess(NULL,
Appname,
NULL,
NULL,
FALSE,
0L,
NULL, NULL,
&si,
&pi) )
return;
WaitForSingleObject(pi.hProcess, INFINITE);
//
// Close Handle
//
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
else
{
//////////////////////////////////////////////
// MessageBox should be changed to Dialog
//////////////////////////////////////////////
DoMessageBox(NULL, IDS_HELP, IDS_HELP_T, MB_OK | MB_DEFBUTTON1);
}
}
////////////////////////////////////////////////////////////////////////////////////
//
// CopyArgument
//
// Copies command line argument pointed to by src to dest
//
////////////////////////////////////////////////////////////////////////////////////
int CopyArgument(LPTSTR dest, LPTSTR src)
{
int i=0;
if ((!dest) || (!src))
{
return i;
}
while(*src!=TEXT(' ') && *src!=TEXT('\0'))
{
*dest=*src;
dest++;
src++;
i++;
}
*dest = TEXT('\0');
return i;
}
////////////////////////////////////////////////////////////////////////////////////
//
// IsInstalled
//
// Checks to see if lpArg is a language installed in the registry
//
////////////////////////////////////////////////////////////////////////////////////
BOOL IsInstalled(LPTSTR lpArg)
{
HKEY hKey;
DWORD dwData;
DWORD dwIndex;
DWORD dwValue;
TCHAR lpData[BUFFER_SIZE];
TCHAR lpValue[BUFFER_SIZE];
int rc;
int iArg;
if (!lpArg)
{
return FALSE;
}
hKey=OpenMuiKey(KEY_READ);
if (hKey == NULL)
{
return (FALSE);
}
dwIndex=0;
rc=ERROR_SUCCESS;
iArg=_tcstol(lpArg, NULL, 16);
if (iArg == gSystemUILangId)
{
RegCloseKey(hKey);
return (TRUE);
}
while(rc==ERROR_SUCCESS)
{
dwValue=sizeof(lpValue)/sizeof(TCHAR);
lpValue[0]=TEXT('\0');
dwData=sizeof(lpData);
lpData[0]=TEXT('\0');
DWORD dwType;
rc=RegEnumValue(hKey, dwIndex, lpValue, &dwValue, 0, &dwType, (LPBYTE)lpData, &dwData);
if(rc==ERROR_SUCCESS)
{
if (dwType != REG_SZ)
{
dwIndex++;
continue;
}
if(_tcstol(lpValue, NULL, 16)==iArg)
{
RegCloseKey(hKey);
return TRUE;
}
}
dwIndex++;
}
RegCloseKey(hKey);
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetInstalledMUILanguages
//
// Get installed MUI languages, dump it to lpUninstall buffer in a MULTI_SZ format
//
////////////////////////////////////////////////////////////////////////////////////
DWORD GetInstalledMUILanguages(LPTSTR lpUninstall, int cch)
{
HKEY hKey;
DWORD dwIndex = 0;
DWORD dwCount = 0;
DWORD dwValue = cch;
DWORD dwType = 0;
if (!lpUninstall)
{
return dwCount;
}
if (hKey = OpenMuiKey(KEY_READ))
{
while(ERROR_NO_MORE_ITEMS != RegEnumValue(hKey, dwIndex++, lpUninstall, &dwValue, 0, &dwType, NULL, NULL) &&
cch > 0)
{
if (dwType != REG_SZ)
continue;
if (_tcstol(lpUninstall, NULL, 16) != gSystemUILangId)
{
//
// Count in NULL
//
dwValue++;
lpUninstall += dwValue;
cch -= dwValue;
dwCount++;
}
dwValue = cch;
}
RegCloseKey(hKey);
*lpUninstall = TEXT('\0');
}
return dwCount;
}
////////////////////////////////////////////////////////////////////////////////////
//
// HaveFiles
//
// Checks that the language in lpBuffer is in MUI.INF
//
////////////////////////////////////////////////////////////////////////////////////
BOOL HaveFiles(LPTSTR lpBuffer, BOOL bCheckDir)
{
LPTSTR lpLanguages = NULL;
TCHAR lpMessage[BUFFER_SIZE];
TCHAR tchBuffer[BUFFER_SIZE];
if (!lpBuffer)
{
return FALSE;
}
lpLanguages = tchBuffer;
if (EnumLanguages(lpLanguages, bCheckDir) == 0)
{
//
// "LOG: No languages found in MUI.INF"
//
LoadString(ghInstance, IDS_NO_LANG_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
return FALSE;
}
if(!lpLanguages)
return FALSE;
while (*lpLanguages != TEXT('\0'))
{
if (_tcscmp(lpBuffer, lpLanguages) == 0)
{
return TRUE;
}
lpLanguages = _tcschr(lpLanguages, '\0');
lpLanguages++;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// OpenLogFile
//
// Opens the setup log for writing
//
////////////////////////////////////////////////////////////////////////////////////
HANDLE OpenLogFile()
{
DWORD dwSize;
DWORD dwUnicodeHeader;
HANDLE hFile;
SECURITY_ATTRIBUTES SecurityAttributes;
TCHAR lpPath[BUFFER_SIZE];
int error;
HRESULT hresult;
pfnGetWindowsDir(lpPath, MAX_PATH);
error=GetLastError();
//*STRSAFE* _tcscat(lpPath, LOG_FILE);
hresult = StringCchCat(lpPath , ARRAYSIZE(lpPath), LOG_FILE);
if (!SUCCEEDED(hresult))
{
return NULL;
}
SecurityAttributes.nLength=sizeof(SecurityAttributes);
SecurityAttributes.lpSecurityDescriptor=NULL;
SecurityAttributes.bInheritHandle=FALSE;
hFile=CreateFile(
lpPath,
GENERIC_WRITE,
0,
&SecurityAttributes,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
#ifdef UNICODE
//
// If the file did not already exist, add the unicode header
//
if(GetLastError()==0)
{
dwUnicodeHeader=0xFEFF;
WriteFile(hFile, &dwUnicodeHeader, 2, &dwSize, NULL);
}
#endif
error=GetLastError();
return hFile;
}
////////////////////////////////////////////////////////////////////////////////////
//
// LogMessage
//
// Writes lpMessage to the setup log
//
////////////////////////////////////////////////////////////////////////////////////
BOOL LogMessage(LPCTSTR lpMessage)
{
DWORD dwBytesWritten;
HANDLE hFile;
if (!lpMessage)
{
return FALSE;
}
hFile=OpenLogFile();
if(hFile==INVALID_HANDLE_VALUE)
{
return FALSE;
}
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(
hFile,
lpMessage,
_tcslen(lpMessage) * sizeof(TCHAR),
&dwBytesWritten,
NULL);
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(
hFile,
TEXT("\r\n"),
_tcslen(TEXT("\r\n")) * sizeof(TCHAR),
&dwBytesWritten,
NULL);
CloseHandle(hFile);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// LogFormattedMessage
//
// Writes a formatted lpMessage to the setup log
//
////////////////////////////////////////////////////////////////////////////////////
BOOL LogFormattedMessage(HINSTANCE hInstance, int messageID, LONG_PTR* lppArgs)
{
TCHAR szBuffer[BUFFER_SIZE];
LoadString(hInstance, messageID, szBuffer, ARRAYSIZE(szBuffer));
if (lppArgs == NULL)
{
return (LogMessage(szBuffer));
}
FormatMessage(
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szBuffer,
0,
0,
szBuffer,
sizeof(szBuffer) / sizeof(TCHAR),
(va_list *)lppArgs);
return (LogMessage(szBuffer));
}
////////////////////////////////////////////////////////////////////////////
//
// FormatStringFromResource
//
// Format a string using the format specified in the resource and the
// specified arguments.
//
// Parameters:
//
// Return Values:
// the formatted string.
//
// Remarks:
//
// 08-07-2000 YSLin Created.
//
////////////////////////////////////////////////////////////////////////////
LPTSTR FormatStringFromResource(LPTSTR pszBuffer, UINT bufferSize, HMODULE hInstance, int messageID, LONG_PTR* lppArgs)
{
TCHAR szFormatStr[BUFFER_SIZE];
LoadString(hInstance, messageID, szFormatStr, ARRAYSIZE(szFormatStr)-1);
if (!lppArgs)
{
LogMessage(szFormatStr);
return NULL;
}
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szFormatStr,
0,
0,
pszBuffer,
bufferSize ,
(va_list *)lppArgs);
return (pszBuffer);
}
////////////////////////////////////////////////////////////////////////////////////
//
// BeginLog
//
// Writes a header to the setup log
//
////////////////////////////////////////////////////////////////////////////////////
void BeginLog(void)
{
TCHAR lpMessage[BUFFER_SIZE];
SYSTEMTIME stSysTime;
HRESULT hresult;
//
// "**********************************************************
// Language Module Installation Log
// **********************************************************" (LOG)
//
LoadString(ghInstance, IDS_LOG_HEAD, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
// Also log the time the mui installation is started.
GetLocalTime(&stSysTime);
//*STRSAFE* wsprintf(lpMessage, TEXT("Muisetup.exe started on day %2d/%2d/%4d at time %2d:%2d:%2d"),
//*STRSAFE* stSysTime.wMonth,
//*STRSAFE* stSysTime.wDay,
//*STRSAFE* stSysTime.wYear,
//*STRSAFE* stSysTime.wHour,
//*STRSAFE* stSysTime.wMinute,
//*STRSAFE* stSysTime.wSecond
//);
hresult = StringCchPrintf(lpMessage , ARRAYSIZE(lpMessage) , TEXT("Muisetup.exe started on day %2d/%2d/%4d at time %2d:%2d:%2d"),
stSysTime.wMonth,
stSysTime.wDay,
stSysTime.wYear,
stSysTime.wHour,
stSysTime.wMinute,
stSysTime.wSecond
);
if (!SUCCEEDED(hresult))
{
return;
}
LogMessage(lpMessage);
}
////////////////////////////////////////////////////////////////////////////////////
//
// GetLanguageGroup
//
// Retreive the Language Group of this locale.
//
////////////////////////////////////////////////////////////////////////////////////
LGRPID GetLanguageGroup(LCID lcid)
{
int i;
gLangGroup = LGRPID_WESTERN_EUROPE;
gFoundLangGroup = FALSE;
gLCID = lcid;
for (i=0 ; i<gNumLanguageGroups; i++)
{
// The globals gLangGroup and gFoundLangGroup is used in the callback function
// EnumLanguageGroupLocalesProc.
gpfnEnumLanguageGroupLocalesW(EnumLanguageGroupLocalesProc, gLanguageGroups[i], 0L, 0L);
//
// If we found it, then break now
//
if (gFoundLangGroup)
break;
}
return gLangGroup;
}
BOOL EnumLanguageGroupLocalesProc(
LGRPID langGroupId,
LCID lcid,
LPTSTR lpszLocale,
LONG_PTR lParam)
{
if (lcid == gLCID)
{
gLangGroup = langGroupId;
gFoundLangGroup = TRUE;
// stop iterating
return FALSE;
}
// next iteration
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// DetectLanguageGroups
//
// Detect language groups installed.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL DetectLanguageGroups(HWND hwndDlg)
{
int i;
HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST1);
HWND hwndProgress, hwndStatus,hProgDlg;
int iCount = ListView_GetItemCount(hwndList);
LVITEM lvItem;
PMUILANGINFO pMuiLangInfo;
TCHAR szBuf[MAX_PATH], szStatus[MAX_PATH];
PVOID ppArgs[1];
hProgDlg = CreateDialog(ghInstance,
MAKEINTRESOURCE(IDD_DIALOG_INSTALL_PROGRESS),
hwndDlg,
ProgressDialogFunc);
hwndProgress = GetDlgItem(hProgDlg, IDC_PROGRESS1);
hwndStatus = GetDlgItem(hProgDlg, IDC_STATUS);
//
// Reflect that we doing something on the UI
//
LoadString(ghInstance, IDS_INSTALLLANGGROUP, szBuf, MAX_PATH-1);
SetWindowText(hProgDlg, szBuf);
SendMessage(hwndProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, iCount));
SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)(0), 0);
SetWindowText(hwndStatus, TEXT(""));
i = 0;
while (i < iCount)
{
//
// Check if Language Group is installed
//
lvItem.mask = LVIF_PARAM;
lvItem.iItem = i;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = 0;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
lvItem.lParam = 0;
ListView_GetItem(hwndList, &lvItem);
pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)i+1, 0L);
LoadString(ghInstance, IDS_CHECK_LANG_GROUP, szStatus, MAX_PATH-1);
if (pMuiLangInfo->szDisplayName[0] == L'\0')
{
GetDisplayName(pMuiLangInfo);
}
ppArgs[0] = pMuiLangInfo->szDisplayName;
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szStatus,
0,
0,
szStatus,
MAX_PATH-1,
(va_list *)ppArgs);
SetWindowText(hwndStatus, szStatus);
pMuiLangInfo->lgrpid = GetLanguageGroup(pMuiLangInfo->lcid);
i++;
};
SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)i+1, 0L);
DestroyWindow(hProgDlg);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// AddExtraLangGroupsFromINF
//
// Look at the [LanguagePack] section to see if we need to install extra
// language packs for the language specified in lpszLcid.
//
// This is basically used to support pseudo localized build.
//
// Parameter:
// lpszLcid the LCID of UI language to be installed in string form.
// pInstallLangGroup points to a strcutre which stores language groups to be installed.
//
// Remarks:
//
// 10-11-2000 YSLin Created.
////////////////////////////////////////////////////////////////////////////////////
BOOL AddExtraLangGroupsFromINF(LPTSTR lpszLcid, PINSTALL_LANG_GROUP pInstallLangGroup)
{
WCHAR szBuffer[BUFFER_SIZE];
HINF hInf;
INFCONTEXT InfContext;
LONG_PTR lppArgs[2];
int LangGroup;
int i;
HRESULT hresult;
if (!pInstallLangGroup)
{
return FALSE;
}
hInf = SetupOpenInfFile(g_szMUIInfoFilePath, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
//*STRSAFE* _stprintf(szBuffer, TEXT("%d"), GetLastError());
hresult = StringCchPrintf(szBuffer , ARRAYSIZE(szBuffer), TEXT("%d"), GetLastError());
if (!SUCCEEDED(hresult))
{
return FALSE;
}
lppArgs[0] = (LONG_PTR)szBuffer;
lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
return (FALSE);
}
if (SetupFindFirstLine(hInf, MUI_LANGPACK_SECTION, lpszLcid, &InfContext))
{
i = 1;
while (SetupGetIntField(&InfContext, i++, &LangGroup))
{
AddMUILangGroup(pInstallLangGroup, LangGroup);
}
}
SetupCloseInfFile(hInf);
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// ConvertMUILangToLangGroup
//
// Generate Lang-Group IDs for the selected items in the listview,
// in preparation to pass them to InstallLanguageGroups(...)
////////////////////////////////////////////////////////////////////////////////////
BOOL ConvertMUILangToLangGroup(HWND hwndDlg, PINSTALL_LANG_GROUP pInstallLangGroup)
{
int i;
LVITEM lvItem;
HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST1);
int iCount = ListView_GetItemCount(hwndList);
PMUILANGINFO pMuiLangInfo;
if (!pInstallLangGroup)
{
return FALSE;
}
//
// Initialize to "No lang-groups to install"
//
pInstallLangGroup->iCount = 0L;
i = 0;
while (i < iCount)
{
if (ListView_GetCheckState(hwndList, i))
{
//
// Check if Language Group is installed
//
lvItem.mask = LVIF_PARAM;
lvItem.iItem = i;
lvItem.iSubItem = 0;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.pszText = 0;
lvItem.cchTextMax = 0;
lvItem.iImage = 0;
lvItem.lParam = 0;
ListView_GetItem(hwndList, &lvItem);
pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
//
// Make sure there are no redundant elements
//
AddMUILangGroup(pInstallLangGroup, pMuiLangInfo->lgrpid);
//
// Add extra language groups specified in [LangPack] section of mui.inf
// This is used to support Pesudo Localized Build.
//
AddExtraLangGroupsFromINF(pMuiLangInfo->lpszLcid, pInstallLangGroup);
}
i++;
};
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// AddMUILangGroup
//
// Add a language a group to INSTALL_LANG_GROUP. Takes care of duplicates.
////////////////////////////////////////////////////////////////////////////////////
BOOL AddMUILangGroup(PINSTALL_LANG_GROUP pInstallLangGroup, LGRPID lgrpid)
{
int j = 0L;
BOOL bFound = FALSE;
if (!pInstallLangGroup)
{
return FALSE;
}
//
// Check if it is installed by default
//
if (gpfnIsValidLanguageGroup(lgrpid, LGRPID_INSTALLED))
{
return FALSE;
}
while (j < pInstallLangGroup->iCount)
{
if (pInstallLangGroup->lgrpid[j] == lgrpid)
{
bFound = TRUE;
}
j++;
}
if (!bFound)
{
pInstallLangGroup->lgrpid[j] = lgrpid;
pInstallLangGroup->iCount++;
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
//
// RunRegionalOptionsApplet
//
// Run the Regional Option silent mode installation using the specified pCommands.
//
// This function will create the "[RegigionalSettings]" string, so there is no need
// to supply that in pCommands.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL RunRegionalOptionsApplet(LPTSTR pCommands)
{
HANDLE hFile;
TCHAR szFilePath[MAX_PATH], szCmdLine[MAX_PATH];
DWORD dwNumWritten = 0L;
STARTUPINFO si;
PROCESS_INFORMATION pi = {0};
int i;
LONG_PTR lppArgs[3];
HRESULT hresult;
TCHAR szRunDllPath[MAX_PATH];
TCHAR szSection[MAX_PATH] = TEXT("[RegionalSettings]\r\n");
if (!pCommands)
{
return FALSE;
}
//
// prepare the file for un-attended mode setup
//
szFilePath[0] = UNICODE_NULL;
if (!pfnGetWindowsDir(szFilePath, MAX_PATH-1))
{
return FALSE;
}
i = lstrlen(szFilePath);
if (szFilePath[i-1] != TEXT('\\'))
{
//*STRSAFE* lstrcat(szFilePath, TEXT("\\"));
hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), TEXT("\\"));
if (!SUCCEEDED(hresult))
{
return FALSE;
}
}
hresult = StringCchCopy(szRunDllPath , ARRAYSIZE(szRunDllPath), szFilePath);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
//*STRSAFE* lstrcat(szFilePath, MUI_LANG_GROUP_FILE);
hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), MUI_LANG_GROUP_FILE);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
hresult = StringCchCat(szRunDllPath , ARRAYSIZE(szRunDllPath), RUNDLLNAME);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
hFile = CreateFile(szFilePath,
GENERIC_WRITE,
0L,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
lppArgs[0] = (LONG_PTR)szFilePath;
LogFormattedMessage(ghInstance, IDS_ERROR_FILE_CREATE, lppArgs);
return FALSE;
}
WriteFile(hFile,
szSection,
(lstrlen(szSection) * sizeof(TCHAR)),
&dwNumWritten,
NULL);
if (dwNumWritten != (lstrlen(szSection) * sizeof(TCHAR)))
{
lppArgs[0] = (LONG_PTR)szFilePath;
LogFormattedMessage(ghInstance, IDS_ERROR_FILE_CREATE, lppArgs);
CloseHandle(hFile);
return FALSE;
}
WriteFile(hFile,
pCommands,
(lstrlen(pCommands) * sizeof(TCHAR)),
&dwNumWritten,
NULL);
if (dwNumWritten != (lstrlen(pCommands) * sizeof(TCHAR)))
{
#if SAMER_DBG
OutputDebugString(TEXT("Unable to write to Language Groups to muilang.txt\n"));
#endif
CloseHandle(hFile);
return (FALSE);
}
CloseHandle(hFile);
//
// Call the control panel regional-options applet, and wait for it to complete
//
//*STRSAFE* lstrcpy(szCmdLine, TEXT("rundll32 shell32,Control_RunDLL intl.cpl,, /f:\""));
hresult=StringCchPrintf(szCmdLine,ARRAYSIZE(szCmdLine),TEXT("\"%s\" shell32,Control_RunDLL intl.cpl,, /f:\""),szRunDllPath);
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
//*STRSAFE* lstrcat(szCmdLine, szFilePath);
hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), szFilePath);
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
// only pop up progress bar UI if we are showing UI "/g" param for intl.cpl dictates this
// also add a /D so that intl.cpl will not prompt for a source dialog if no UI is to be shown
if (!g_bNoUI)
{
//*STRSAFE* lstrcat(szCmdLine, TEXT("\"/g "f));
hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" /g"));
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
}
else
{
#ifdef MUI_MAGIC
//*STRSAFE* lstrcat(szCmdLine, TEXT("\" /D"));
hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" /D "));
// hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
#else
//*STRSAFE* lstrcat(szCmdLine, TEXT("\" /D"));
hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
// hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
#endif
}
// intl.cpl matches the UI font if /t is specified on the command line
if (g_bCmdMatchUIFont)
{
//*STRSAFE* lstrcat(szCmdLine, TEXT("/t "));
hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("/t "));
if (!SUCCEEDED(hresult))
{
DeleteFile(szFilePath);
return FALSE;
}
}
memset( &si, 0x00, sizeof(si));
si.cb = sizeof(STARTUPINFO);
if (!CreateProcess(NULL,
szCmdLine,
NULL,
NULL,
FALSE,
0L,
NULL,
NULL,
&si,
&pi))
{
lppArgs[0] = (LONG_PTR)szCmdLine;
LogFormattedMessage(ghInstance, IDS_ERROR_LAUNCH_INTLCPL, lppArgs);
DeleteFile(szFilePath);
return FALSE;
}
//
// Wait forever till intl.cpl terminates.
//
WaitForSingleObject(pi.hProcess, INFINITE);
//
// Close Handle
//
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
//
// Delete the File
//
DeleteFile(szFilePath);
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
//
// InstallLanguageGroups
//
// Checks whether a language group is needed to be installed or not. If
// any lang-group needs to be installed, then the routine will invoke
// the Regional-Options applet in unattended mode setup.
//
// Return:
// TURE if the operation succeeds. Otherwise FALSE.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InstallLanguageGroups(PINSTALL_LANG_GROUP pInstallLangGroup)
{
TCHAR pCommands[MAX_PATH];
int i, iCount = pInstallLangGroup->iCount;
BOOL bFirstTime=FALSE;
HRESULT hresult;
if (!pInstallLangGroup)
{
return FALSE;
}
//
// If nothing to do, then just return
//
if (0L == iCount)
{
return TRUE;
}
i = 0;
while (i < iCount)
{
if (!gpfnIsValidLanguageGroup(pInstallLangGroup->lgrpid[i], LGRPID_INSTALLED))
{
if (!bFirstTime)
{
bFirstTime = TRUE;
//*STRSAFE* wsprintf(pCommands, TEXT("LanguageGroup = %d\0"), pInstallLangGroup->lgrpid[i]);
hresult = StringCchPrintf(pCommands , ARRAYSIZE(pCommands), TEXT("LanguageGroup = %d\0"), pInstallLangGroup->lgrpid[i]);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
}
else
{
//*STRSAFE* wsprintf(&pCommands[lstrlen(pCommands)], TEXT(",%d\0"), pInstallLangGroup->lgrpid[i]);
hresult = StringCchPrintf(&pCommands[lstrlen(pCommands)] , ARRAYSIZE(pCommands) -lstrlen(pCommands) , TEXT(",%d\0"), pInstallLangGroup->lgrpid[i]);
if (!SUCCEEDED(hresult))
{
return FALSE;
}
}
}
i++;
};
if (!bFirstTime)
{
//
// There is no language group to be added.
return (FALSE);
}
return (RunRegionalOptionsApplet(pCommands));
}
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_RebootTheSystem
//
// This routine enables all privileges in the token, calls ExitWindowsEx
// to reboot the system, and then resets all of the privileges to their
// old state.
//
////////////////////////////////////////////////////////////////////////////
void Muisetup_RebootTheSystem(void)
{
HANDLE Token = NULL;
ULONG ReturnLength, Index;
PTOKEN_PRIVILEGES NewState = NULL;
PTOKEN_PRIVILEGES OldState = NULL;
BOOL Result;
Result = OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&Token );
if (Result)
{
ReturnLength = 4096;
NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
Result = (BOOL)((NewState != NULL) && (OldState != NULL));
if (Result)
{
Result = GetTokenInformation( Token, // TokenHandle
TokenPrivileges, // TokenInformationClass
NewState, // TokenInformation
ReturnLength, // TokenInformationLength
&ReturnLength ); // ReturnLength
if (Result)
{
//
// Set the state settings so that all privileges are enabled...
//
if (NewState->PrivilegeCount > 0)
{
for (Index = 0; Index < NewState->PrivilegeCount; Index++)
{
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
}
}
Result = AdjustTokenPrivileges( Token, // TokenHandle
FALSE, // DisableAllPrivileges
NewState, // NewState
ReturnLength, // BufferLength
OldState, // PreviousState
&ReturnLength ); // ReturnLength
if (Result)
{
ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG);
AdjustTokenPrivileges( Token,
FALSE,
OldState,
0,
NULL,
NULL );
}
}
}
}
if (NewState != NULL)
{
LocalFree(NewState);
}
if (OldState != NULL)
{
LocalFree(OldState);
}
if (Token != NULL)
{
CloseHandle(Token);
}
}
////////////////////////////////////////////////////////////////////////////
//
// CheckForReboot
//
// Check if we need to reboot the system, if a lang group is installed
//
// Return:
// TRUE if we need user to reboot, otherwise FALSE.
//
////////////////////////////////////////////////////////////////////////////
BOOL CheckForReboot(HWND hwnd, PINSTALL_LANG_GROUP pInstallLangGroup)
{
int nIDS,nMask=MB_YESNO | MB_ICONQUESTION;
if (!pInstallLangGroup)
{
return FALSE;
}
if (pInstallLangGroup->iCount || pInstallLangGroup->bFontLinkRegistryTouched || pInstallLangGroup->NotDeleted
|| g_bRemoveDefaultUI || g_bRemoveUserUI || g_bReboot)
{
if (g_bRemoveUserUI)
{
nIDS=IDS_MUST_REBOOT_STRING1;
nMask=MB_YESNO | MB_ICONWARNING;
}
else if (g_bRemoveDefaultUI)
{
nMask=MB_YESNO | MB_ICONWARNING;
nIDS=IDS_MUST_REBOOT_STRING2;
}
else
{
nIDS=IDS_REBOOT_STRING;
}
SetForegroundWindow(hwnd); // muisetup lost focus when it show reboot dialog so we force it as foreground window.
if (DoMessageBox(hwnd, nIDS, IDS_MAIN_TITLE, nMask) == IDYES)
{
Muisetup_RebootTheSystem();
}
return (TRUE);
}
return (FALSE);
}
////////////////////////////////////////////////////////////////////////////
//
// Following code are stolen from intl.cpl
//
// We want to enumulate all installed UI languages
//
////////////////////////////////////////////////////////////////////////////
DWORD_PTR TransNum(
LPTSTR lpsz)
{
DWORD dw = 0L;
TCHAR c;
if (!lpsz)
{
return dw;
}
while (*lpsz)
{
c = *lpsz++;
if (c >= TEXT('A') && c <= TEXT('F'))
{
c -= TEXT('A') - 0xa;
}
else if (c >= TEXT('0') && c <= TEXT('9'))
{
c -= TEXT('0');
}
else if (c >= TEXT('a') && c <= TEXT('f'))
{
c -= TEXT('a') - 0xa;
}
else
{
break;
}
dw *= 0x10;
dw += c;
}
return (dw);
}
BOOL MUIGetAllInstalledUILanguages()
{
pfnEnumUILanguages fnEnumUILanguages;
BOOL result = TRUE;
HINSTANCE hKernel32;
//
// Enumerate the installed UI languages.
//
g_UILanguageGroup.iCount = 0L;
hKernel32 = LoadLibrary(TEXT("kernel32.dll"));
fnEnumUILanguages = (pfnEnumUILanguages)GetProcAddress(hKernel32, "EnumUILanguagesW");
if (fnEnumUILanguages == NULL)
{
result = FALSE;
} else
{
fnEnumUILanguages(Region_EnumUILanguagesProc, 0, (LONG_PTR)&g_UILanguageGroup);
}
FreeLibrary(hKernel32);
return (result);
}
BOOL CALLBACK Region_EnumUILanguagesProc(
LPWSTR pwszUILanguage,
LONG_PTR lParam)
{
int Ctr = 0;
LGRPID lgrp;
PUILANGUAGEGROUP pUILangGroup = (PUILANGUAGEGROUP)lParam;
if ( (!pwszUILanguage) || (!pUILangGroup))
{
return FALSE;
}
LCID UILanguage = (LCID)TransNum( pwszUILanguage );
if (UILanguage)
{
while (Ctr < pUILangGroup->iCount)
{
if (pUILangGroup->lcid[Ctr] == UILanguage)
{
break;
}
Ctr++;
}
//
// Theoritically, we won't go over 64 language groups!
//
if ((Ctr == pUILangGroup->iCount) && (Ctr < MAX_UI_LANG_GROUPS))
{
pUILangGroup->lcid[Ctr] = UILanguage;
pUILangGroup->iCount++;
}
}
return (TRUE);
}
BOOL IsSpaceEnough(HWND hwndDlg,INT64 *ulSizeNeed,INT64 *ulSizeAvailable)
{
HWND hList;
LGRPID lgrpid[MAX_MUI_LANGUAGES];
LPTSTR lpszLcid;
int iIndex;
int i = 0;
int iCount=0,iArrayIndex=0;
PMUILANGINFO pMuiLangInfo;
BOOL bChked,bResult=TRUE;
INT64 ulTotalBytesRequired=0,ulSpaceAvailable;
TCHAR szWinDir[MAX_PATH];
BOOL bFELangpackAdded = FALSE;
ULARGE_INTEGER ulgiFreeBytesAvailableToCaller;
ULARGE_INTEGER ulgiTotalNumberOfBytes;
if ((!ulSizeNeed) || (!ulSizeAvailable))
{
return FALSE;
}
*ulSizeNeed=0;
*ulSizeAvailable=0;
hList=GetDlgItem(hwndDlg, IDC_LIST1);
iIndex = ListView_GetItemCount(hList);
while(i<iIndex)
{
bChked=ListView_GetCheckState(hList, i);
GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
lpszLcid = pMuiLangInfo->lpszLcid;
//
// Install required
//
if (bChked && !IsInstalled(lpszLcid) && HaveFiles(lpszLcid))
{
if (!gpfnIsValidLanguageGroup(pMuiLangInfo->lgrpid, LGRPID_INSTALLED))
{
for(iArrayIndex=0;iArrayIndex < iCount;iArrayIndex++)
{
if (lgrpid[iArrayIndex]==pMuiLangInfo->lgrpid)
break;
}
if(iArrayIndex == iCount)
{
if (IS_FE_LANGPACK(pMuiLangInfo->lcid))
{
if (!bFELangpackAdded)
{
ulTotalBytesRequired+=pMuiLangInfo->ulLPKSize;
bFELangpackAdded = TRUE;
}
}
else
{
ulTotalBytesRequired+=pMuiLangInfo->ulLPKSize;
}
lgrpid[iCount]= pMuiLangInfo->lgrpid;
iCount++;
}
}
ulTotalBytesRequired+=pMuiLangInfo->ulUISize;
}
// Uninstall required
if (!bChked && IsInstalled(lpszLcid))
{
ulTotalBytesRequired-=pMuiLangInfo->ulUISize;
}
i++;
}
//
// Let's check available disk space of system drive
//
pfnGetWindowsDir( szWinDir, MAX_PATH);
szWinDir[3]=TEXT('\0');
if (GetDiskFreeSpaceEx(szWinDir,
&ulgiFreeBytesAvailableToCaller,
&ulgiTotalNumberOfBytes,
NULL))
{
ulSpaceAvailable= ulgiFreeBytesAvailableToCaller.QuadPart;
if ( ulSpaceAvailable < ulTotalBytesRequired )
{
*ulSizeNeed =ulTotalBytesRequired;
*ulSizeAvailable=ulSpaceAvailable;
bResult=FALSE;
}
}
return bResult;
}
void ExitFromOutOfMemory()
{
LONG_PTR lppArgs[1];
lppArgs[0] = (LONG_PTR)GetLastError();
DoMessageBox(NULL, IDS_OUT_OF_MEMORY, IDS_MAIN_TITLE, MB_ICONEXCLAMATION | MB_OK);
LogFormattedMessage(ghInstance, IDS_OUT_OF_MEMORY_L, lppArgs);
ExitProcess(1);
}
////////////////////////////////////////////////////////////////////////////
//
// Call the kernel to notify it that a new language is being added or
// removed
//
////////////////////////////////////////////////////////////////////////////
void NotifyKernel(
LPTSTR LangList,
ULONG Flags
)
{
HANDLE Handle;
WMILANGUAGECHANGE LanguageChange;
ULONG ReturnSize;
BOOL IoctlSuccess;
HRESULT hresult;
if ((LangList != NULL) &&
(*LangList != 0))
{
Handle = CreateFile(WMIAdminDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (Handle != INVALID_HANDLE_VALUE)
{
while (*LangList != 0)
{
memset(&LanguageChange, 0, sizeof(LanguageChange));
//*STRSAFE* _tcscpy(LanguageChange.Language, LangList);
hresult = StringCchCopy(LanguageChange.Language , MAX_LANGUAGE_SIZE, LangList);
if (!SUCCEEDED(hresult))
{
CloseHandle(Handle);
return ;
}
LanguageChange.Flags = Flags;
IoctlSuccess = DeviceIoControl(Handle,
IOCTL_WMI_NOTIFY_LANGUAGE_CHANGE,
&LanguageChange,
sizeof(LanguageChange),
NULL,
0,
&ReturnSize,
NULL);
#if ALANWAR_DBG
{
WCHAR Buf[256];
//*STRSAFE* wsprintf(Buf, L"MUISetup: Notify Lang change -> %d for %ws\n", GetLastError(), LangList);
hresult = StringCchPrintfW(Buf , ARRAYSIZE(Buf), L"MUISetup: Notify Lang change -> %d for %ws\n", GetLastError(), LangList);
if (!SUCCEEDED(hresult))
{
CloseHandle(Handle);
return ;
}
OutputDebugStringW(Buf);
}
#endif
while (*LangList++ != 0) ;
}
CloseHandle(Handle);
}
}
}
//
// Query MUI registry setting
//
BOOL CheckMUIRegSetting(DWORD dwFlag)
{
BOOL bRet = FALSE;
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, KEY_READ, &hKey))
{
DWORD dwValue;
DWORD dwSize = sizeof(dwValue);
DWORD dwType;
if (ERROR_SUCCESS ==
RegQueryValueEx(hKey,
(dwFlag & MUI_MATCH_UIFONT)? REGSTR_VALUE_MATCH_UIFONT : REGSTR_VALUE_MATCH_LOCALE,
0, &dwType, (LPBYTE)&dwValue, &dwSize))
{
bRet = (BOOL) dwValue;
}
RegCloseKey(hKey);
}
return bRet;
}
//
// Set MUI registry setting
//
BOOL SetMUIRegSetting(DWORD dwFlag, BOOL bEnable)
{
BOOL bRet = FALSE;
HKEY hKey;
if (ERROR_SUCCESS ==
RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, &hKey, NULL))
{
DWORD dwValue = (DWORD) bEnable;
if (ERROR_SUCCESS ==
RegSetValueEx(hKey,
(dwFlag & MUI_MATCH_UIFONT)? REGSTR_VALUE_MATCH_UIFONT : REGSTR_VALUE_MATCH_LOCALE,
0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)))
{
bRet = TRUE;
}
RegCloseKey(hKey);
}
return bRet;
}
//
// Delete MUI registry setting
//
BOOL DeleteMUIRegSetting()
{
BOOL bRet = TRUE;
HKEY hKey;
TCHAR tcMessage[BUFFER_SIZE];
if (ERROR_SUCCESS ==RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, KEY_ALL_ACCESS, &hKey))
{
DWORD dwValue;
DWORD dwSize = sizeof(dwValue);
DWORD dwType;
if (ERROR_SUCCESS ==
RegQueryValueEx(hKey,
REGSTR_VALUE_MATCH_UIFONT,
0, &dwType, (LPBYTE)&dwValue, &dwSize))
{
if (RegDeleteValue(hKey, REGSTR_VALUE_MATCH_UIFONT) != ERROR_SUCCESS)
{
wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: DeleteMUIRegSetting: WARNING - Failed to delete regkey HKLM\\%s regvalue %s"), REGSTR_MUI_SETTING,REGSTR_VALUE_MATCH_UIFONT);
LogMessage(tcMessage);
bRet = FALSE;
}
}
dwSize = sizeof(dwValue);
if (ERROR_SUCCESS ==
RegQueryValueEx(hKey,
REGSTR_VALUE_MATCH_LOCALE,
0, &dwType, (LPBYTE)&dwValue, &dwSize))
{
if (RegDeleteValue(hKey, REGSTR_VALUE_MATCH_LOCALE) != ERROR_SUCCESS)
{
wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: DeleteMUIRegSetting: WARNING - Failed to delete regkey HKLM\\%s regvalue %s"), REGSTR_MUI_SETTING,REGSTR_VALUE_MATCH_LOCALE);
LogMessage(tcMessage);
bRet = FALSE;
}
}
RegCloseKey(hKey);
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////
//
// DeleteRegTree
//
// This deletes all subkeys under a specific key.
//
// Note: The code makes no attempt to check or recover from partial
// deletions.
//
// A registry key that is opened by an application can be deleted
// without error by another application. This is by design.
//
////////////////////////////////////////////////////////////////////////////
DWORD DeleteRegTree(
HKEY hStartKey,
LPTSTR pKeyName)
{
DWORD dwRtn, dwSubKeyLength;
LPTSTR pSubKey = NULL;
TCHAR szSubKey[REGSTR_MAX_VALUE_LENGTH]; // (256) this should be dynamic.
HKEY hKey;
//
// Do not allow NULL or empty key name.
//
if (pKeyName && lstrlen(pKeyName))
{
if ((dwRtn = RegOpenKeyEx( hStartKey,
pKeyName,
0,
KEY_ENUMERATE_SUB_KEYS | DELETE,
&hKey )) == ERROR_SUCCESS)
{
while (dwRtn == ERROR_SUCCESS)
{
dwSubKeyLength = REGSTR_MAX_VALUE_LENGTH;
dwRtn = RegEnumKeyEx( hKey,
0, // always index zero
szSubKey,
&dwSubKeyLength,
NULL,
NULL,
NULL,
NULL );
if (dwRtn == ERROR_NO_MORE_ITEMS)
{
dwRtn = RegDeleteKey(hStartKey, pKeyName);
break;
}
else if (dwRtn == ERROR_SUCCESS)
{
dwRtn = DeleteRegTree(hKey, szSubKey);
}
}
RegCloseKey(hKey);
}
else if (dwRtn == ERROR_FILE_NOT_FOUND)
{
dwRtn = ERROR_SUCCESS;
}
}
else
{
dwRtn = ERROR_BADKEY;
}
return (dwRtn);
}
////////////////////////////////////////////////////////////////////////////////////
//
// InstallExternalComponents
//
//
// Return:
// TURE if the operation succeeds. Otherwise FALSE.
//
////////////////////////////////////////////////////////////////////////////////////
BOOL InstallExternalComponents(LPTSTR Languages)
{
BOOL bRet = TRUE;
TCHAR lpMessage[BUFFER_SIZE];
if (! Languages)
{
return FALSE;
}
//
// call WBEM API to mofcompile MUI MFL's for each language
//
if (!MofCompileLanguages(Languages))
{
//
// LOG: Error mofcompiling
//
LoadString(ghInstance, IDS_MOFCOMPILE_L, lpMessage, ARRAYSIZE(lpMessage)-1);
LogMessage(lpMessage);
bRet = FALSE;
}
if (bRet)
{
//
// Inform kernel that new languages have been added
//
NotifyKernel(Languages,
WMILANGUAGECHANGE_FLAG_ADDED);
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////
//
// UninstallExternalComponents
//
////////////////////////////////////////////////////////////////////////////////////
VOID UninstallExternalComponents(LPTSTR Languages)
{
if (!Languages)
{
return ;
}
//
// Inform kernel that new languages have been added
//
NotifyKernel(Languages,
WMILANGUAGECHANGE_FLAG_REMOVED);
}