using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Ameliorated.ConsoleUtils; using Microsoft.Dism; using Microsoft.Win32; using static Ameliorated.ConsoleUtils.Menu; namespace amecs.Actions { public class Languages { public static bool ShowMenu() { while (true) { Program.Frame.Clear(); var mainMenu = new Ameliorated.ConsoleUtils.Menu() { Choices = { true ? new Menu.MenuItem("Change Display Language", new Func(ShowDisplayMenu)) { IsEnabled = false, SecondaryText = "[Not Supported]", SecondaryTextForeground = ConsoleColor.Red, PrimaryTextForeground = ConsoleColor.DarkGray } : new Menu.MenuItem("Change Display Language", new Func(ShowDisplayMenu)), new Menu.MenuItem("Add Keyboard Language", new Func(ShowAddKeyboardLanguageMenu)), new Menu.MenuItem("Remove Keyboard Language", new Func(ShowRemoveKeyboardLanguageMenu)), Globals.WinVer >= 22000 ? new Menu.MenuItem("Install Language Pack", new Func(ShowLanguagePackMenu)) { IsEnabled = false, SecondaryText = "[Not Supported]", SecondaryTextForeground = ConsoleColor.Red, PrimaryTextForeground = ConsoleColor.DarkGray } : new Menu.MenuItem("Install Language Pack", new Func(ShowLanguagePackMenu)), Globals.WinVer >= 22000 ? new Menu.MenuItem("Uninstall Language Pack", new Func(ShowRemoveLanguagePackMenu)) { IsEnabled = false, SecondaryText = "[Not Supported]", SecondaryTextForeground = ConsoleColor.Red, PrimaryTextForeground = ConsoleColor.DarkGray } : new Menu.MenuItem("Uninstall Language Pack", new Func(ShowRemoveLanguagePackMenu)), Menu.MenuItem.Blank, new Menu.MenuItem("Return to Menu", null), new Menu.MenuItem("Exit", new Func(Globals.Exit)) }, SelectionForeground = ConsoleColor.Green }; Func result; try { mainMenu.Write(); var res = mainMenu.Load(); if (res == null) return true; result = (Func)res; } catch (Exception e) { Console.WriteLine(e); Console.ReadLine(); return false; } try { result.Invoke(); } catch (Exception e) { ConsoleTUI.ShowErrorBox("Error while loading a menu: " + e.ToString(), null); } } } private static bool ShowDisplayMenu() => ShowLanguageMenu(true); private static bool ShowLanguagePackMenu() => ShowLanguageMenu(false); private static List currentLanguagePacks; public static bool ShowLanguageMenu(bool display) { /* if (display) { try { var deskKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\Desktop"); var pendingLang = ((string[])deskKey.GetValue("PreferredUILanguagesPending")).First(); ConsoleTUI.OpenFrame.WriteCentered("Checking languages"); var indicator = new ConsoleUtils.LoadingIndicator(true); Thread.Sleep(50); indicator.Dispose(); Console.WriteLine(); ConsoleTUI.OpenFrame.Close("A language change is currently pending.\r\nYou must restart before continuing.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } catch {} } */ List displayItems = new List(LanguagePackItems); if (!display) { DismApi.Initialize(DismLogLevel.LogErrors); DismPackageCollection packages; using (var session = DismApi.OpenOnlineSession()) { packages = DismApi.GetPackages(session); session.Close(); } DismApi.Shutdown(); currentLanguagePacks = new List(packages.Where(x => x.PackageName.StartsWith("Microsoft-Windows-Client-LanguagePack-Package")).Select(x => x.PackageName)); } foreach (var menuItem in new List(displayItems)) { var tag = ((string)menuItem.ReturnValue).Split('|').First(); string activeLang = null; string pendingLang = null; try { var deskKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\Desktop"); activeLang = ((string[])deskKey.GetValue("PreferredUILanguages")).First(); pendingLang = ((string[])deskKey.GetValue("PreferredUILanguagesPending")).First(); } catch { } if (display && tag == pendingLang && activeLang != pendingLang) { var clone = menuItem.Clone(); clone.IsEnabled = false; clone.PrimaryTextForeground = ConsoleColor.DarkGray; clone.SecondaryText = "[Pending Restart]"; clone.SecondaryTextForeground = ConsoleColor.Yellow; displayItems.ReplaceItem(menuItem, clone); } if (display && tag == activeLang && (activeLang == pendingLang || pendingLang == null)) { var clone = menuItem.Clone(); clone.IsEnabled = false; clone.PrimaryTextForeground = ConsoleColor.DarkGray; clone.SecondaryText = "[Current]"; clone.SecondaryTextForeground = ConsoleColor.Yellow; displayItems.ReplaceItem(menuItem, clone); } if (!display) { if (currentLanguagePacks.Any(x => x.Contains('~' + tag + '~'))) { var clone = menuItem.Clone(); clone.IsEnabled = false; clone.PrimaryTextForeground = ConsoleColor.DarkGray; clone.SecondaryText = "[Installed]"; clone.SecondaryTextForeground = ConsoleColor.Yellow; displayItems.ReplaceItem(menuItem, clone); } } } var result = amecs.ShowDefaultMenu(displayItems.ToList()); if (result.GetType().Name.StartsWith("Func")) return ((Func)result).Invoke(); var languageTag = ((string)result).Split('|').First(); var downloadAmount = int.Parse(((string)result).Split('|').Last(), CultureInfo.InvariantCulture); if (!display) { return InstallLanguagePack(downloadAmount, languageTag); } else { return ChangeDisplayLanguage(downloadAmount, languageTag); } } private static List CurrentLanguages; public static bool ShowAddKeyboardLanguageMenu() { while (true) { CurrentLanguages = new List(); try { var langsKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\International\\User Profile"); foreach (var langKey in langsKey.GetSubKeyNames()) { CurrentLanguages.AddRange(langsKey.OpenSubKey(langKey).GetValueNames().Where(x => x.Contains(':'))); } } catch { } List displayItems = new List(KeyboardLanguageItems); foreach (var menuItem in displayItems.Where(x => x.ReturnValue.GetType().Name == "String").ToList()) { if (CurrentLanguages.Contains((string)menuItem.ReturnValue, StringComparer.InvariantCultureIgnoreCase)) { var clone = menuItem.Clone(); clone.IsEnabled = false; clone.PrimaryTextForeground = ConsoleColor.DarkGray; clone.SecondaryText = "[Installed]"; clone.SecondaryTextForeground = ConsoleColor.Yellow; displayItems.ReplaceItem(menuItem, clone); } } var result = amecs.ShowDefaultMenu(displayItems); if (result.GetType().Name.StartsWith("Func")) return ((Func)result).Invoke(); if (result.GetType().Name == "String") { return AddKeyboardLanguage((string)result); } else { var subDisplayItems = ((MenuItem[])result).ToList(); foreach (var menuItem in subDisplayItems) { if (CurrentLanguages.Contains((string)menuItem.ReturnValue, StringComparer.InvariantCultureIgnoreCase)) { menuItem.IsEnabled = false; menuItem.PrimaryTextForeground = ConsoleColor.DarkGray; menuItem.SecondaryText = "[Installed]"; menuItem.SecondaryTextForeground = ConsoleColor.Yellow; } else { menuItem.IsEnabled = true; menuItem.PrimaryTextForeground = null; menuItem.SecondaryText = null; menuItem.SecondaryTextForeground = null; } } var subResult = amecs.ShowDefaultMenu(subDisplayItems); if (subResult.GetType().Name.StartsWith("Func")) { ((Func)subResult).Invoke(); continue; } return AddKeyboardLanguage((string)subResult); } } } public static bool AddKeyboardLanguage(string tip) { var choice = new ChoicePrompt() { Text = "Make default keyboard language? (Y/N): " }.Start(); if (!choice.HasValue) return true; bool makeDefault = choice == 0; try { ConsoleTUI.OpenFrame.WriteCentered("\r\nAdding keyboard language"); using (new ConsoleUtils.LoadingIndicator(true)) { var result = NSudo.RunProcessAsUser(NSudo.GetUserToken(), "PowerShell.exe", makeDefault ? $"-NoP -C \"$List=Get-WinUserLanguageList;" + $"$List[0].InputMethodTips.Add('{tip}');" + $"Set-WinUserLanguageList $List -Force;" + $"Set-WinDefaultInputMethodOverride -InputTip '{tip}'\"" : $"-NoP -C \"$List=Get-WinUserLanguageList;" + $"$List[0].InputMethodTips.Add('{tip}');" + $"Set-WinUserLanguageList $List -Force\""); if (result == null) { throw new Exception("Could not start user PowerShell process."); } if (result > 0) { throw new Exception("PowerShell exited with a non-zero exitcode."); } } } catch (Exception e) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } Console.WriteLine(); ConsoleTUI.OpenFrame.Close($"Keyboard language added successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return true; } [StructLayout(LayoutKind.Sequential)] public struct COORD { public short X; public short Y; public COORD(short X, short Y) { this.X = X; this.Y = Y; } }; [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, StringBuilder lpCharacter, uint nLength, COORD dwWriteCoord, out uint lpNumberOfCharsWritten); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GetStdHandle(int nStdHandle); private static bool InstallLanguagePack(int downloadAmount, string language) => InstallLanguage(downloadAmount, language, true); private static bool InstallLanguage(int downloadAmount, string language, bool finalize) { var downloadFolder = Directory.Exists(Path.Combine(Globals.UserFolder, "Desktop")) ? Path.Combine(Globals.UserFolder, "Desktop") : Environment.GetEnvironmentVariable("TEMP"); var file = "LangPacks-" + new Random().Next(0, 9999); try { try { DriveInfo drive = DriveInfo.GetDrives().First(x => x.Name == Environment.GetEnvironmentVariable("SYSTEMDRIVE") + "\\"); if (drive.AvailableFreeSpace < downloadAmount * 2.3) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("There is not enough available space on the system drive.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } } catch { } string amountString = "0"; if (downloadAmount == 2480000) amountString = "2.5"; if (downloadAmount == 2900000) amountString = "2.9"; if (downloadAmount == 3230000) amountString = "3.2"; var choice = new ChoicePrompt() { Text = $"A ~{amountString}GB Language Packs ISO must be downloaded\r\nContinue? (Y/N): " }.Start(); if (choice == null || choice == 1) return false; if (!amecs.IsInternetAvailable()) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("An internet connection is required for this action.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } var sevenZip = ExistsInPath("7z.exe"); sevenZip = sevenZip == null ? File.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\7-Zip\7z.exe")) ? Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\7-Zip\7z.exe") : null : sevenZip; var choco = ExistsInPath("choco.exe"); choco = choco == null ? File.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\chocolatey\choco.exe")) ? Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\chocolatey\choco.exe") : null : choco; if (String.IsNullOrEmpty(sevenZip) && String.IsNullOrEmpty(choco)) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("7zip or Chocolatey must be installed for this action.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } bool wasMissing = false; if (String.IsNullOrEmpty(sevenZip)) { wasMissing = true; ConsoleTUI.OpenFrame.WriteCentered("\r\nInstalling 7zip"); using (new ConsoleUtils.LoadingIndicator(true)) { var proc = new Process(); var startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = "install -y --force --allow-empty-checksums 7zip", FileName = choco, }; proc.StartInfo = startInfo; proc.Start(); proc.WaitForExit(); } sevenZip = ExistsInPath("7z.exe"); sevenZip = sevenZip == null ? File.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\7-Zip\7z.exe")) ? Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\7-Zip\7z.exe") : null : sevenZip; if (sevenZip == null) { ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling 7zip"); using (new ConsoleUtils.LoadingIndicator(true)) { var proc = new Process(); var startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = "uninstall 7zip -y --force-dependencies --allow-empty-checksums", FileName = choco, }; proc.StartInfo = startInfo; proc.Start(); proc.WaitForExit(); } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Could not detect 7zip.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } } try { ConsoleTUI.OpenFrame.WriteCenteredLine("\r\nDownload progress"); using (WebClientEx wc = new WebClientEx(0, (long)downloadAmount * 1000)) { var stdout = GetStdHandle(-11); var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); wc.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e) { var currentHashTags = (int)Math.Ceiling(Math.Min(((double)e.ProgressPercentage / 100) * maxHashTags, maxHashTags)); var spaces = maxHashTags - currentHashTags + (4 - e.ProgressPercentage.ToString().Length); var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + e.ProgressPercentage + "%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); }; var task = wc.DownloadFileTaskAsync(new Uri("https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_CLIENTLANGPACKDVD_OEM_MULTI.iso"), Path.Combine(downloadFolder, file + ".ISO")); task.Wait(); Thread.Sleep(100); var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); } ConsoleTUI.OpenFrame.WriteCentered("\r\n\r\nExtracting ISO"); using (new ConsoleUtils.LoadingIndicator(true)) { var proc = new Process(); var startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = $@"e -y -o""{Path.Combine(downloadFolder, file)}"" ""{Path.Combine(downloadFolder, file + ".ISO")}"" x64\langpacks\*.cab", FileName = sevenZip, }; proc.StartInfo = startInfo; proc.Start(); proc.WaitForExit(); } try { File.Delete(Path.Combine(downloadFolder, file + ".ISO")); } catch { } } catch (Exception e) { try { if (wasMissing) { ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling 7zip"); using (new ConsoleUtils.LoadingIndicator(true)) { var proc = new Process(); var startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = "uninstall 7zip -y --force-dependencies --allow-empty-checksums", FileName = choco, }; proc.StartInfo = startInfo; proc.Start(); proc.WaitForExit(); } } } catch { } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } if (wasMissing) { ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling 7zip"); using (new ConsoleUtils.LoadingIndicator(true)) { var proc = new Process(); var startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = "uninstall 7zip -y --force-dependencies --allow-empty-checksums", FileName = choco, }; proc.StartInfo = startInfo; proc.Start(); proc.WaitForExit(); } } var cab = Path.Combine(downloadFolder, file, $"Microsoft-Windows-Client-Language-Pack_x64_{language}.cab"); if (!File.Exists(cab)) { try { Directory.Delete(Path.Combine(downloadFolder, file)); } catch { } throw new Exception("Extraction failed."); } ConsoleTUI.OpenFrame.WriteCentered("\r\nInstalling language pack"); var topCache = Console.CursorTop; var leftCache = Console.CursorLeft; Console.WriteLine(); bool inProgress = false; try { using (var indicator = new ConsoleUtils.LoadingIndicator(true)) { DismApi.Initialize(DismLogLevel.LogErrors); using (var session = DismApi.OpenOnlineSession()) { var stdout = GetStdHandle(-11); bool indicatorStopped = false; var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); DismApi.AddPackage(session, cab, false, true, delegate(DismProgress progress) { inProgress = true; if (!indicatorStopped) { indicator.Stop(); Console.SetCursorPosition(leftCache, topCache); Console.WriteLine(" "); } indicatorStopped = true; var progressPerc = progress.Current / 10; var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPerc / 100) * maxHashTags, maxHashTags)); var spaces = maxHashTags - currentHashTags + (4 - progressPerc.ToString().Length); var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPerc + "%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)topCache), out throwaway); inProgress = false; }); session.Close(); Thread.Sleep(100); var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)topCache), out throwaway); } DismApi.Shutdown(); } } catch (Exception e) { while (inProgress) { Thread.Sleep(50); } try { Directory.Delete(Path.Combine(downloadFolder, file), true); } catch { } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("DISM error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } Directory.Delete(Path.Combine(downloadFolder, file), true); } catch (Exception e) { try { Directory.Delete(Path.Combine(downloadFolder, file), true); } catch { } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } if (finalize) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Language pack installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); } return true; } public static string ExistsInPath(string fileName) { if (File.Exists(fileName)) return fileName; var values = Environment.GetEnvironmentVariable("PATH"); foreach (var path in values.Split(Path.PathSeparator).Where(x => !x.Contains("chocolatey\\bin"))) { var fullPath = Path.Combine(path, fileName); if (File.Exists(fullPath)) return fullPath; if (!fileName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) && File.Exists(fullPath + ".exe")) return fullPath + ".exe"; } return null; } public static bool ShowRemoveKeyboardLanguageMenu() { CurrentLanguages = new List(); try { var langsKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\International\\User Profile"); foreach (var langKey in langsKey.GetSubKeyNames()) { CurrentLanguages.AddRange(langsKey.OpenSubKey(langKey).GetValueNames().Where(x => x.Contains(':'))); } } catch { throw new Exception("Could not fetch installed keyboard languages.\r\n"); } List displayItems = new List(); foreach (var menuItem in KeyboardLanguageItems.Where(x => x.ReturnValue.GetType().Name == "String")) { if (CurrentLanguages.Contains((string)menuItem.ReturnValue, StringComparer.InvariantCultureIgnoreCase)) { displayItems.Add(menuItem); } } foreach (var menuItemList in KeyboardLanguageItems.Where(x => x.ReturnValue.GetType().Name != "String").Select(x => x.ReturnValue)) { var subDisplayItems = ((MenuItem[])menuItemList).ToList(); foreach (var subMenuItem in subDisplayItems) { if (CurrentLanguages.Contains((string)subMenuItem.ReturnValue, StringComparer.InvariantCultureIgnoreCase)) { displayItems.Add(subMenuItem); } } } var result = amecs.ShowDefaultMenu(displayItems); if (result.GetType().Name.StartsWith("Func")) return ((Func)result).Invoke(); return RemoveKeyboardLanguage((string)result); } private static bool RemoveKeyboardLanguage(string language) { ConsoleTUI.OpenFrame.WriteCentered("Removing keyboard language"); try { using (new ConsoleUtils.LoadingIndicator(true)) { StringBuilder reAddCommand = new StringBuilder(""); foreach (var tag in CurrentLanguages.Where(x => !x.Equals(language, StringComparison.InvariantCultureIgnoreCase))) { reAddCommand.Append($@";$List[0].InputMethodTips.Add('{tag}')"); } var result = NSudo.RunProcessAsUser(NSudo.GetUserToken(), "PowerShell.exe", $"-NoP -C \"$Tag=(Get-WinUserLanguageList)[0].LanguageTag;" + $"$List = New-WinUserLanguageList $Tag" + $"{reAddCommand.ToString()};" + $"Set-WinUserLanguageList $List -Force\""); if (result == null) { throw new Exception("Could not start user PowerShell process."); } if (result > 0) { throw new Exception("PowerShell exited with a non-zero exitcode."); } } } catch (Exception e) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } CurrentLanguages = new List(); var langsKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\International\\User Profile"); foreach (var langKey in langsKey.GetSubKeyNames()) { CurrentLanguages.AddRange(langsKey.OpenSubKey(langKey).GetValueNames().Where(x => x.Contains(':'))); } if (CurrentLanguages.Contains(language, StringComparer.InvariantCultureIgnoreCase)) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Keyboard language could not be removed. If it is the\r\nactive UI language, this is normal.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Keyboard language removed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return true; } public static bool ShowRemoveLanguagePackMenu() { DismApi.Initialize(DismLogLevel.LogErrors); DismPackageCollection packages; using (var session = DismApi.OpenOnlineSession()) { packages = DismApi.GetPackages(session); session.Close(); } DismApi.Shutdown(); currentLanguagePacks = new List(packages.Where(x => x.PackageName.StartsWith("Microsoft-Windows-Client-LanguagePack-Package")).Select(x => x.PackageName)); List displayItems = new List(); foreach (var menuItem in LanguagePackItems) { var tag = ((string)menuItem.ReturnValue).Split('|').First(); var pkg = currentLanguagePacks.FirstOrDefault(x => x.Contains('~' + tag + '~')); if (pkg != null) { var clone = menuItem.Clone(); string activeLang = null; try { var deskKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\Desktop"); activeLang = ((string[])deskKey.GetValue("PreferredUILanguages")).First(); } catch { } if (activeLang == tag) { clone.IsEnabled = false; clone.PrimaryTextForeground = ConsoleColor.DarkGray; clone.SecondaryText = "[UI Language]"; clone.SecondaryTextForeground = ConsoleColor.Yellow; } clone.ReturnValue = pkg; displayItems.Add(clone); } } var result = amecs.ShowDefaultMenu(displayItems.ToList()); if (result.GetType().Name.StartsWith("Func")) return ((Func)result).Invoke(); return RemoveLanguagePack((string)result); } private static bool RemoveLanguagePack(string package) { ConsoleTUI.OpenFrame.WriteCentered("Removing language pack"); var topCache = Console.CursorTop; var leftCache = Console.CursorLeft; bool inProgress = false; try { using (var indicator = new ConsoleUtils.LoadingIndicator(true)) { DismApi.Initialize(DismLogLevel.LogErrors); using (var session = DismApi.OpenOnlineSession()) { var stdout = GetStdHandle(-11); bool indicatorStopped = false; var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); DismApi.RemovePackageByName(session, package, delegate(DismProgress progress) { inProgress = true; if (!indicatorStopped) { indicator.Stop(); Console.SetCursorPosition(leftCache, topCache); Console.WriteLine(" "); } indicatorStopped = true; var progressPerc = progress.Current / 10; var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPerc / 100) * maxHashTags, maxHashTags)); var spaces = maxHashTags - currentHashTags + (4 - progressPerc.ToString().Length); var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPerc + "%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); inProgress = false; }); session.Close(); Thread.Sleep(100); var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); } DismApi.Shutdown(); } } catch (Exception e) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("DISM error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Language pack removed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return true; } public static bool ChangeDisplayLanguage(int downloadAmount, string language) { DismApi.Initialize(DismLogLevel.LogErrors); DismPackageCollection packages; using (var session = DismApi.OpenOnlineSession()) { packages = DismApi.GetPackages(session); session.Close(); } DismApi.Shutdown(); currentLanguagePacks = new List(packages.Where(x => x.PackageName.StartsWith("Microsoft-Windows-Client-LanguagePack-Package")).Select(x => x.PackageName)); if (!currentLanguagePacks.Any(x => x.Contains('~' + language + '~'))) { if (!InstallLanguage(downloadAmount, language, false)) return false; ConsoleTUI.OpenFrame.WriteLine(); ConsoleTUI.OpenFrame.WriteLine(); } var choice = new ChoicePrompt() { Text = "Make default keyboard language? (Y/N): " }.Start(); if (!choice.HasValue) return true; bool makeDefault = choice == 0; string previousDefault = null; if (!makeDefault) { try { var langsKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\International\\User Profile"); try { previousDefault = (string)langsKey.GetValue("InputMethodOverride");} catch {} if (previousDefault == null) { string activeLang = null; try { var deskKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\Desktop"); activeLang = ((string[])deskKey.GetValue("PreferredUILanguages")).First(); } catch { } var keyName = langsKey.GetSubKeyNames().FirstOrDefault(x => x == activeLang); if (keyName == null) keyName = langsKey.GetSubKeyNames().FirstOrDefault(x => x.StartsWith(activeLang.Split('-').First())); var langKey = langsKey.OpenSubKey(keyName); foreach (var langValue in langKey.GetValueNames().Where(x => x.Contains(':'))) { if ((int)langKey.GetValue(langValue) == 1) previousDefault = langValue; } } } catch (Exception e) { } } CurrentLanguages = new List(); try { var langsKey = Registry.Users.OpenSubKey(Globals.UserSID + "\\Control Panel\\International\\User Profile"); foreach (var langKey in langsKey.GetSubKeyNames()) { CurrentLanguages.AddRange(langsKey.OpenSubKey(langKey).GetValueNames().Where(x => x.Contains(':'))); } } catch { } ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting language"); try { using (new ConsoleUtils.LoadingIndicator(true)) { try { Process proc = new Process(); proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; proc.StartInfo.FileName = "PowerShell.exe"; proc.StartInfo.Arguments = $"-NoP -C \"Set-WinSystemLocale {language}\""; proc.Start(); proc.WaitForExit(); } catch { } StringBuilder reAddCommand = new StringBuilder(""); foreach (var tag in CurrentLanguages) { reAddCommand.Append($@";$List[0].InputMethodTips.Add('{tag}')"); } var result = NSudo.RunProcessAsUser(NSudo.GetUserToken(), "PowerShell.exe", previousDefault == null ? $"-NoP -C \"$List = New-WinUserLanguageList {language}" + $"{reAddCommand.ToString()};" + $"Set-WinUserLanguageList $List -Force;" + $"Set-WinDefaultInputMethodOverride\"" : $"-NoP -C \"$List = New-WinUserLanguageList {language}" + $"{reAddCommand.ToString()};" + $"Set-WinUserLanguageList $List -Force;" + $"Set-WinDefaultInputMethodOverride '{previousDefault}'\"" ); if (result == null) { throw new Exception("Could not start user PowerShell process."); } if (result > 0) { throw new Exception("PowerShell exited with a non-zero exitcode."); } new Reg.Value() { KeyName = "HKU\\" + Globals.UserSID + "\\Control Panel\\Desktop", ValueName = "PreferredUILanguagesPending", Data = new[] { language }, Type = Reg.RegistryValueType.REG_MULTI_SZ }.Apply(); } } catch (Exception e) { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } Console.WriteLine(); if ((int?)ConsoleTUI.OpenFrame.Close("Display language changed to " + language, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { TextForeground = ConsoleColor.Yellow, Text = "Restart to apply changes? (Y/N): " }) == 0) amecs.RestartWindows(false, true); return true; } private static readonly MenuItem[] LanguagePackItems = new[] { new MenuItem("Arabic (ar-SA)", "ar-SA|2480000"), new MenuItem("Bulgarian (bg-BG)", "bg-BG|2480000"), new MenuItem("Chineese [Simplified] (zh-CN)", "zh-CN|3230000"), new MenuItem("Chineese [Traditional] (zh-TW)", "zh-TW|3230000"), new MenuItem("Croatian (hr-HR)", "hr-HR|2900000"), new MenuItem("Czech (cs-CZ)", "cs-CZ|2480000"), new MenuItem("Danish (da-DK)", "da-DK|2480000"), new MenuItem("Dutch (nl-NL)", "nl-NL|2900000"), new MenuItem("English [US] (en-US)", "en-US|2480000"), new MenuItem("English [UK] (en-GB)", "en-GB|2480000"), new MenuItem("Estonian (et-EE)", "et-EE|2480000"), new MenuItem("Finnish (fi-FI)", "fi-FI|2480000"), new MenuItem("French [Canada] (fr-CA)", "fr-CA|2480000"), new MenuItem("French [France] (fr-FR)", "fr-FR|2900000"), new MenuItem("German (de-DE)", "de-DE|2480000"), new MenuItem("Greek (el-GR)", "el-GR|2480000"), new MenuItem("Hebrew (he-IL)", "he-IL|2900000"), new MenuItem("Hungarian (hu-HU)", "hu-HU|2900000"), new MenuItem("Italian (it-IT)", "it-IT|2900000"), new MenuItem("Japanese (ja-JP)", "ja-JP|2900000"), new MenuItem("Korean (ko-KR)", "ko-KR|2900000"), new MenuItem("Latvian (lv-LV)", "lv-LV|2900000"), new MenuItem("Lithuanian (lt-LT)", "lt-LT|2900000"), new MenuItem("Norwegian (nb-NO)", "nb-NO|2900000"), new MenuItem("Polish (pl-PL)", "pl-PL|3230000"), new MenuItem("Portugeese [Brazil] (pt-BR)", "pt-BR|3230000"), new MenuItem("Portugeese [Portugal] (pt-PT)", "pt-PT|3230000"), new MenuItem("Romanian (ro-RO)", "ro-RO|3230000"), new MenuItem("Russian (ru-RU)", "ru-RU|3230000"), new MenuItem("Serbian (sr-Latn-RS)", "tn-RS|3230000"), new MenuItem("Slovak (sk-SK)", "sk-SK|3230000"), new MenuItem("Slovenian (sl-SI)", "sl-SI|3230000"), new MenuItem("Spanish [Mexico] (es-MX)", "es-MX|2480000"), new MenuItem("Spanish [Spain] (es-ES)", "es-ES|2480000"), new MenuItem("Swedish (sv-SE)", "sv-SE|3230000"), new MenuItem("Thai (th-TH)", "th-TH|3230000"), new MenuItem("Turkish (tr-TR)", "tr-TR|3230000"), new MenuItem("Ukrainian (uk-UA)", "uk-UA|3230000"), }; private static readonly MenuItem[] KeyboardLanguageItems = new[] { new MenuItem("United States", new[] { new MenuItem("United States - English", "0409:00000409"), new MenuItem("United States - International", "0409:00020409"), new MenuItem("United States - Dvorak", "0409:00010409"), new MenuItem("United States - Dvorak (Left Hand)", "0409:00030409"), new MenuItem("United States - Dvorak (Right Hand)", "0409:00040409") }), new MenuItem("Chinese", new[] { new MenuItem("Chineese (Simplified)", "0804:{81D4E9C9-1D3B-41BC-9E6C-4B40BF79E35E}{FA550B04-5AD7-411f-A5AC-CA038EC515D7}"), new MenuItem("Chineese (Traditional) NON-FUNCTIONAL", "0404:{B115690A-EA02-48D5-A231-E3578D2FDF80}{B2F9C502-1742-11D4-9790-0080C882687E}"), new MenuItem("Chineese (Traditional, Hong Kong S.A.R.)", "0404:00000c04"), new MenuItem("Chineese (Traditonal Macao S.A.R.)", "0404:00001404"), new MenuItem("Chineese (Simplified, Singapore)", "0404:00001004") }), new MenuItem("Hindi (Devanagari) Traditional", "0439:00010439"), new MenuItem("Spanish", new[] { new MenuItem("Spanish (Spain)", "0c0a:0000040a"), new MenuItem("Spanish (Mexico)", "080a:0000080a"), new MenuItem("Spanish Variation", "0c0a:0001040a") }), new MenuItem("French", "040c:0000040c"), new MenuItem("Arabic", new[] { new MenuItem("Arabic (101)", "0401:00000401"), new MenuItem("Arabic (102)", "0401:00010401"), new MenuItem("Arabic (102 AZERTY)", "0401:00020401") }), new MenuItem("Russian", new[] { new MenuItem("Russian", "0419:00000419"), new MenuItem("Russian - Mnemonic", "0419:00020419"), new MenuItem("Russian (Typewriter)", "0419:00010419") }), new MenuItem("Bangla", new[] { new MenuItem("Bangla (Bangladesh)", "0445:00000445"), new MenuItem("Bangla (India)", "0445:00020445"), new MenuItem("Bangla (India) - Legacy", "0445:00010445") }), new MenuItem("Portuguese", new[] { new MenuItem("Portuguese", "0816:00000816"), new MenuItem("Portuguese (Brazilian ABNT)", "0816:00000416"), new MenuItem("Portuguese (Brazilian ABNT2)", "0816:00010416") }), new MenuItem("Albanian", "041c:0000041c"), new MenuItem("Amharic", "045e:{E429B25A-E5D3-4D1F-9BE3-0C608477E3A1}{8F96574E-C86C-4bd6-9666-3F7327D4CBE8}"), new MenuItem("Armenian", new[] { new MenuItem("Armenian Eastern", "042b:0000042b"), new MenuItem("Armenian Phonetic", "042b:0002042b"), new MenuItem("Armenian Typewriter", "042b:0003042b"), new MenuItem("Armenian Western", "042b:0001042b") }), new MenuItem("Assamese - Inscript", "044d:0000044d"), new MenuItem("Azerbaijani", new[] { new MenuItem("Azerbaijani (Standard)", "042c:0001042c"), new MenuItem("Azerbaijani Cyrillic", "042c:0000082c"), new MenuItem("Azerbaijani Latin", "042c:0000042c") }), new MenuItem("Bashkir", "046d:0000046d"), new MenuItem("Belarusian", "0423:00000423"), new MenuItem("Belgian", new[] { new MenuItem("Belgian (Comma)", "080c:0001080c"), new MenuItem("Belgian (Period)", "080c:00000813"), new MenuItem("Belgian French", "080c:0000080c") }), new MenuItem("Bosnian (Cyrillic)", "141a:00000201a"), new MenuItem("Buginese", "0421:000b0c00"), new MenuItem("Bulgarian", new[] { new MenuItem("Bulgarian", "0402:00030402"), new MenuItem("Bulgarian Latin", "0402:00010402"), new MenuItem("Bulgarian (Phonetic Layout)", "0402:00020402"), new MenuItem("Bulgarian (Phonetic Traditonal)", "0402:00040402"), new MenuItem("Bulgarian (Typewriter)", "0402:00000402") }), new MenuItem("Canadian", new[] { new MenuItem("Canadian French", "0c0c:00001009"), new MenuItem("Canadian French (Legacy)", "0c0c:00000c0c"), new MenuItem("Canadian Multilingual Standard", "0c0c:00011009") }), new MenuItem("Central Atlas Tamazight", "085f:0000085f"), new MenuItem("Central Kurdish", "0429:00000429"), new MenuItem("Cherokee", new[] { new MenuItem("Cherokee Nation", "045c:0000045c"), new MenuItem("Cherokee Nation Phonetic", "045c:0001045c") }), new MenuItem("Croatian", "041a:0000041a"), new MenuItem("Czech", new[] { new MenuItem("Czech", "2000:00000405"), new MenuItem("Czech (QWERTY)", "2000:00010405"), new MenuItem("Czech Programmers", "2000:00020405") }), new MenuItem("Danish", "0406:00000406"), new MenuItem("Divehi", new[] { new MenuItem("Divehi Phonetic", "0465:00000465"), new MenuItem("Divehi Typewriter", "0465:00010465") }), new MenuItem("Dutch", "0413:00000413"), new MenuItem("Dzongkha", "0C51:00000C51"), new MenuItem("Estonian", "0425:00000425"), new MenuItem("Faeroese", "0438:00000438"), new MenuItem("Finnish", new[] { new MenuItem("Finnish", "040b:0000040b"), new MenuItem("Finnish with Sami", "040b:0001083b") }), new MenuItem("Futhark", "0407:00120c00"), new MenuItem("Georgian", new[] { new MenuItem("Georgian", "0437:00020437"), new MenuItem("Georgian (Ergonomic)", "0437:00020437"), new MenuItem("Georgian (QWERTY)", "0437:00010437"), new MenuItem("Georgian Ministry of Education and Science Schools", "0437:00030437"), new MenuItem("Georgian (Old Alphabets)", "0437:00030437") }), new MenuItem("German", new[] { new MenuItem("German", "0407:00000407"), new MenuItem("German (IBM)", "0407:00010407") }), new MenuItem("Gothic", "0407:000c0c00"), new MenuItem("Greek", new[] { new MenuItem("Greek", "0408:00000408"), new MenuItem("Greek (220)", "0408:00010408"), new MenuItem("Greek (220) Latin", "0408:00030408"), new MenuItem("Greek (319)", "0408:00020408"), new MenuItem("Greek (319) Latin", "0408:00040408"), new MenuItem("Greek Latin", "0408:00050408"), new MenuItem("Greek Polytonic", "0408:00600408") }), new MenuItem("Greenlandic", "046f:0000046f"), new MenuItem("Guarani", "0474:00000474"), new MenuItem("Gujarati", "0447:00000447"), new MenuItem("Hausa", "0468:00000468"), new MenuItem("Hebrew", "040d:0000040d"), new MenuItem("Hungarian", new[] { new MenuItem("Hungarian", "040e:0000040e"), new MenuItem("Hungarian 101-key", "040e:0001040e") }), new MenuItem("Icelandic", "040f:0000040f"), new MenuItem("Igbo", "0470:00000470"), new MenuItem("Indian", "4009:00004009"), new MenuItem("Inuktitut", new[] { new MenuItem("Inuktitut - Latin", "085d:0000085d"), new MenuItem("Inuktitut - Naqittaut", "085d:0001045d") }), new MenuItem("Irish", "083C:000001809"), new MenuItem("Italian", new[] { new MenuItem("Italian", "0410:00000410"), new MenuItem("Italian (142)", "0410:00010410") }), new MenuItem("Japanese NON-FUNCTIONAL", "0411:{03B5835F-F03C-411B-9CE2-AA23E1171E36}{A76C93D9-5523-4E90-AAFA-4DB112F9AC76}"), new MenuItem("Javanese", "0421:00110c00"), new MenuItem("Kannada", "044b:0000044b"), new MenuItem("Kazakh", "043f:0000043f"), new MenuItem("Khmer", new[] { new MenuItem("Khmer", "0453:00000453"), new MenuItem("Khmer (NIDA)", "0453:00010453") }), new MenuItem("Konkoni (Devanagari) - INSCRIPT", "0457:00000439"), new MenuItem("Korean", new[] { new MenuItem("Korean (Hangul)", "0412:{A028AE76-01B1-46C2-99C4-ACD9858AE02F}{B5FE1F02-D5F2-4445-9C03-C568F23C99A1}"), new MenuItem("Korean (Old Hangul)", "0412:{a1e2b86b-924a-4d43-80f6-8a820df7190f}{b60af051-257a-46bc-b9d3-84dad819bafb}") }), new MenuItem("Kyrgyz Cyrillic", "0440:00000440"), new MenuItem("Lao", "0454:00000454"), new MenuItem("Latin American", "080a:0000080a"), new MenuItem("Latvian", new[] { new MenuItem("Latvian (Standard)", "0426:00020426"), new MenuItem("Latvian (Legacy)", "0426:00010426") }), new MenuItem("Lisu", new[] { new MenuItem("Lisu (Basic)", "0409:00070c00"), new MenuItem("Lisu (Standard)", "0409:00080c00") }), new MenuItem("Lithuanian", new[] { new MenuItem("Lithuanian", "0427:00010427"), new MenuItem("Lithuanian IBM", "0427:00000427"), new MenuItem("Lithuanian Standard", "0427:00020427") }), new MenuItem("Luxembourgish", "046e:0000046e"), new MenuItem("Macedonia", new[] { new MenuItem("Macedonian (FYROM)", "042f:0000042f"), new MenuItem("Macedonian (FYROM) - Standard", "042f:0001042f") }), new MenuItem("Malayalam", "044c:0000044c"), new MenuItem("Maltese", new[] { new MenuItem("Maltese 47-key", "043a:0000043a"), new MenuItem("Maltese 48-key", "043a:0001043a") }), new MenuItem("Maori", "0481:00000481"), new MenuItem("Marathi", "044e:0000044e"), new MenuItem("Mongolian", new[] { new MenuItem("Mongoloian (Mongolian Script - Legacy)", "0850:00000850"), new MenuItem("Mongolian (Mongolian Script - Standard)", "0850:00020850"), new MenuItem("Mongolian Cyrillic", "0850:00000450") }), new MenuItem("Myanmar", "0455:00010c00"), new MenuItem("N'ko", "0409:000090c00"), new MenuItem("Nepali", "0461:00000461"), new MenuItem("New Tai Lue", "0409:00020c00"), new MenuItem("Norwegian", new[] { new MenuItem("Norwegian", "0814:00000414"), new MenuItem("Norwegian with Sami", "0814:0000043b") }), new MenuItem("Odia", "0448:00000448"), new MenuItem("Ol Chiki", "0409:d0c00"), new MenuItem("Old Italic", "0409:000f0c00"), new MenuItem("Osmanya", "0409:000e0c00"), new MenuItem("Pashto (Afghanistan)", "0463:00000463"), new MenuItem("Persian", new[] { new MenuItem("Persian", "0429:00000429"), new MenuItem("Persian (Standard)", "0429:00050429") }), new MenuItem("Phags-pa", "0409:000a0c00"), new MenuItem("Polish", new[] { new MenuItem("Polish (214)", "0415:00010415"), new MenuItem("Polish (Programmers)", "0415:00000415") }), new MenuItem("Punjabi", "0446:00000446"), new MenuItem("Romanian", new[] { new MenuItem("Romanian (Legacy)", "0418:00000418"), new MenuItem("Romanian (Programmers)", "0418:00020418"), new MenuItem("Romanian (Standard)", "0418:00010418") }), new MenuItem("Sakha", "0485:00000485"), new MenuItem("Sami", new[] { new MenuItem("Sami Extended Finland-Sweden", "083b:0002083b"), new MenuItem("Sami Extended Norway", "043b:0001043b") }), new MenuItem("Scottish Gaelic", "0809:00011809"), new MenuItem("Serbian", new[] { new MenuItem("Serbian (Cyrillic)", "1C1A:00000c1a"), new MenuItem("Serbian (Latin)", "241A:0000081a") }), new MenuItem("Sesotho sa Leboa", "046c:0000046c"), new MenuItem("Setswana", "0432:00000432"), new MenuItem("Sinhala", new[] { new MenuItem("Sinhala", "045b:0000045b"), new MenuItem("Sinhala - wij 9", "045b:0001045b") }), new MenuItem("Slovak", new[] { new MenuItem("Slovak", "041b:0000041b"), new MenuItem("Slovak (QWERTY)", "041b:0001041b") }), new MenuItem("Slovenian", "0424:00000424"), new MenuItem("Sora", "0409:00100c00"), new MenuItem("Sorbian", new[] { new MenuItem("Sorbian Extended", "042e:0001042e"), new MenuItem("Sorbian Standard", "042e:0002042e"), new MenuItem("Sorbian Standard (Legacy)", "042e:0000042e") }), new MenuItem("Swedish", new[] { new MenuItem("Swedish", "041d:0000041d"), new MenuItem("Swedish with Sami", "083b:0000083b") }), new MenuItem("Swiss", new[] { new MenuItem("Swiss French", "100c:0000100c"), new MenuItem("Swiss German", "0807:00000807") }), new MenuItem("Syriac", new[] { new MenuItem("Syriac", "045a:0000045a"), new MenuItem("Syriac Phonetic", "045a:0001045a") }), new MenuItem("Tai Le", "0409:00030c00"), new MenuItem("Tajik", "0428:00000428"), new MenuItem("Tamil", new[] { new MenuItem("Tamil", "0449:00000449"), new MenuItem("Tamil (99 Keyboard)", "0449:00020449") }), new MenuItem("Tatar", new[] { new MenuItem("Tatar", "0444:00010444"), new MenuItem("Tatar (Legacy)", "0444:00000444") }), new MenuItem("Telugu", "044a:0000044a"), new MenuItem("Thai", new[] { new MenuItem("Thai Kedmanee", "041e:0000041e"), new MenuItem("Thai Kedmanee (non-ShiftLock)", "041e:0002041e"), new MenuItem("Thai Pattachote", "041e:0001041e"), new MenuItem("Thai Pattachote (non-ShiftLock)", "041e:0003041e") }), new MenuItem("Tibetan", new[] { new MenuItem("Tibetan (PRC - Standard)", "0451:00010451"), new MenuItem("Tibetan (PRC - Legacy)", "0451:00000451") }), new MenuItem("Tifinagh", new[] { new MenuItem("Tifinagh (Basic)", "0409:00050c00"), new MenuItem("Tifinagh (Full)", "0409:00050c00") }), new MenuItem("Tigrinya", "0473:{E429B25A-E5D3-4D1F-9BE3-0C608477E3A1}{3CAB88B7-CC3E-46A6-9765-B772AD7761FF}"), new MenuItem("Turkish", new[] { new MenuItem("Turkish F", "041f:0001041f"), new MenuItem("Turkish Q", "041f:0000041f") }), new MenuItem("Turkmen", "0442:00000442"), new MenuItem("Uyghur", new[] { new MenuItem("Uyghur", "0480:00010480"), new MenuItem("Uygher (Legacy)", "0480:00000480"), new MenuItem("Uyghur (Greek 220)", "0480:00010408") }), new MenuItem("Ukrainian", new[] { new MenuItem("Ukrainian", "0422:00000422"), new MenuItem("Ukrainian (Enhanced)", "0422:00020422") }), new MenuItem("United Kingdom", new[] { new MenuItem("United Kingdom", "0809:00000809"), new MenuItem("United Kingdom Extended", "0809:00000452") }), new MenuItem("Urdu", "0420:00000420"), new MenuItem("Uzbek", "0843:00000843"), new MenuItem("Vietnamese", new[] { new MenuItem("Vietnamese", "042a:0000042a"), new MenuItem("Vietnamese Telex", "042A:{C2CB2CF0-AF47-413E-9780-8BC3A3C16068}{5FB02EC5-0A77-4684-B4FA-DEF8A2195628}") }), new MenuItem("Wolof", "0488:00000488"), new MenuItem("Yakut", "0485:00000485"), new MenuItem("Yoruba", "046a:0000056a"), }; } public static class NativeMethods { private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); private const uint FILE_READ_EA = 0x0008; private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000; [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] uint access, [MarshalAs(UnmanagedType.U4)] FileShare share, IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] uint flagsAndAttributes, IntPtr templateFile); public static string GetFinalPathName(string path) { var h = CreateFile(path, FILE_READ_EA, FileShare.ReadWrite | FileShare.Delete, IntPtr.Zero, FileMode.Open, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero); if (h == INVALID_HANDLE_VALUE) return null; try { var sb = new StringBuilder(1024); var res = GetFinalPathNameByHandle(h, sb, 1024, 0); if (res == 0) return null; return sb.ToString(); } finally { CloseHandle(h); } } } public class WebClientEx : WebClient { private readonly long from; private readonly long to; public WebClientEx(long from, long to) { this.from = from; this.to = to; } protected override WebRequest GetWebRequest(Uri address) { var request = (HttpWebRequest)base.GetWebRequest(address); request.AddRange(this.from, this.to); return request; } } }