diff --git a/.gitignore b/.gitignore index ab792ee69..22296c86c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ ReleaseHant/ /output/*.ime /output/*.txt /output/*.bat +/output/*.config /output/data/essay.txt /output/data/opencc/ /output/data/*.yaml @@ -44,4 +45,5 @@ arm64x_wrapper/*.o arm64x_wrapper/*.dll arm64x_wrapper/*.ime arm64x_wrapper/*.lib -arm64x_wrapper/*.exp \ No newline at end of file +arm64x_wrapper/*.exp +/packages \ No newline at end of file diff --git a/Weasel.Setup/Localization/Resources.Designer.cs b/Weasel.Setup/Localization/Resources.Designer.cs new file mode 100644 index 000000000..5ec4ca74d --- /dev/null +++ b/Weasel.Setup/Localization/Resources.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Weasel.Setup.Localization { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weasel.Setup.Localization.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 Error 的本地化字符串。 + /// + internal static string STR_ERROR { + get { + return ResourceManager.GetString("STR_ERROR", resourceCulture); + } + } + + /// + /// 查找类似 Install 的本地化字符串。 + /// + internal static string STR_INSTALL { + get { + return ResourceManager.GetString("STR_INSTALL", resourceCulture); + } + } + + /// + /// 查找类似 Installation success 的本地化字符串。 + /// + internal static string STR_INSTALL_SUCCESS { + get { + return ResourceManager.GetString("STR_INSTALL_SUCCESS", resourceCulture); + } + } + + /// + /// 查找类似 OK 的本地化字符串。 + /// + internal static string STR_OK { + get { + return ResourceManager.GetString("STR_OK", resourceCulture); + } + } + + /// + /// 查找类似 Change the user folder location successfully 的本地化字符串。 + /// + internal static string STR_UF_CHANGE_SUCCESS { + get { + return ResourceManager.GetString("STR_UF_CHANGE_SUCCESS", resourceCulture); + } + } + + /// + /// 查找类似 Uninstall successfully 的本地化字符串。 + /// + internal static string STR_UNINSTALL_SUCCESS { + get { + return ResourceManager.GetString("STR_UNINSTALL_SUCCESS", resourceCulture); + } + } + } +} diff --git a/Weasel.Setup/Localization/Resources.resx b/Weasel.Setup/Localization/Resources.resx new file mode 100644 index 000000000..6c89c2f2f --- /dev/null +++ b/Weasel.Setup/Localization/Resources.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Install + + + OK + + + Error + + + Installation success + + + Uninstall successfully + + + Change the user folder location successfully + + \ No newline at end of file diff --git a/Weasel.Setup/Localization/Resources.zh-Hans.resx b/Weasel.Setup/Localization/Resources.zh-Hans.resx new file mode 100644 index 000000000..5132eddce --- /dev/null +++ b/Weasel.Setup/Localization/Resources.zh-Hans.resx @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 安装 + + + 确定 + + + 出错了 + + + 可以使【小狼毫】写字了 :) + + + 小狼毫 :) + + + 更改用户文件夹位置成功 :) + + diff --git a/Weasel.Setup/Localization/Resources.zh-Hant.resx b/Weasel.Setup/Localization/Resources.zh-Hant.resx new file mode 100644 index 000000000..ba779971d --- /dev/null +++ b/Weasel.Setup/Localization/Resources.zh-Hant.resx @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 安裝 + + + 確認 + + + 出錯了 + + + 可以使【小狼毫】寫字了 :) + + + 小狼毫 :) + + + 更改用戶資料夾位置成功 :) + + \ No newline at end of file diff --git a/Weasel.Setup/PInvoke.cs b/Weasel.Setup/PInvoke.cs new file mode 100644 index 000000000..c0e98d403 --- /dev/null +++ b/Weasel.Setup/PInvoke.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.InteropServices; + +namespace Weasel.Setup +{ + internal class PInvoke + { + [Flags] + public enum ILOT + { + ILOT_UNINSTALL = 0x00000001, + } + + [DllImport("input.dll", SetLastError = false, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool InstallLayoutOrTip([In, MarshalAs(UnmanagedType.LPWStr)] string psz, [In] ILOT dwFlags); + + + [Flags] + public enum MoveFileFlags + { + MOVEFILE_REPLACE_EXISTING = 0x1, + MOVEFILE_DELAY_UNTIL_REBOOT = 0x4 + } + + + [DllImport("kernel32.dll", EntryPoint = "MoveFileExW", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool MoveFileEx(string src, string dest, MoveFileFlags flags); + + [Flags] + public enum PROCESS_DPI_AWARENESS + { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE, + PROCESS_PER_MONITOR_DPI_AWARE, + } + + [DllImport("Shcore.dll", SetLastError = true)] + public static extern int SetProcessDpiAwareness(PROCESS_DPI_AWARENESS type); + } +} diff --git a/Weasel.Setup/Program.cs b/Weasel.Setup/Program.cs new file mode 100644 index 000000000..a87ed2c7e --- /dev/null +++ b/Weasel.Setup/Program.cs @@ -0,0 +1,214 @@ +using Microsoft.Win32; +using System; +using System.Diagnostics; +using System.IO; +using System.Security.Principal; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Weasel.Setup +{ + internal class Program + { + private static bool IsRunAsAdmin() + { + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + + private static void RunAsAdmin(string arg) + { + var info = new ProcessStartInfo + { + FileName = Application.ExecutablePath, + Arguments = arg, + Verb = "RunAs", + UseShellExecute = true, + }; + Process.Start(info); + } + + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + Utils.App.SetProcessApiAwareness(); + + var appCulture = Utils.App.CultureInfo; + Thread.CurrentThread.CurrentCulture = appCulture; + Thread.CurrentThread.CurrentUICulture = appCulture; + + Run(string.Join(" ", args)); + } + + private static readonly string WEASEL_PROG_REG_KEY = @"SOFTWARE\Rime\Weasel"; + private static readonly string WEASEL_UPDATE_REG_KEY = $@"{WEASEL_PROG_REG_KEY}\Updates"; + + private static void Run(string arg) + { + try + { + if (arg.StartsWith("/userdir:")) // 设置用户目录 + { + var dir = arg.Substring(arg.IndexOf(':') + 1); + if (dir != null) + { + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\RimeUserDir", dir); + } + return; + } + else + { + switch (arg) // 无需管理员权限的操作 + { + case "/ls": // 简体中文 + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\Language", "chs"); + return; + case "/lt": // 繁体中文 + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\Language", "cht"); + return; + case "/le": // 英语 + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\Language", "eng"); + return; + case "/eu": // 启用更新 + Registry.CurrentUser.SetValue($@"{WEASEL_UPDATE_REG_KEY}\CheckForUpdates", "1"); + return; + case "/du": // 禁用更新 + Registry.CurrentUser.SetValue($@"{WEASEL_UPDATE_REG_KEY}\CheckForUpdates", "0"); + return; + case "/toggleime": + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\ToggleImeOnOpenClose", "yes"); + return; + case "/toggleascii": + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\ToggleImeOnOpenClose", "no"); + return; + case "/testing": // 测试通道 + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\UpdateChannel", "testing"); + return; + case "/release": // 正式通道 + Registry.CurrentUser.SetValue($@"{WEASEL_PROG_REG_KEY}\UpdateChannel", "release"); + return; + default: // 需要管理员权限的操作 + if (!IsRunAsAdmin()) + { + RunAsAdmin(arg); + Application.Exit(); + return; + } + switch (arg) + { + case "/u": // 卸载 + Setup.Uninstall(true); + return; + case "/s": // 简体中文安装 + Setup.NormalInstall(false); + return; + case "/t": // 繁体中文安装 + Setup.NormalInstall(true); + return; + default: + break; + } + break; + } + } + // 自定义安装 + CustomInstall(arg == "/i"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, Localization.Resources.STR_ERROR); + } + } + + private static void CustomInstall(bool isInstalling) + { + var isSilentMode = false; + var isInstalled = Setup.IsWeaselInstalled; + + bool isHant = false; + string userDir = string.Empty; + using (var user = Registry.CurrentUser.OpenSubKey(WEASEL_PROG_REG_KEY)) + { + if (user != null) + { + userDir = Convert.ToString(user.GetValue("RimeUserDir")); + var value = user.GetValue("Hant"); + if (value != null && value is int) + { + isHant = Convert.ToBoolean(value); + if (isInstalling) isSilentMode = true; + } + } + } + + if (!isSilentMode) + { + var dialog = new SetupOptionDialog + { + IsInstalled = isInstalled, + IsHant = isHant, + UserDir = userDir + }; + if (DialogResult.OK == dialog.ShowDialog()) + { + isInstalled = dialog.IsInstalled; + isHant = dialog.IsHant; + userDir = dialog.UserDir; + + using (var user = Registry.CurrentUser.CreateSubKey(WEASEL_PROG_REG_KEY)) + { + user.SetValue($@"{WEASEL_PROG_REG_KEY}\RimeUserDir", userDir); + user.SetValue($@"{WEASEL_PROG_REG_KEY}\Hant", isHant ? 1 : 0); + } + } + else + { + if (!isInstalling) + { + Application.Exit(); + return; + } + } + } + if (!isInstalled) + { + Setup.NormalInstall(isHant, isSilentMode); + } + else + { + var installDir = Path.GetDirectoryName(Application.ExecutablePath); ; + Task.Run(() => + { + ExecProcess(Path.Combine(installDir, "WeaselServer.exe"), "/q"); + Task.Delay(500); + + ExecProcess(Path.Combine(installDir, "WeaselServer.exe"), string.Empty); + Task.Delay(500); + + ExecProcess(Path.Combine(installDir, "WeaselDeployer.exe"), "/deploy"); + }); + MessageBox.Show(Localization.Resources.STR_UF_CHANGE_SUCCESS); + } + } + + private static void ExecProcess(string path, string args) + { + var info = new ProcessStartInfo + { + FileName = path, + Arguments = args, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Normal, + }; + Process.Start(info); + } + } +} diff --git a/Weasel.Setup/Setup.cs b/Weasel.Setup/Setup.cs new file mode 100644 index 000000000..2d1d71a30 --- /dev/null +++ b/Weasel.Setup/Setup.cs @@ -0,0 +1,273 @@ +using Microsoft.Win32; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using TSF.InteropTypes; +using TSF.TypeLib; + +namespace Weasel.Setup +{ + public static class Setup + { + private static readonly Guid CLSID_TEXT_SERVICE; + private static readonly Guid GUID_PROFILE; + + private static readonly string PSZTITLE_HANS; + private static readonly string PSZTITLE_HANT; + + private static readonly string RIME_ROOT_REG_KEY; + private static readonly string WEASEL_PROG_REG_KEY; + private static readonly string WEASEL_SERVER_EXE; + private static readonly string WEASEL_WER_REG_KEY; + + static Setup() + { + CLSID_TEXT_SERVICE = Guid.Parse("{A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}"); + GUID_PROFILE = Guid.Parse("{3D02CAB6-2B8E-4781-BA20-1C9267529467}"); + + PSZTITLE_HANS = $"0804:{CLSID_TEXT_SERVICE:B}{GUID_PROFILE:B}"; + PSZTITLE_HANT = $"0404:{CLSID_TEXT_SERVICE:B}{GUID_PROFILE:B}"; + + RIME_ROOT_REG_KEY = @"SOFTWARE\Rime"; + WEASEL_PROG_REG_KEY = $@"{RIME_ROOT_REG_KEY}\Weasel"; + WEASEL_SERVER_EXE = "WeaselServer.exe"; + + WEASEL_WER_REG_KEY = $@"SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\{WEASEL_SERVER_EXE}"; + } + + public static bool IsWeaselInstalled + { + get + { + var sys32Dir = Environment.GetFolderPath(Environment.SpecialFolder.System); + var weaselPath = Path.Combine(sys32Dir, "weasel.dll"); + return File.Exists(weaselPath); + } + } + + public static void NormalInstall(bool isHant, bool isSilentMode = true) + { + // 安装 IME 文件 + var productDir = Path.GetDirectoryName(Application.ExecutablePath); + var imeSrcPath = Path.Combine(productDir, "weasel.dll"); + InstallImeFiles(imeSrcPath, (libPath) => + { + UpdateServiceState(libPath, true, isHant); + }); + + // 登记注册表 + using (var local = Registry.LocalMachine.CreateSubKey(WEASEL_PROG_REG_KEY)) + { + local.SetValue("WeaselRoot", productDir); + local.SetValue("ServerExecutable", WEASEL_SERVER_EXE); + } + + // 启用键盘布局和文本服务 + var psz = isHant ? PSZTITLE_HANT : PSZTITLE_HANS; + PInvoke.InstallLayoutOrTip(psz, 0); + + // 收集用户模式转储 + // https://learn.microsoft.com/zh-cn/windows/win32/wer/collecting-user-mode-dumps + using (var local = Registry.LocalMachine.CreateSubKey(WEASEL_WER_REG_KEY)) + { + local.SetValue("DumpFolder", Utils.LogPath); + local.SetValue("DumpType", 0); + local.SetValue("CustomDumpFlags", 0); + local.SetValue("DumpCount", 10); + } + + if (!isSilentMode) + { + MessageBox.Show(Localization.Resources.STR_INSTALL_SUCCESS); + } + } + + public static void Uninstall(bool isSilentMode) + { + // 停用键盘布局和文本服务 + var isHant = Convert.ToBoolean( + Registry.CurrentUser.GetValue($@"{WEASEL_PROG_REG_KEY}\Hant") + ); + var psz = isHant ? PSZTITLE_HANT : PSZTITLE_HANS; + PInvoke.InstallLayoutOrTip(psz, PInvoke.ILOT.ILOT_UNINSTALL); + + UninstallImeFiles("weasel.dll", (imePath) => + { + UpdateServiceState(imePath, enable: false, isHant); + }); + + // 清理注册表 + using (var local = Registry.LocalMachine) + { + local.DeleteSubKeyTree(RIME_ROOT_REG_KEY, throwOnMissingSubKey: false); + local.DeleteSubKey(WEASEL_WER_REG_KEY, throwOnMissingSubKey: false); + } + + if (!isSilentMode) + { + MessageBox.Show(Localization.Resources.STR_UNINSTALL_SUCCESS); + } + } + + private static void InstallImeFiles(string srcPath, Action updateService) + { + var baseName = Path.GetFileName(srcPath); + var sys32Dir = Environment.GetFolderPath(Environment.SpecialFolder.System); + var destPath = Path.Combine(sys32Dir, baseName); + + if (Environment.Is64BitOperatingSystem) + { + if (RuntimeInformation.OSArchitecture == Architecture.Arm64) + { + var sysarm32Dir = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.Windows), + "SysArm32" + ); + if (Directory.Exists(sysarm32Dir)) + { + // 如果支持 ARM32 子系统,则安装 ARM32 版本(Windows 11 24H2 之前) + var arm32SrcPath = srcPath.Insert(srcPath.LastIndexOf('.'), "ARM"); + var arm32DestPath = Path.Combine(sysarm32Dir, baseName); + if (File.Exists(arm32SrcPath)) + { + Utils.CopyFile(arm32SrcPath, arm32DestPath); + updateService(arm32SrcPath); + } + } + + // 安装 ARM64(和 x64)版本库。 + // ARM64 系统上进程会被重定向至 ARM64X DLL, + // 其加载时,ARM64 进程会被重定向到 ARM64 DLL,x64 进程会被重定向到 x64 DLL, + // 所以这三个库都要安装 + var x64SrcPath = srcPath.Insert(srcPath.LastIndexOf('.'), "x64"); + var x64DestPath = destPath.Insert(srcPath.LastIndexOf('.'), "x64"); + if (File.Exists(x64SrcPath)) Utils.CopyFile(x64SrcPath, x64DestPath); + + var arm64SrcPath = srcPath.Insert(srcPath.LastIndexOf('.'), "x64"); + var arm64DestPath = destPath.Insert(srcPath.LastIndexOf('.'), "x64"); + if (File.Exists(arm64SrcPath)) Utils.CopyFile(arm64SrcPath, arm64DestPath); + + // ARM64X 充当重定向器(转发器),因此我们不必区分其简繁变体 + var arm64xSrcPath = srcPath.Insert(srcPath.LastIndexOf('.'), "ARM64X"); + if (File.Exists(arm64xSrcPath)) + { + Utils.CopyFile(arm64xSrcPath, destPath); + updateService(destPath); + } + } + else + { + var sysWow64Dir = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86); + var wow64DestPath = Path.Combine(sysWow64Dir, baseName); + if (File.Exists(srcPath)) + { + Utils.CopyFile(srcPath, wow64DestPath); + updateService(wow64DestPath); + } + var x64SrcPath = srcPath.Insert(srcPath.LastIndexOf('.'), "x64"); + if (File.Exists(x64SrcPath)) + { + Utils.CopyFile(x64SrcPath, destPath); + updateService(destPath); + } + } + } + else + { + if (File.Exists(srcPath)) + { + File.Copy(srcPath, destPath, true); + updateService(destPath); + } + } + } + + private static void UninstallImeFiles(string baseName, Action updateService) + { + var sys32Dir = Environment.GetFolderPath(Environment.SpecialFolder.System); + var imePath = Path.Combine(sys32Dir, baseName); + + if (Environment.Is64BitOperatingSystem) + { + var sysWow64Dir = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86); + var wow64ImePath = Path.Combine(sysWow64Dir, baseName); + if (File.Exists(wow64ImePath)) Utils.DeleteFile(wow64ImePath); + + if (RuntimeInformation.OSArchitecture == Architecture.Arm64) + { + var sysarm32Dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysArm32"); + if (Directory.Exists(sysarm32Dir)) + { + var arm32ImePath = Path.Combine(sysarm32Dir, baseName); + if (File.Exists(arm32ImePath)) + { + updateService(arm32ImePath); + Utils.DeleteFile(arm32ImePath); + } + } + + var x64ImePath = imePath.Insert(imePath.LastIndexOf('.'), "x64"); + if (File.Exists(x64ImePath)) Utils.DeleteFile(x64ImePath); + + var arm64ImePath = imePath.Insert(imePath.LastIndexOf('.'), "ARM64"); + if (File.Exists(arm64ImePath)) Utils.DeleteFile(arm64ImePath); + } + else + { + if (File.Exists(imePath)) + { + updateService(imePath); + Utils.DeleteFile(imePath); + } + } + } + else + { + if (File.Exists(imePath)) + { + updateService(imePath); + Utils.DeleteFile(imePath); + } + } + } + + private static void UpdateServiceState(string libPath, bool enable, bool isHant) + { + if (!enable) UpdateProfile(false, isHant); + var value = isHant ? "hant" : "hans"; + Environment.SetEnvironmentVariable("TEXTSERVICE_PROFILE", value); + var sysarm32Dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysArm32"); + var regsvr32Path = Directory.Exists(sysarm32Dir) + ? Path.Combine(sysarm32Dir, "regsvr32.exe") + : "regsvr32.exe"; + var args = enable ? $"/s \"{libPath}\"" : $"/s /u \"{libPath}\""; + var updateInfo = new ProcessStartInfo + { + FileName = regsvr32Path, + Arguments = args, + Verb = "open", + UseShellExecute = true, + }; + Process.Start(updateInfo).WaitForExit(); + + if (enable) UpdateProfile(true, isHant); + } + + private static void UpdateProfile(bool enable, bool isHant) + { + var langId = isHant ? new LangID(0x0404) : new LangID(0x0804); + var profiles = new ITfInputProcessorProfiles(); + if (enable) + { + profiles.EnableLanguageProfile(CLSID_TEXT_SERVICE, langId, GUID_PROFILE, enable); + profiles.EnableLanguageProfileByDefault(CLSID_TEXT_SERVICE, langId, GUID_PROFILE, out _); + } + else + { + profiles.RemoveLanguageProfile(CLSID_TEXT_SERVICE, langId, GUID_PROFILE); + } + } + } +} diff --git a/Weasel.Setup/SetupOptionDialog.Designer.cs b/Weasel.Setup/SetupOptionDialog.Designer.cs new file mode 100644 index 000000000..fa482e4fc --- /dev/null +++ b/Weasel.Setup/SetupOptionDialog.Designer.cs @@ -0,0 +1,156 @@ +namespace Weasel.Setup +{ + partial class SetupOptionDialog + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SetupOptionDialog)); + this.inputLangGroup = new System.Windows.Forms.GroupBox(); + this.chtRadio = new System.Windows.Forms.RadioButton(); + this.chsRadio = new System.Windows.Forms.RadioButton(); + this.userFolderGroup = new System.Windows.Forms.GroupBox(); + this.selectButton = new System.Windows.Forms.Button(); + this.customPathBox = new System.Windows.Forms.TextBox(); + this.customFolderRadio = new System.Windows.Forms.RadioButton(); + this.defaultFolderRadio = new System.Windows.Forms.RadioButton(); + this.confirmButton = new System.Windows.Forms.Button(); + this.removeButton = new System.Windows.Forms.Button(); + this.inputLangGroup.SuspendLayout(); + this.userFolderGroup.SuspendLayout(); + this.SuspendLayout(); + // + // inputLangGroup + // + this.inputLangGroup.Controls.Add(this.chtRadio); + this.inputLangGroup.Controls.Add(this.chsRadio); + resources.ApplyResources(this.inputLangGroup, "inputLangGroup"); + this.inputLangGroup.Name = "inputLangGroup"; + this.inputLangGroup.TabStop = false; + // + // chtRadio + // + resources.ApplyResources(this.chtRadio, "chtRadio"); + this.chtRadio.Name = "chtRadio"; + this.chtRadio.TabStop = true; + this.chtRadio.UseVisualStyleBackColor = true; + // + // chsRadio + // + resources.ApplyResources(this.chsRadio, "chsRadio"); + this.chsRadio.Name = "chsRadio"; + this.chsRadio.TabStop = true; + this.chsRadio.UseVisualStyleBackColor = true; + // + // userFolderGroup + // + this.userFolderGroup.Controls.Add(this.selectButton); + this.userFolderGroup.Controls.Add(this.customPathBox); + this.userFolderGroup.Controls.Add(this.customFolderRadio); + this.userFolderGroup.Controls.Add(this.defaultFolderRadio); + resources.ApplyResources(this.userFolderGroup, "userFolderGroup"); + this.userFolderGroup.Name = "userFolderGroup"; + this.userFolderGroup.TabStop = false; + // + // selectButton + // + resources.ApplyResources(this.selectButton, "selectButton"); + this.selectButton.Name = "selectButton"; + this.selectButton.UseVisualStyleBackColor = true; + this.selectButton.Click += new System.EventHandler(this.SelectButton_Click); + // + // customPathBox + // + resources.ApplyResources(this.customPathBox, "customPathBox"); + this.customPathBox.Name = "customPathBox"; + // + // customFolderRadio + // + resources.ApplyResources(this.customFolderRadio, "customFolderRadio"); + this.customFolderRadio.Name = "customFolderRadio"; + this.customFolderRadio.TabStop = true; + this.customFolderRadio.UseVisualStyleBackColor = true; + this.customFolderRadio.CheckedChanged += new System.EventHandler(this.CustomFolderRadio_CheckedChanged); + // + // defaultFolderRadio + // + resources.ApplyResources(this.defaultFolderRadio, "defaultFolderRadio"); + this.defaultFolderRadio.Name = "defaultFolderRadio"; + this.defaultFolderRadio.TabStop = true; + this.defaultFolderRadio.UseVisualStyleBackColor = true; + this.defaultFolderRadio.CheckedChanged += new System.EventHandler(this.DefaultFolderRadio_CheckedChanged); + // + // confirmButton + // + resources.ApplyResources(this.confirmButton, "confirmButton"); + this.confirmButton.Name = "confirmButton"; + this.confirmButton.UseVisualStyleBackColor = true; + this.confirmButton.Click += new System.EventHandler(this.ConfirmButton_Click); + // + // removeButton + // + resources.ApplyResources(this.removeButton, "removeButton"); + this.removeButton.Name = "removeButton"; + this.removeButton.UseVisualStyleBackColor = true; + this.removeButton.Click += new System.EventHandler(this.RemoveButton_Click); + // + // SetupOptionDialog + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.removeButton); + this.Controls.Add(this.confirmButton); + this.Controls.Add(this.userFolderGroup); + this.Controls.Add(this.inputLangGroup); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SetupOptionDialog"; + this.ShowIcon = false; + this.Load += new System.EventHandler(this.InstallOptionDialog_Load); + this.inputLangGroup.ResumeLayout(false); + this.inputLangGroup.PerformLayout(); + this.userFolderGroup.ResumeLayout(false); + this.userFolderGroup.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox inputLangGroup; + private System.Windows.Forms.GroupBox userFolderGroup; + private System.Windows.Forms.RadioButton chtRadio; + private System.Windows.Forms.RadioButton chsRadio; + private System.Windows.Forms.RadioButton customFolderRadio; + private System.Windows.Forms.RadioButton defaultFolderRadio; + private System.Windows.Forms.Button confirmButton; + private System.Windows.Forms.Button removeButton; + private System.Windows.Forms.TextBox customPathBox; + private System.Windows.Forms.Button selectButton; + } +} + diff --git a/Weasel.Setup/SetupOptionDialog.cs b/Weasel.Setup/SetupOptionDialog.cs new file mode 100644 index 000000000..5d829a46e --- /dev/null +++ b/Weasel.Setup/SetupOptionDialog.cs @@ -0,0 +1,89 @@ +using System.Windows.Forms; + +namespace Weasel.Setup +{ + public partial class SetupOptionDialog : Form + { + public bool IsInstalled { get; set; } + public bool IsHant { get; set; } + public string UserDir { get; set; } + + public SetupOptionDialog() + { + InitializeComponent(); + } + + private void InstallOptionDialog_Load(object sender, System.EventArgs e) + { + chsRadio.Checked = !IsHant; + chtRadio.Checked = IsHant; + + inputLangGroup.Enabled = !IsInstalled; + + defaultFolderRadio.Checked = string.IsNullOrEmpty(UserDir); + customFolderRadio.Checked = !string.IsNullOrEmpty(UserDir); + customPathBox.Enabled = !string.IsNullOrEmpty(UserDir); + selectButton.Enabled = !string.IsNullOrEmpty(UserDir); + customPathBox.Text = UserDir; + + if (IsInstalled) + { + confirmButton.Text = Localization.Resources.STR_OK; + } + removeButton.Enabled = IsInstalled; + } + + private void DefaultFolderRadio_CheckedChanged(object sender, System.EventArgs e) + { + if (defaultFolderRadio.Checked) + { + customPathBox.Text = string.Empty; + customPathBox.Enabled = false; + selectButton.Enabled = false; + } + } + + private void CustomFolderRadio_CheckedChanged(object sender, System.EventArgs e) + { + if (customFolderRadio.Checked) + { + customPathBox.Enabled = true; + selectButton.Enabled = true; + } + } + + private void ConfirmButton_Click(object sender, System.EventArgs e) + { + IsHant = chtRadio.Checked; + UserDir = customFolderRadio.Checked + ? customPathBox.Text + : string.Empty; + DialogResult = DialogResult.OK; + Close(); + } + + private void SelectButton_Click(object sender, System.EventArgs e) + { + var folderDialog = new FolderBrowserDialog(); + var customPath = customPathBox.Text; + if (!string.IsNullOrEmpty(customPath)) + { + folderDialog.SelectedPath = customPath; + } + if (DialogResult.OK == folderDialog.ShowDialog()) + { + customPathBox.Text = folderDialog.SelectedPath; + } + confirmButton.Focus(); + } + + private void RemoveButton_Click(object sender, System.EventArgs e) + { + Setup.Uninstall(false); + IsInstalled = false; + confirmButton.Text = Localization.Resources.STR_INSTALL; + inputLangGroup.Enabled = !IsInstalled; + removeButton.Enabled = IsInstalled; + } + } +} diff --git a/Weasel.Setup/SetupOptionDialog.resx b/Weasel.Setup/SetupOptionDialog.resx new file mode 100644 index 000000000..354f10496 --- /dev/null +++ b/Weasel.Setup/SetupOptionDialog.resx @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + chtRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + inputLangGroup + + + 0 + + + chsRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + inputLangGroup + + + 1 + + + + 10, 11 + + + 652, 204 + + + + 0 + + + Input language + + + inputLangGroup + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + True + + + 45, 125 + + + 218, 21 + + + 1 + + + Chinese (Traditional) + + + chtRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + inputLangGroup + + + 0 + + + True + + + 45, 63 + + + 209, 21 + + + 0 + + + Chinese (Simplified) + + + chsRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + inputLangGroup + + + 1 + + + 495, 137 + + + 112, 33 + + + 3 + + + Select + + + selectButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + userFolderGroup + + + 0 + + + False + + + 45, 139 + + + 440, 27 + + + 2 + + + customPathBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + userFolderGroup + + + 1 + + + True + + + 45, 93 + + + 164, 21 + + + 1 + + + Custom location + + + customFolderRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + userFolderGroup + + + 2 + + + True + + + 45, 46 + + + 173, 21 + + + 0 + + + Default location + + + defaultFolderRadio + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + userFolderGroup + + + 3 + + + 10, 222 + + + 652, 204 + + + 1 + + + User folder + + + userFolderGroup + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 55, 442 + + + 112, 45 + + + 2 + + + Install + + + confirmButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 505, 442 + + + 112, 45 + + + 3 + + + Remove + + + removeButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 9, 17 + + + 675, 510 + + + 宋体, 10pt + + + + CenterScreen + + + Weasel Setup Options + + + SetupOptionDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Weasel.Setup/SetupOptionDialog.zh-Hans.resx b/Weasel.Setup/SetupOptionDialog.zh-Hans.resx new file mode 100644 index 000000000..ff9550065 --- /dev/null +++ b/Weasel.Setup/SetupOptionDialog.zh-Hans.resx @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 99, 27 + + + 繁体中文 + + + 99, 27 + + + 简体中文 + + + 输入语言 + + + 用户文件夹 + + + 133, 27 + + + 我来指定位置 + + + 133, 27 + + + 使用默认位置 + + + 安装 + + + 移除 + + + 【小狼毫】配置选项 + + + 选择 + + \ No newline at end of file diff --git a/Weasel.Setup/SetupOptionDialog.zh-Hant.resx b/Weasel.Setup/SetupOptionDialog.zh-Hant.resx new file mode 100644 index 000000000..a301d86f4 --- /dev/null +++ b/Weasel.Setup/SetupOptionDialog.zh-Hant.resx @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 99, 27 + + + 繁體中文 + + + 99, 27 + + + 簡體中文 + + + 輸入語言 + + + 用戶資料夾 + + + 133, 27 + + + 我來指定位置 + + + 133, 27 + + + 使用默認位置 + + + 安裝 + + + 移除 + + + 【小狼毫】配置選項 + + + 選擇 + + \ No newline at end of file diff --git a/Weasel.Setup/Utils.cs b/Weasel.Setup/Utils.cs new file mode 100644 index 000000000..0c3542628 --- /dev/null +++ b/Weasel.Setup/Utils.cs @@ -0,0 +1,117 @@ +using Microsoft.Win32; +using System; +using System.IO; + +namespace Weasel.Setup +{ + internal class Utils + { + public static CultureInfo CultureInfo + { + get + { + var lang = (string)Registry.CurrentUser.GetValue(@"Software\Rime\Weasel\Language", string.Empty); + if (!string.IsNullOrEmpty(lang)) + { + switch (lang) + { + case "chs": + return new CultureInfo("zh-Hans"); + case "cht": + return new CultureInfo("zh-Hant"); + default: + return new CultureInfo("en-US"); + } + } + else + { + var current = Thread.CurrentThread.CurrentUICulture.Name; + if (current.StartsWith("zh")) + { + if (current.EndsWith("HK") || current.EndsWith("MO") || + current.EndsWith("TW") || current.EndsWith("Hant")) + { + return new CultureInfo("zh-Hant"); + } + else + { + return new CultureInfo("zh-Hans"); + } + } + else + { + return new CultureInfo("en-US"); + } + } + } + } + + public static void SetProcessApiAwareness() + { + if (Environment.OSVersion.Version >= new Version(6, 3, 9600)) // Windows 8.1 + { + PInvoke.HIDPI.SetProcessDpiAwareness(PInvoke.HIDPI.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE); + } + } + + public static string LogPath + { + get + { + var path = Environment.ExpandEnvironmentVariables(@"%TEMP%\rime.weasel"); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + return path; + } + } + + public static void CopyFile(string src, string dest) + { + try + { + File.Copy(src, dest, true); + } + catch + { + for (int i = 0; i < 10; i++) + { + var old = $"{dest}.old.{i}"; + if (PInvoke.MoveFileEx(dest, old, PInvoke.MoveFileFlags.MOVEFILE_REPLACE_EXISTING)) + { + PInvoke.MoveFileEx(old, null, PInvoke.MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT); + break; + } + } + try + { + File.Copy(src, dest, true); + } + catch + { + } + } + } + + public static void DeleteFile(string path) + { + try + { + File.Delete(path); + } + catch + { + for (int i = 0; i < 10; i++) + { + var old = $"{path}.old.{i}"; + if (PInvoke.MoveFileEx(path, old, PInvoke.MoveFileFlags.MOVEFILE_REPLACE_EXISTING)) + { + PInvoke.MoveFileEx(old, null, PInvoke.MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT); + return; + } + } + } + } + } +} diff --git a/Weasel.Setup/Weasel.Setup.csproj b/Weasel.Setup/Weasel.Setup.csproj new file mode 100644 index 000000000..76df0f454 --- /dev/null +++ b/Weasel.Setup/Weasel.Setup.csproj @@ -0,0 +1,20 @@ + + + net48 + true + WinExe + AnyCPU + $(SolutionDir)output\ + false + + + True + + + True + + + + + + diff --git a/WeaselSetup/InstallOptionsDlg.cpp b/WeaselSetup/InstallOptionsDlg.cpp deleted file mode 100644 index 54fce46c8..000000000 --- a/WeaselSetup/InstallOptionsDlg.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "stdafx.h" -#include "InstallOptionsDlg.h" -#include -#include -#pragma comment(lib, "Shell32.lib") - -int uninstall(bool silent); - -InstallOptionsDialog::InstallOptionsDialog() - : installed(false), hant(false), user_dir() {} - -InstallOptionsDialog::~InstallOptionsDialog() {} - -LRESULT InstallOptionsDialog::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { - cn_.Attach(GetDlgItem(IDC_RADIO_CN)); - tw_.Attach(GetDlgItem(IDC_RADIO_TW)); - remove_.Attach(GetDlgItem(IDC_REMOVE)); - default_dir_.Attach(GetDlgItem(IDC_RADIO_DEFAULT_DIR)); - custom_dir_.Attach(GetDlgItem(IDC_RADIO_CUSTOM_DIR)); - dir_.Attach(GetDlgItem(IDC_EDIT_DIR)); - - CheckRadioButton(IDC_RADIO_CN, IDC_RADIO_TW, - (hant ? IDC_RADIO_TW : IDC_RADIO_CN)); - CheckRadioButton( - IDC_RADIO_DEFAULT_DIR, IDC_RADIO_CUSTOM_DIR, - (user_dir.empty() ? IDC_RADIO_DEFAULT_DIR : IDC_RADIO_CUSTOM_DIR)); - dir_.SetWindowTextW(user_dir.c_str()); - - cn_.EnableWindow(!installed); - tw_.EnableWindow(!installed); - remove_.EnableWindow(installed); - dir_.EnableWindow(user_dir.empty() ? FALSE : TRUE); - - button_custom_dir_.Attach(GetDlgItem(IDC_BUTTON_CUSTOM_DIR)); - button_custom_dir_.EnableWindow(user_dir.empty() ? FALSE : TRUE); - - ok_.Attach(GetDlgItem(IDOK)); - if (installed) { - CString str; - str.LoadStringW(IDS_STRING_MODIFY); - ok_.SetWindowTextW(str); - } - - ime_.Attach(GetDlgItem(IDC_CHECK_INSTIME)); - if (installed) - ime_.EnableWindow(FALSE); - - CenterWindow(); - return 0; -} - -LRESULT InstallOptionsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) { - EndDialog(IDCANCEL); - return 0; -} - -LRESULT InstallOptionsDialog::OnOK(WORD, WORD code, HWND, BOOL&) { - hant = (IsDlgButtonChecked(IDC_RADIO_TW) == BST_CHECKED); - old_ime_support = (IsDlgButtonChecked(IDC_CHECK_INSTIME) == BST_CHECKED); - if (IsDlgButtonChecked(IDC_RADIO_CUSTOM_DIR) == BST_CHECKED) { - CStringW text; - dir_.GetWindowTextW(text); - user_dir = text; - } else { - user_dir.clear(); - } - EndDialog(IDOK); - return 0; -} - -LRESULT InstallOptionsDialog::OnRemove(WORD, WORD code, HWND, BOOL&) { - const bool non_silent = false; - uninstall(non_silent); - installed = false; - ime_.EnableWindow(!installed); - CString str; - str.LoadStringW(IDS_STRING_INSTALL); - ok_.SetWindowTextW(str); - cn_.EnableWindow(!installed); - tw_.EnableWindow(!installed); - remove_.EnableWindow(installed); - return 0; -} - -LRESULT InstallOptionsDialog::OnUseDefaultDir(WORD, WORD code, HWND, BOOL&) { - dir_.EnableWindow(FALSE); - dir_.SetWindowTextW(L""); - button_custom_dir_.EnableWindow(FALSE); - return 0; -} - -LRESULT InstallOptionsDialog::OnUseCustomDir(WORD, WORD code, HWND, BOOL&) { - CShellFileOpenDialog fileOpenDlg( - NULL, FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_PICKFOLDERS); - CStringW text; - dir_.GetWindowTextW(text); - if (!text.IsEmpty()) { - PIDLIST_ABSOLUTE pidl; - HRESULT hr = SHParseDisplayName(text, NULL, &pidl, 0, NULL); - if (SUCCEEDED(hr)) { - IShellItem* psi; - hr = SHCreateShellItem(NULL, NULL, pidl, &psi); - if (SUCCEEDED(hr)) { - fileOpenDlg.GetPtr()->SetFolder(psi); - psi->Release(); - } - CoTaskMemFree(pidl); - } - } - if (fileOpenDlg.DoModal(m_hWnd) == IDOK) { - CComPtr psi; - if (SUCCEEDED(fileOpenDlg.GetPtr()->GetResult(&psi))) { - LPWSTR path; - if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &path))) { - dir_.SetWindowTextW(path); - CoTaskMemFree(path); - } - } - } - ok_.SetFocus(); - return 0; -} diff --git a/WeaselSetup/InstallOptionsDlg.h b/WeaselSetup/InstallOptionsDlg.h deleted file mode 100644 index 4a7ba6ecb..000000000 --- a/WeaselSetup/InstallOptionsDlg.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include "resource.h" -#include - -#define MSG_BY_IDS(idInfo, idCap, uType) \ - { \ - CString info, cap; \ - info.LoadStringW(idInfo); \ - cap.LoadStringW(idCap); \ - LANGID langID = GetThreadUILanguage(); \ - MessageBoxExW(NULL, info, cap, uType, langID); \ - } - -#define MSG_ID_CAP(info, idCap, uType) \ - { \ - CString cap; \ - cap.LoadStringW(idCap); \ - LANGID langID = GetThreadUILanguage(); \ - MessageBoxExW(NULL, info, cap, uType, langID); \ - } - -#define MSG_NOT_SILENT_BY_IDS(silent, idInfo, idCap, uType) \ - { \ - if (!silent) \ - MSG_BY_IDS(idInfo, idCap, uType); \ - } -#define MSG_NOT_SILENT_ID_CAP(silent, info, idCap, uType) \ - { \ - if (!silent) \ - MSG_ID_CAP(info, idCap, uType); \ - } - -template -LSTATUS SetRegKeyValue(HKEY rootKey, - const wchar_t* subpath, - const wchar_t* key, - const T& value, - DWORD type, - bool disable_reg_redirect = false) { - HKEY hKey; - auto flag_wow64 = (disable_reg_redirect && is_wow64()) ? KEY_WOW64_64KEY : 0; - LSTATUS ret = - RegOpenKeyEx(rootKey, subpath, 0, KEY_ALL_ACCESS | flag_wow64, &hKey); - if (ret != ERROR_SUCCESS) { - ret = RegCreateKeyEx(rootKey, subpath, 0, NULL, 0, - KEY_ALL_ACCESS | flag_wow64, 0, &hKey, NULL); - if (ret != ERROR_SUCCESS) - return ret; - } - if (ret == ERROR_SUCCESS) { - DWORD dataSize; - const BYTE* dataPtr; - if constexpr (std::is_same::value) { - dataSize = (value.size() + 1) * sizeof(wchar_t); - dataPtr = reinterpret_cast(value.c_str()); - } else if constexpr (std::is_same::value) { - dataSize = (wcslen((wchar_t*)value) + 1) * sizeof(wchar_t); - dataPtr = reinterpret_cast(value); - } else { - dataSize = sizeof(T); - dataPtr = reinterpret_cast(&value); - } - ret = RegSetValueEx(hKey, key, 0, type, dataPtr, dataSize); - RegCloseKey(hKey); - } - return ret; -} - -class InstallOptionsDialog : public CDialogImpl { - public: - enum { IDD = IDD_INSTALL_OPTIONS }; - - InstallOptionsDialog(); - ~InstallOptionsDialog(); - - bool installed; - bool hant; - bool old_ime_support; - std::wstring user_dir; - - protected: - BEGIN_MSG_MAP(InstallOptionsDialog) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - MESSAGE_HANDLER(WM_CLOSE, OnClose) - COMMAND_ID_HANDLER(IDOK, OnOK) - COMMAND_ID_HANDLER(IDC_REMOVE, OnRemove) - COMMAND_ID_HANDLER(IDC_RADIO_DEFAULT_DIR, OnUseDefaultDir) - COMMAND_ID_HANDLER(IDC_RADIO_CUSTOM_DIR, OnUseCustomDir) - COMMAND_ID_HANDLER(IDC_BUTTON_CUSTOM_DIR, OnUseCustomDir) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); - LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); - LRESULT OnOK(WORD, WORD code, HWND, BOOL&); - LRESULT OnRemove(WORD, WORD code, HWND, BOOL&); - LRESULT OnUseDefaultDir(WORD, WORD code, HWND, BOOL&); - LRESULT OnUseCustomDir(WORD, WORD code, HWND, BOOL&); - - CButton cn_; - CButton tw_; - CButton remove_; - CButton default_dir_; - CButton custom_dir_; - CButton ok_; - CButton ime_; - CButton button_custom_dir_; - CEdit dir_; -}; diff --git a/WeaselSetup/WeaselSetup.cpp b/WeaselSetup/WeaselSetup.cpp deleted file mode 100644 index 43286ecfb..000000000 --- a/WeaselSetup/WeaselSetup.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// WeaselSetup.cpp : main source file for WeaselSetup.exe -// - -#include "stdafx.h" - -#include "resource.h" -#include "WeaselUtility.h" -#include - -#include "InstallOptionsDlg.h" - -#include -#pragma comment(lib, "Shcore.lib") -CAppModule _Module; - -static int Run(LPTSTR lpCmdLine); -static bool IsProcAdmin(); -static int RestartAsAdmin(LPTSTR lpCmdLine); - -int WINAPI _tWinMain(HINSTANCE hInstance, - HINSTANCE /*hPrevInstance*/, - LPTSTR lpstrCmdLine, - int /*nCmdShow*/) { - HRESULT hRes = ::CoInitialize(NULL); - ATLASSERT(SUCCEEDED(hRes)); - - AtlInitCommonControls( - ICC_BAR_CLASSES); // add flags to support other controls - - hRes = _Module.Init(NULL, hInstance); - ATLASSERT(SUCCEEDED(hRes)); - - LANGID langId = get_language_id(); - SetThreadUILanguage(langId); - SetThreadLocale(langId); - - int nRet = Run(lpstrCmdLine); - - _Module.Term(); - ::CoUninitialize(); - - return nRet; -} -int install(bool hant, bool silent, bool old_ime_support); -int uninstall(bool silent); -bool has_installed(); - -static std::wstring install_dir() { - WCHAR exe_path[MAX_PATH] = {0}; - GetModuleFileNameW(GetModuleHandle(NULL), exe_path, _countof(exe_path)); - std::wstring dir(exe_path); - size_t pos = dir.find_last_of(L"\\"); - dir.resize(pos); - return dir; -} - -static int CustomInstall(bool installing) { - bool hant = false; - bool silent = false; - bool old_ime_support = false; - std::wstring user_dir; - - const WCHAR KEY[] = L"Software\\Rime\\Weasel"; - HKEY hKey; - LSTATUS ret = RegOpenKey(HKEY_CURRENT_USER, KEY, &hKey); - if (ret == ERROR_SUCCESS) { - WCHAR value[MAX_PATH]; - DWORD len = sizeof(value); - DWORD type = 0; - DWORD data = 0; - ret = - RegQueryValueEx(hKey, L"RimeUserDir", NULL, &type, (LPBYTE)value, &len); - if (ret == ERROR_SUCCESS && type == REG_SZ) { - user_dir = value; - } - len = sizeof(data); - ret = RegQueryValueEx(hKey, L"Hant", NULL, &type, (LPBYTE)&data, &len); - if (ret == ERROR_SUCCESS && type == REG_DWORD) { - hant = (data != 0); - if (installing) - silent = true; - } - RegCloseKey(hKey); - } - bool _has_installed = has_installed(); - if (!silent) { - InstallOptionsDialog dlg; - dlg.installed = _has_installed; - dlg.hant = hant; - dlg.user_dir = user_dir; - if (IDOK != dlg.DoModal()) { - if (!installing) - return 1; // aborted by user - } else { - hant = dlg.hant; - user_dir = dlg.user_dir; - old_ime_support = dlg.old_ime_support; - _has_installed = dlg.installed; - } - } - if (!_has_installed) - if (0 != install(hant, silent, old_ime_support)) - return 1; - - ret = SetRegKeyValue(HKEY_CURRENT_USER, KEY, L"RimeUserDir", user_dir.c_str(), - REG_SZ, false); - if (FAILED(HRESULT_FROM_WIN32(ret))) { - MSG_BY_IDS(IDS_STR_ERR_WRITE_USER_DIR, IDS_STR_INSTALL_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - ret = SetRegKeyValue(HKEY_CURRENT_USER, KEY, L"Hant", (hant ? 1 : 0), - REG_DWORD, false); - if (FAILED(HRESULT_FROM_WIN32(ret))) { - MSG_BY_IDS(IDS_STR_ERR_WRITE_HANT, IDS_STR_INSTALL_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - if (_has_installed) { - std::wstring dir(install_dir()); - std::thread th([dir]() { - ShellExecuteW(NULL, NULL, (dir + L"\\WeaselServer.exe").c_str(), L"/q", - NULL, SW_SHOWNORMAL); - Sleep(500); - ShellExecuteW(NULL, NULL, (dir + L"\\WeaselServer.exe").c_str(), L"", - NULL, SW_SHOWNORMAL); - Sleep(500); - ShellExecuteW(NULL, NULL, (dir + L"\\WeaselDeployer.exe").c_str(), - L"/deploy", NULL, SW_SHOWNORMAL); - }); - th.detach(); - MSG_BY_IDS(IDS_STR_MODIFY_SUCCESS_INFO, IDS_STR_MODIFY_SUCCESS_CAP, - MB_ICONINFORMATION | MB_OK); - } - - return 0; -} - -LPCTSTR GetParamByPrefix(LPCTSTR lpCmdLine, LPCTSTR prefix) { - return (wcsncmp(lpCmdLine, prefix, wcslen(prefix)) == 0) - ? (lpCmdLine + wcslen(prefix)) - : 0; -} - -static int Run(LPTSTR lpCmdLine) { - constexpr bool silent = true; - constexpr bool old_ime_support = false; - bool uninstalling = !wcscmp(L"/u", lpCmdLine); - if (uninstalling) { - if (IsProcAdmin()) - return uninstall(silent); - else - return RestartAsAdmin(lpCmdLine); - } - - if (auto res = GetParamByPrefix(lpCmdLine, L"/userdir:")) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"RimeUserDir", res, REG_SZ); - } - - if (!wcscmp(L"/ls", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"Language", L"chs", REG_SZ); - } else if (!wcscmp(L"/lt", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"Language", L"cht", REG_SZ); - } else if (!wcscmp(L"/le", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"Language", L"eng", REG_SZ); - } - - if (!wcscmp(L"/eu", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel\\Updates", - L"CheckForUpdates", L"1", REG_SZ); - } - if (!wcscmp(L"/du", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel\\Updates", - L"CheckForUpdates", L"0", REG_SZ); - } - - if (!wcscmp(L"/toggleime", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"ToggleImeOnOpenClose", L"yes", REG_SZ); - } - if (!wcscmp(L"/toggleascii", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"ToggleImeOnOpenClose", L"no", REG_SZ); - } - if (!wcscmp(L"/testing", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"UpdateChannel", L"testing", REG_SZ); - } - if (!wcscmp(L"/release", lpCmdLine)) { - return SetRegKeyValue(HKEY_CURRENT_USER, L"Software\\Rime\\weasel", - L"UpdateChannel", L"release", REG_SZ); - } - - if (!IsProcAdmin()) { - return RestartAsAdmin(lpCmdLine); - } - - bool hans = !wcscmp(L"/s", lpCmdLine); - if (hans) - return install(false, silent, old_ime_support); - bool hant = !wcscmp(L"/t", lpCmdLine); - if (hant) - return install(true, silent, old_ime_support); - bool installing = !wcscmp(L"/i", lpCmdLine); - return CustomInstall(installing); -} - -// https://learn.microsoft.com/zh-cn/windows/win32/api/securitybaseapi/nf-securitybaseapi-checktokenmembership -bool IsProcAdmin() { - BOOL b = FALSE; - SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; - PSID AdministratorsGroup; - b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, - &AdministratorsGroup); - - if (b) { - if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) { - b = FALSE; - } - FreeSid(AdministratorsGroup); - } - - return (b); -} - -int RestartAsAdmin(LPTSTR lpCmdLine) { - SHELLEXECUTEINFO execInfo{0}; - TCHAR path[MAX_PATH]; - GetModuleFileName(GetModuleHandle(NULL), path, _countof(path)); - execInfo.lpFile = path; - execInfo.lpParameters = lpCmdLine; - execInfo.lpVerb = _T("runas"); - execInfo.cbSize = sizeof(execInfo); - execInfo.nShow = SW_SHOWNORMAL; - execInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS; - execInfo.hwnd = NULL; - execInfo.hProcess = NULL; - if (::ShellExecuteEx(&execInfo) && execInfo.hProcess != NULL) { - ::WaitForSingleObject(execInfo.hProcess, INFINITE); - DWORD dwExitCode = 0; - ::GetExitCodeProcess(execInfo.hProcess, &dwExitCode); - ::CloseHandle(execInfo.hProcess); - return dwExitCode; - } - return -1; -} diff --git a/WeaselSetup/WeaselSetup.h b/WeaselSetup/WeaselSetup.h deleted file mode 100644 index 99d30f5f1..000000000 --- a/WeaselSetup/WeaselSetup.h +++ /dev/null @@ -1 +0,0 @@ -// WeaselSetup.h diff --git a/WeaselSetup/WeaselSetup.ico b/WeaselSetup/WeaselSetup.ico deleted file mode 100644 index b2a7c748e..000000000 Binary files a/WeaselSetup/WeaselSetup.ico and /dev/null differ diff --git a/WeaselSetup/WeaselSetup.rc b/WeaselSetup/WeaselSetup.rc deleted file mode 100644 index 5a67a1582..000000000 Binary files a/WeaselSetup/WeaselSetup.rc and /dev/null differ diff --git a/WeaselSetup/WeaselSetup.vcxproj b/WeaselSetup/WeaselSetup.vcxproj deleted file mode 100644 index a141fc515..000000000 --- a/WeaselSetup/WeaselSetup.vcxproj +++ /dev/null @@ -1,160 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - 17.0 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095} - WeaselSetup - - - - - Application - true - $(PLATFORM_TOOLSET) - Unicode - - - Application - false - true - $(PLATFORM_TOOLSET) - Unicode - - - - - - - - - - - - - - - false - $(SolutionDir)output\ - $(SolutionDir)msbuild\$(Configuration)\$(Platform)\$(ProjectName)\ - - - true - $(SolutionDir)output\ - $(SolutionDir)msbuild\$(Configuration)\$(Platform)\$(ProjectName)\ - - - - Use - Level3 - MultiThreaded - Sync - - WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) - stdcpp17 - $(SolutionDir)include;$(BOOST_ROOT) - true - - - Windows - Imm32.lib;Kernel32.lib;%(AdditionalDependencies) - $(SolutionDir)output\$(ProjectName)$(TargetExt) - AsInvoker - UseLinkTimeCodeGeneration - - - 0x7804 - $(IntDir);$(SolutionDir)\include\wtl - NDEBUG;%(PreprocessorDefinitions) - - - false - Win32 - NDEBUG;%(PreprocessorDefinitions) - WeaselSetup.h - WeaselSetup_i.c - WeaselSetup_p.c - true - $(IntDir)/WeaselSetup.tlb - - - - PerMonitorHighDPIAware - - - - - Use - Level3 - MultiThreadedDebug - EditAndContinue - EnableFastChecks - Disabled - WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) - stdcpp17 - $(SolutionDir)include;$(BOOST_ROOT) - - - - - Windows - true - Imm32.lib;Kernel32.lib;%(AdditionalDependencies) - $(SolutionDir)output\$(ProjectName)$(TargetExt) - AsInvoker - - - - - 0x7804 - $(IntDir);$(SolutionDir)\include\wtl - _DEBUG;%(PreprocessorDefinitions) - - - false - Win32 - _DEBUG;%(PreprocessorDefinitions) - WeaselSetup.h - WeaselSetup_i.c - WeaselSetup_p.c - true - $(IntDir)/WeaselSetup.tlb - - - - PerMonitorHighDPIAware - - - - - - - Create - Create - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WeaselSetup/WeaselSetup.vcxproj.filters b/WeaselSetup/WeaselSetup.vcxproj.filters deleted file mode 100644 index 84e08d0b9..000000000 --- a/WeaselSetup/WeaselSetup.vcxproj.filters +++ /dev/null @@ -1,52 +0,0 @@ - - - - - {2df80f89-25ee-49a8-a0bf-2dd38ec3b0b2} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {30b9a326-3c70-4dd6-99a0-8fc6015e684b} - h;hpp;hxx;hm;inl;inc - - - {6ed053d1-845d-4449-a84b-43340151cc7c} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/WeaselSetup/imesetup.cpp b/WeaselSetup/imesetup.cpp deleted file mode 100644 index ed48aea99..000000000 --- a/WeaselSetup/imesetup.cpp +++ /dev/null @@ -1,681 +0,0 @@ -#include "stdafx.h" -#include -#include -#include -#include -#include -#include -#include -#include "InstallOptionsDlg.h" - -// {A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A} -static const GUID c_clsidTextService = { - 0xa3f4cded, - 0xb1e9, - 0x41ee, - {0x9c, 0xa6, 0x7b, 0x4d, 0xd, 0xe6, 0xcb, 0xa}}; - -// {3D02CAB6-2B8E-4781-BA20-1C9267529467} -static const GUID c_guidProfile = { - 0x3d02cab6, - 0x2b8e, - 0x4781, - {0xba, 0x20, 0x1c, 0x92, 0x67, 0x52, 0x94, 0x67}}; - -// if in the future, option hant is extended, maybe a function to generate this -// info is required -#define PSZTITLE_HANS \ - L"0804:{A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}{3D02CAB6-2B8E-4781-BA20-" \ - L"1C9267529467}" -#define PSZTITLE_HANT \ - L"0404:{A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}{3D02CAB6-2B8E-4781-BA20-" \ - L"1C9267529467}" -#define ILOT_UNINSTALL 0x00000001 -typedef HRESULT(WINAPI* PTF_INSTALLLAYOUTORTIP)(LPCWSTR psz, DWORD dwFlags); - -#define WEASEL_WER_KEY \ - L"SOFTWARE\\Microsoft\\Windows\\Windows Error " \ - L"Reporting\\LocalDumps\\WeaselServer.exe" - -BOOL copy_file(const std::wstring& src, const std::wstring& dest) { - BOOL ret = CopyFile(src.c_str(), dest.c_str(), FALSE); - if (!ret) { - for (int i = 0; i < 10; ++i) { - std::wstring old = dest + L".old." + std::to_wstring(i); - if (MoveFileEx(dest.c_str(), old.c_str(), MOVEFILE_REPLACE_EXISTING)) { - MoveFileEx(old.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT); - break; - } - } - ret = CopyFile(src.c_str(), dest.c_str(), FALSE); - } - return ret; -} - -BOOL delete_file(const std::wstring& file) { - BOOL ret = DeleteFile(file.c_str()); - if (!ret) { - for (int i = 0; i < 10; ++i) { - std::wstring old = file + L".old." + std::to_wstring(i); - if (MoveFileEx(file.c_str(), old.c_str(), MOVEFILE_REPLACE_EXISTING)) { - MoveFileEx(old.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT); - return TRUE; - } - } - } - return ret; -} - -typedef BOOL(WINAPI* PISWOW64P2)(HANDLE, USHORT*, USHORT*); -BOOL is_arm64_machine() { - PISWOW64P2 fnIsWow64Process2 = (PISWOW64P2)GetProcAddress( - GetModuleHandle(_T("kernel32.dll")), "IsWow64Process2"); - - if (fnIsWow64Process2 == NULL) { - return FALSE; - } - - USHORT processMachine; - USHORT nativeMachine; - - if (!fnIsWow64Process2(GetCurrentProcess(), &processMachine, - &nativeMachine)) { - return FALSE; - } - return nativeMachine == IMAGE_FILE_MACHINE_ARM64; -} - -typedef HRESULT(WINAPI* PISWOWGMS)(USHORT, BOOL*); -typedef UINT(WINAPI* PGSW64DIR2)(LPWSTR, UINT, WORD); -INT get_wow_arm32_system_dir(LPWSTR lpBuffer, UINT uSize) { - PISWOWGMS fnIsWow64GuestMachineSupported = (PISWOWGMS)GetProcAddress( - GetModuleHandle(_T("kernel32.dll")), "IsWow64GuestMachineSupported"); - PGSW64DIR2 fnGetSystemWow64Directory2W = (PGSW64DIR2)GetProcAddress( - GetModuleHandle(_T("kernelbase.dll")), "GetSystemWow64Directory2W"); - - if (fnIsWow64GuestMachineSupported == NULL || - fnGetSystemWow64Directory2W == NULL) { - return 0; - } - - BOOL supported; - if (fnIsWow64GuestMachineSupported(IMAGE_FILE_MACHINE_ARMNT, &supported) != - S_OK) { - return 0; - } - - if (!supported) { - return 0; - } - - return fnGetSystemWow64Directory2W(lpBuffer, uSize, IMAGE_FILE_MACHINE_ARMNT); -} - -typedef int (*ime_register_func)(const std::wstring& ime_path, - bool register_ime, - bool is_wow64, - bool is_wowarm, - bool hant, - bool silent); - -int install_ime_file(std::wstring& srcPath, - const std::wstring& ext, - bool hant, - bool silent, - ime_register_func func) { - WCHAR path[MAX_PATH]; - GetModuleFileNameW(GetModuleHandle(NULL), path, _countof(path)); - - std::wstring srcFileName = L"weasel"; - - srcFileName += ext; - WCHAR drive[_MAX_DRIVE]; - WCHAR dir[_MAX_DIR]; - _wsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), NULL, 0, NULL, - 0); - srcPath = std::wstring(drive) + dir + srcFileName; - - GetSystemDirectoryW(path, _countof(path)); - std::wstring destPath = std::wstring(path) + L"\\weasel" + ext; - - int retval = 0; - // 复制 .dll/.ime 到系统目录 - if (!copy_file(srcPath, destPath)) { - MSG_NOT_SILENT_ID_CAP(silent, destPath.c_str(), IDS_STR_INSTALL_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - retval += func(destPath, true, false, false, hant, silent); - if (is_wow64()) { - PVOID OldValue = NULL; - // PW64DW64FR fnWow64DisableWow64FsRedirection = - // (PW64DW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), - // "Wow64DisableWow64FsRedirection"); PW64RW64FR - // fnWow64RevertWow64FsRedirection = - // (PW64RW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), - // "Wow64RevertWow64FsRedirection"); - if (Wow64DisableWow64FsRedirection(&OldValue) == FALSE) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRCANCELFSREDIRECT, - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - if (is_arm64_machine()) { - WCHAR sysarm32[MAX_PATH]; - if (get_wow_arm32_system_dir(sysarm32, _countof(sysarm32)) > 0) { - // Install the ARM32 version if ARM32 WOW is supported (lower than - // Windows 11 24H2). - std::wstring srcPathARM32 = srcPath; - ireplace_last(srcPathARM32, ext, L"ARM" + ext); - - std::wstring destPathARM32 = std::wstring(sysarm32) + L"\\weasel" + ext; - if (!copy_file(srcPathARM32, destPathARM32)) { - MSG_NOT_SILENT_ID_CAP(silent, destPathARM32.c_str(), - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - retval += func(destPathARM32, true, true, true, hant, silent); - } - - // Then install the ARM64 (and x64) version. - // On ARM64 weasel.dll(ime) is an ARM64X redirection DLL (weaselARM64X). - // When loaded, it will be redirected to weaselARM64.dll(ime) on ARM64 - // processes, and weaselx64.dll(ime) on x64 processes. So we need a total - // of three files. - - std::wstring srcPathX64 = srcPath; - std::wstring destPathX64 = destPath; - ireplace_last(srcPathX64, ext, L"x64" + ext); - ireplace_last(destPathX64, ext, L"x64" + ext); - if (!copy_file(srcPathX64, destPathX64)) { - MSG_NOT_SILENT_ID_CAP(silent, destPathX64.c_str(), - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - std::wstring srcPathARM64 = srcPath; - std::wstring destPathARM64 = destPath; - ireplace_last(srcPathARM64, ext, L"ARM64" + ext); - ireplace_last(destPathARM64, ext, L"ARM64" + ext); - if (!copy_file(srcPathARM64, destPathARM64)) { - MSG_NOT_SILENT_ID_CAP(silent, destPathARM64.c_str(), - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - // Since weaselARM64X is just a redirector we don't have separate - // HANS and HANT variants. - srcPath = std::wstring(drive) + dir + L"weaselARM64X" + ext; - } else { - ireplace_last(srcPath, ext, L"x64" + ext); - } - - if (!copy_file(srcPath, destPath)) { - MSG_NOT_SILENT_ID_CAP(silent, destPath.c_str(), IDS_STR_INSTALL_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - retval += func(destPath, true, true, false, hant, silent); - if (Wow64RevertWow64FsRedirection(OldValue) == FALSE) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRRECOVERFSREDIRECT, - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - } - return retval; -} - -int uninstall_ime_file(const std::wstring& ext, - bool silent, - ime_register_func func) { - int retval = 0; - WCHAR path[MAX_PATH]; - GetSystemDirectoryW(path, _countof(path)); - std::wstring imePath(path); - imePath += L"\\weasel" + ext; - retval += func(imePath, false, false, false, false, silent); - delete_file(imePath); - if (is_wow64()) { - retval += func(imePath, false, true, false, false, silent); - PVOID OldValue = NULL; - if (Wow64DisableWow64FsRedirection(&OldValue) == FALSE) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRCANCELFSREDIRECT, - IDS_STR_UNINSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - if (is_arm64_machine()) { - WCHAR sysarm32[MAX_PATH]; - if (get_wow_arm32_system_dir(sysarm32, _countof(sysarm32)) > 0) { - std::wstring imePathARM32 = std::wstring(sysarm32) + L"\\weasel" + ext; - retval += func(imePathARM32, false, true, true, false, silent); - delete_file(imePathARM32); - } - - std::wstring imePathX64 = imePath; - ireplace_last(imePathX64, ext, L"x64" + ext); - delete_file(imePathX64); - - std::wstring imePathARM64 = imePath; - ireplace_last(imePathARM64, ext, L"ARM64" + ext); - delete_file(imePathARM64); - } - - delete_file(imePath); - if (Wow64RevertWow64FsRedirection(OldValue) == FALSE) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRRECOVERFSREDIRECT, - IDS_STR_UNINSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - } - return retval; -} - -// 注册IME输入法 -int register_ime(const std::wstring& ime_path, - bool register_ime, - bool is_wow64, - bool is_wowarm, - bool hant, - bool silent) { - if (is_wow64) { - return 0; // only once - } - - const WCHAR KEYBOARD_LAYOUTS_KEY[] = - L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"; - const WCHAR PRELOAD_KEY[] = L"Keyboard Layout\\Preload"; - - if (register_ime) { - HKL hKL = ImmInstallIME(ime_path.c_str(), get_weasel_ime_name().c_str()); - if (!hKL) { - // manually register ime - WCHAR hkl_str[16] = {0}; - HKEY hKey; - LSTATUS ret = RegOpenKey(HKEY_LOCAL_MACHINE, KEYBOARD_LAYOUTS_KEY, &hKey); - if (ret == ERROR_SUCCESS) { - for (DWORD k = 0xE0200000 + (hant ? 0x0404 : 0x0804); k <= 0xE0FF0804; - k += 0x10000) { - StringCchPrintfW(hkl_str, _countof(hkl_str), L"%08X", k); - HKEY hSubKey; - ret = RegOpenKey(hKey, hkl_str, &hSubKey); - if (ret == ERROR_SUCCESS) { - WCHAR imeFile[32] = {0}; - DWORD len = sizeof(imeFile); - DWORD type = 0; - ret = RegQueryValueEx(hSubKey, L"Ime File", NULL, &type, - (LPBYTE)imeFile, &len); - if (ret = ERROR_SUCCESS) { - if (_wcsicmp(imeFile, L"weasel.ime") == 0) { - hKL = (HKL)k; // already there - } - } - RegCloseKey(hSubKey); - } else { - // found a spare number to register - ret = RegCreateKey(hKey, hkl_str, &hSubKey); - if (ret == ERROR_SUCCESS) { - const WCHAR ime_file[] = L"weasel.ime"; - RegSetValueEx(hSubKey, L"Ime File", 0, REG_SZ, (LPBYTE)ime_file, - sizeof(ime_file)); - const WCHAR layout_file[] = L"kbdus.dll"; - RegSetValueEx(hSubKey, L"Layout File", 0, REG_SZ, - (LPBYTE)layout_file, sizeof(layout_file)); - const std::wstring layout_text = get_weasel_ime_name(); - RegSetValueEx(hSubKey, L"Layout Text", 0, REG_SZ, - (LPBYTE)layout_text.c_str(), - layout_text.size() * sizeof(wchar_t)); - RegCloseKey(hSubKey); - hKL = (HKL)k; - } - break; - } - } - RegCloseKey(hKey); - } - if (hKL) { - HKEY hPreloadKey; - ret = RegOpenKey(HKEY_CURRENT_USER, PRELOAD_KEY, &hPreloadKey); - if (ret == ERROR_SUCCESS) { - for (size_t i = 1; true; ++i) { - std::wstring number = std::to_wstring(i); - DWORD type = 0; - WCHAR value[32]; - DWORD len = sizeof(value); - ret = RegQueryValueEx(hPreloadKey, number.c_str(), 0, &type, - (LPBYTE)value, &len); - if (ret != ERROR_SUCCESS) { - RegSetValueEx(hPreloadKey, number.c_str(), 0, REG_SZ, - (const BYTE*)hkl_str, - (wcslen(hkl_str) + 1) * sizeof(WCHAR)); - break; - } - } - RegCloseKey(hPreloadKey); - } - } - } - if (!hKL) { - DWORD dwErr = GetLastError(); - WCHAR msg[100]; - CString str; - str.LoadStringW(IDS_STR_ERRREGIME); - StringCchPrintfW(msg, _countof(msg), str, hKL, dwErr); - MSG_NOT_SILENT_ID_CAP(silent, msg, IDS_STR_INSTALL_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - return 0; - } - - // unregister ime - - HKEY hKey; - LSTATUS ret = RegOpenKey(HKEY_LOCAL_MACHINE, KEYBOARD_LAYOUTS_KEY, &hKey); - if (ret != ERROR_SUCCESS) { - MSG_NOT_SILENT_ID_CAP(silent, KEYBOARD_LAYOUTS_KEY, - IDS_STR_UNINSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - for (int i = 0; true; ++i) { - WCHAR subKey[16]; - ret = RegEnumKey(hKey, i, subKey, _countof(subKey)); - if (ret != ERROR_SUCCESS) - break; - - // 中文键盘布局? - if (wcscmp(subKey + 4, L"0804") == 0 || wcscmp(subKey + 4, L"0404") == 0) { - HKEY hSubKey; - ret = RegOpenKey(hKey, subKey, &hSubKey); - if (ret != ERROR_SUCCESS) - continue; - - WCHAR imeFile[32]; - DWORD len = sizeof(imeFile); - DWORD type = 0; - ret = RegQueryValueEx(hSubKey, L"Ime File", NULL, &type, (LPBYTE)imeFile, - &len); - RegCloseKey(hSubKey); - if (ret != ERROR_SUCCESS) - continue; - - // 小狼毫? - if (_wcsicmp(imeFile, L"weasel.ime") == 0) { - DWORD value; - swscanf_s(subKey, L"%x", &value); - UnloadKeyboardLayout((HKL)value); - - RegDeleteKey(hKey, subKey); - - // 移除preload - HKEY hPreloadKey; - ret = RegOpenKey(HKEY_CURRENT_USER, PRELOAD_KEY, &hPreloadKey); - if (ret != ERROR_SUCCESS) - continue; - std::vector preloads; - std::wstring number; - for (size_t i = 1; true; ++i) { - number = std::to_wstring(i); - DWORD type = 0; - WCHAR value[32]; - DWORD len = sizeof(value); - ret = RegQueryValueEx(hPreloadKey, number.c_str(), 0, &type, - (LPBYTE)value, &len); - if (ret != ERROR_SUCCESS) { - if (i > preloads.size()) { - // 删除最大一号注册表值 - number = std::to_wstring(i - 1); - RegDeleteValue(hPreloadKey, number.c_str()); - } - break; - } - if (_wcsicmp(subKey, value) != 0) { - preloads.push_back(value); - } - } - // 重写preloads - for (size_t i = 0; i < preloads.size(); ++i) { - number = std::to_wstring(i + 1); - RegSetValueEx(hPreloadKey, number.c_str(), 0, REG_SZ, - (const BYTE*)preloads[i].c_str(), - (preloads[i].length() + 1) * sizeof(WCHAR)); - } - RegCloseKey(hPreloadKey); - } - } - } - - RegCloseKey(hKey); - return 0; -} - -void enable_profile(BOOL fEnable, bool hant) { - HRESULT hr; - ITfInputProcessorProfiles* pProfiles = NULL; - - hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, - CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, - (LPVOID*)&pProfiles); - - if (SUCCEEDED(hr)) { - LANGID lang_id = hant ? 0x0404 : 0x0804; - if (fEnable) { - pProfiles->EnableLanguageProfile(c_clsidTextService, lang_id, - c_guidProfile, fEnable); - pProfiles->EnableLanguageProfileByDefault(c_clsidTextService, lang_id, - c_guidProfile, fEnable); - } else { - pProfiles->RemoveLanguageProfile(c_clsidTextService, lang_id, - c_guidProfile); - } - - pProfiles->Release(); - } -} - -// 注册TSF输入法 -int register_text_service(const std::wstring& tsf_path, - bool register_ime, - bool is_wow64, - bool is_wowarm32, - bool hant, - bool silent) { - using RegisterServerFunction = HRESULT(STDAPICALLTYPE*)(); - - if (!register_ime) - enable_profile(FALSE, hant); - - std::wstring params = L" \"" + tsf_path + L"\""; - if (!register_ime) { - params = L" /u " + params; // unregister - } - // if (silent) // always silent - { params = L" /s " + params; } - - if (hant) { - if (!SetEnvironmentVariable(L"TEXTSERVICE_PROFILE", L"hant")) { - // bad luck - } - } else { - if (!SetEnvironmentVariable(L"TEXTSERVICE_PROFILE", L"hans")) { - // bad luck - } - } - - std::wstring app = L"regsvr32.exe"; - if (is_wowarm32) { - WCHAR sysarm32[MAX_PATH]; - get_wow_arm32_system_dir(sysarm32, _countof(sysarm32)); - - app = std::wstring(sysarm32) + L"\\" + app; - } - - SHELLEXECUTEINFOW shExInfo = {0}; - shExInfo.cbSize = sizeof(shExInfo); - shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - shExInfo.hwnd = 0; - shExInfo.lpVerb = L"open"; // Operation to perform - shExInfo.lpFile = app.c_str(); // Application to start - shExInfo.lpParameters = params.c_str(); // Additional parameters - shExInfo.lpDirectory = 0; - shExInfo.nShow = SW_SHOW; - shExInfo.hInstApp = 0; - if (ShellExecuteExW(&shExInfo)) { - WaitForSingleObject(shExInfo.hProcess, INFINITE); - CloseHandle(shExInfo.hProcess); - } else { - WCHAR msg[100]; - CString str; - str.LoadStringW(IDS_STR_ERRREGTSF); - StringCchPrintfW(msg, _countof(msg), str, params.c_str()); - // StringCchPrintfW(msg, _countof(msg), L"註冊輸入法錯誤 regsvr32.exe %s", - // params.c_str()); if (!silent) MessageBoxW(NULL, msg, L"安装/卸載失败", - // MB_ICONERROR | MB_OK); - MSG_NOT_SILENT_ID_CAP(silent, msg, IDS_STR_INORUN_FAILED, - MB_ICONERROR | MB_OK); - return 1; - } - - if (register_ime) - enable_profile(TRUE, hant); - - return 0; -} - -int install(bool hant, bool silent, bool old_ime_support) { - std::wstring ime_src_path; - int retval = 0; - if (old_ime_support) { - retval += - install_ime_file(ime_src_path, L".ime", hant, silent, ®ister_ime); - } - retval += install_ime_file(ime_src_path, L".dll", hant, silent, - ®ister_text_service); - - // 写注册表 - WCHAR drive[_MAX_DRIVE]; - WCHAR dir[_MAX_DIR]; - _wsplitpath_s(ime_src_path.c_str(), drive, _countof(drive), dir, - _countof(dir), NULL, 0, NULL, 0); - std::wstring rootDir = std::wstring(drive) + dir; - rootDir.pop_back(); - auto ret = SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_REG_KEY, L"WeaselRoot", - rootDir.c_str(), REG_SZ); - if (FAILED(HRESULT_FROM_WIN32(ret))) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRWRITEWEASELROOT, - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - const std::wstring executable = L"WeaselServer.exe"; - ret = SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_REG_KEY, L"ServerExecutable", - executable.c_str(), REG_SZ); - if (FAILED(HRESULT_FROM_WIN32(ret))) { - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_ERRREGIMEWRITESVREXE, - IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK); - return 1; - } - - // InstallLayoutOrTip - // https://learn.microsoft.com/zh-cn/windows/win32/tsf/installlayoutortip - // example in ref page not right with "*PTF_ INSTALLLAYOUTORTIP" - // space inside should be removed - HMODULE hInputDLL = LoadLibrary(TEXT("input.dll")); - if (hInputDLL) { - PTF_INSTALLLAYOUTORTIP pfnInstallLayoutOrTip; - pfnInstallLayoutOrTip = - (PTF_INSTALLLAYOUTORTIP)GetProcAddress(hInputDLL, "InstallLayoutOrTip"); - if (pfnInstallLayoutOrTip) { - if (hant) - (*pfnInstallLayoutOrTip)(PSZTITLE_HANT, 0); - else - (*pfnInstallLayoutOrTip)(PSZTITLE_HANS, 0); - } - FreeLibrary(hInputDLL); - } - - // https://learn.microsoft.com/zh-cn/windows/win32/wer/collecting-user-mode-dumps - const std::wstring dmpPathW = WeaselLogPath().wstring(); - // DumpFolder - SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_WER_KEY, L"DumpFolder", - dmpPathW.c_str(), REG_SZ, true); - // dump type 0 - SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_WER_KEY, L"DumpType", 0, REG_DWORD, - true); - // CustomDumpFlags, MiniDumpNormal - SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_WER_KEY, L"CustomDumpFlags", 0, - REG_DWORD, true); - // maximium dump count 10 - SetRegKeyValue(HKEY_LOCAL_MACHINE, WEASEL_WER_KEY, L"DumpCount", 10, - REG_DWORD, true); - - if (retval) - return 1; - - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_INSTALL_SUCCESS_INFO, - IDS_STR_INSTALL_SUCCESS_CAP, - MB_ICONINFORMATION | MB_OK); - return 0; -} - -int uninstall(bool silent) { - // 注销输入法 - int retval = 0; - - const WCHAR KEY[] = L"Software\\Rime\\Weasel"; - HKEY hKey; - LSTATUS ret = RegOpenKey(HKEY_CURRENT_USER, KEY, &hKey); - if (ret == ERROR_SUCCESS) { - DWORD type = 0; - DWORD data = 0; - DWORD len = sizeof(data); - ret = RegQueryValueEx(hKey, L"Hant", NULL, &type, (LPBYTE)&data, &len); - if (ret == ERROR_SUCCESS && type == REG_DWORD) { - HMODULE hInputDLL = LoadLibrary(TEXT("input.dll")); - if (hInputDLL) { - PTF_INSTALLLAYOUTORTIP pfnInstallLayoutOrTip; - pfnInstallLayoutOrTip = (PTF_INSTALLLAYOUTORTIP)GetProcAddress( - hInputDLL, "InstallLayoutOrTip"); - if (pfnInstallLayoutOrTip) { - if (data != 0) - (*pfnInstallLayoutOrTip)(PSZTITLE_HANT, ILOT_UNINSTALL); - else - (*pfnInstallLayoutOrTip)(PSZTITLE_HANS, ILOT_UNINSTALL); - } - FreeLibrary(hInputDLL); - } - } - RegCloseKey(hKey); - } - - uninstall_ime_file(L".ime", silent, ®ister_ime); - retval += uninstall_ime_file(L".dll", silent, ®ister_text_service); - - // 清除注册信息 - RegDeleteKey(HKEY_LOCAL_MACHINE, WEASEL_REG_KEY); - RegDeleteKey(HKEY_LOCAL_MACHINE, RIME_REG_KEY); - - // delete WER register, - // "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\Windows Error - // Reporting\\LocalDumps\\WeaselServer.exe" no WOW64 redirect - - auto flag_wow64 = is_wow64() ? KEY_WOW64_64KEY : 0; - RegDeleteKeyEx(HKEY_LOCAL_MACHINE, WEASEL_WER_KEY, flag_wow64, 0); - if (retval) - return 1; - - MSG_NOT_SILENT_BY_IDS(silent, IDS_STR_UNINSTALL_SUCCESS_INFO, - IDS_STR_UNINSTALL_SUCCESS_CAP, - MB_ICONINFORMATION | MB_OK); - return 0; -} - -bool has_installed() { - WCHAR path[MAX_PATH]; - GetSystemDirectory(path, _countof(path)); - std::wstring sysPath(path); - DWORD attr = GetFileAttributesW((sysPath + L"\\weasel.dll").c_str()); - return (attr != INVALID_FILE_ATTRIBUTES && - !(attr & FILE_ATTRIBUTE_DIRECTORY)); -} diff --git a/WeaselSetup/resource.h b/WeaselSetup/resource.h deleted file mode 100644 index 3315f0f94..000000000 --- a/WeaselSetup/resource.h +++ /dev/null @@ -1,48 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by WeaselSetup.rc -// -#define IDI_WEASELSETUP 107 -#define IDR_WEASELSETUP 107 -#define IDR_MAINFRAME 128 -#define IDS_STRING_INSTALL 129 -#define IDS_STRING_MODIFY 130 -#define IDS_STR_INSTALL_FAILED 131 -#define IDS_STR_INSTALL_SUCCESS_CAP 132 -#define IDS_STR_UNINSTALL_SUCCESS_CAP 133 -#define IDS_STR_UNINSTALL_FAILED 134 -#define IDS_STR_ERRCANCELFSREDIRECT 135 -#define IDS_STR_ERRRECOVERFSREDIRECT 136 -#define IDS_STR_ERRREGIME 137 -#define IDS_STR_ERRREGTSF 138 -#define IDS_STR_ERRREGIMEWRITESVREXE 139 -#define IDS_STR_INORUN_FAILED 140 -#define IDS_STR_ERRWRITEWEASELROOT 141 -#define IDS_STR_INSTALL_SUCCESS_INFO 142 -#define IDS_STR_UNINSTALL_SUCCESS_INFO 143 -#define IDS_STR_ERR_WRITE_USER_DIR 144 -#define IDS_STR_ERR_WRITE_HANT 145 -#define IDS_STR_MODIFY_SUCCESS_INFO 146 -#define IDS_STR_MODIFY_SUCCESS_CAP 147 -#define IDD_INSTALL_OPTIONS 201 -#define IDD_DIALOG1 203 -#define IDC_RADIO_CN 1000 -#define IDC_RADIO_TW 1001 -#define IDC_RADIO_DEFAULT_DIR 1002 -#define IDC_RADIO_CUSTOM_DIR 1003 -#define IDC_EDIT_DIR 1004 -#define IDC_REMOVE 1005 -#define IDC_CHECK1 1006 -#define IDC_CHECK_INSTIME 1006 -#define IDC_BUTTON_CUSTOM_DIR 1007 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 205 -#define _APS_NEXT_COMMAND_VALUE 32775 -#define _APS_NEXT_CONTROL_VALUE 1008 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/WeaselSetup/stdafx.cpp b/WeaselSetup/stdafx.cpp deleted file mode 100644 index af034a721..000000000 --- a/WeaselSetup/stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// WeaselSetup.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/WeaselSetup/stdafx.h b/WeaselSetup/stdafx.h deleted file mode 100644 index 1fc659710..000000000 --- a/WeaselSetup/stdafx.h +++ /dev/null @@ -1,34 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -// Change these values to use different versions -#define WINVER 0x0603 -#define _WIN32_WINNT 0x0603 -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#include -#include - -extern CAppModule _Module; - -#include - -#include -#include -#include - -#include -#include -#include - -#if defined _M_IX86 - #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_X64 - #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#else - #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -#endif diff --git a/WeaselSetup/xmake.lua b/WeaselSetup/xmake.lua deleted file mode 100644 index 865392e46..000000000 --- a/WeaselSetup/xmake.lua +++ /dev/null @@ -1,33 +0,0 @@ -target("WeaselSetup") - set_kind("binary") - add_files("./*.cpp") - add_rules("add_rcfiles", "use_weaselconstants", "subwin") - add_links("imm32", "kernel32") - - set_policy("windows.manifest.uac", "invoker") - add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") - add_ldflags("/DEBUG /OPT:REF /OPT:ICF /LARGEADDRESSAWARE /ERRORREPORT:QUEUE") - - before_build(function(target) - local target_dir = path.join(target:targetdir(), target:name()) - if not os.exists(target_dir) then - os.mkdir(target_dir) - end - target:set("targetdir", target_dir) - local level = target:policy("windows.manifest.uac") - if level then - local level_maps = { - invoker = "asInvoker", - admin = "requireAdministrator", - highest = "highestAvailable" - } - assert(level_maps[level], "unknown uac level %s, please set invoker, admin or highest", level) - local ui = target:policy("windows.manifest.uac.ui") or false - target:add("ldflags", "/manifest:embed", {("/manifestuac:level='%s' uiAccess='%s'"):format(level_maps[level], ui)}, {force = true, expand = false}) - end - end) - - after_build(function(target) - os.cp(path.join(target:targetdir(), "WeaselSetup.exe"), "$(projectdir)/output") - os.cp(path.join(target:targetdir(), "WeaselSetup.pdb"), "$(projectdir)/output") - end) diff --git a/build.bat b/build.bat index 152d0de85..cc2da49f9 100644 --- a/build.bat +++ b/build.bat @@ -72,7 +72,7 @@ if not defined PLATFORM_TOOLSET ( if defined DEVTOOLS_PATH set PATH=%DEVTOOLS_PATH%%PATH% set build_config=Release -set build_option=/t:Build +set build_option=/t:Build -restore set build_boost=0 set boost_build_variant=release set build_data=0 diff --git a/clang-format.sh b/clang-format.sh index d1b087b8a..31e54577f 100755 --- a/clang-format.sh +++ b/clang-format.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -WEASEL_SOURCE_PATH="RimeWithWeasel WeaselDeployer WeaselIME WeaselIPC WeaselIPCServer WeaselServer WeaselSetup WeaselTSF WeaselUI include test" +WEASEL_SOURCE_PATH="RimeWithWeasel WeaselDeployer WeaselIME WeaselIPC WeaselIPCServer WeaselServer WeaselTSF WeaselUI include test" # clang format options method="-i" diff --git a/output/install.nsi b/output/install.nsi index 92f5a9b60..29b854fde 100644 --- a/output/install.nsi +++ b/output/install.nsi @@ -260,7 +260,8 @@ program_files: ${Endif} ${Endif} - File "WeaselSetup.exe" + File "Weasel.Setup.exe" + File "TSF.TypeLib.dll" ; shared data files SetOutPath $INSTDIR\data File "data\*.yaml" @@ -287,7 +288,7 @@ program_files: IfErrors +2 0 StrCpy $R2 "/t" - ExecWait '"$INSTDIR\WeaselSetup.exe" $R2' + ExecWait '"$INSTDIR\Weasel.Setup.exe" $R2' ; Write the uninstall keys for Windows WriteRegStr HKLM "${REG_UNINST_KEY}" "DisplayName" "$(DISPLAYNAME)" @@ -350,7 +351,7 @@ Section "Start Menu Shortcuts" CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORUSERFOLDER).lnk" "$INSTDIR\WeaselServer.exe" "/userdir" "$SYSDIR\shell32.dll" 126 CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORAPPFOLDER).lnk" "$INSTDIR\WeaselServer.exe" "/weaseldir" "$SYSDIR\shell32.dll" 19 CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORUPDATER).lnk" "$INSTDIR\WeaselServer.exe" "/update" "$SYSDIR\shell32.dll" 13 - CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORSETUP).lnk" "$INSTDIR\WeaselSetup.exe" "" "$SYSDIR\shell32.dll" 162 + CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORSETUP).lnk" "$INSTDIR\Weasel.Setup.exe" "" "$SYSDIR\shell32.dll" 162 CreateShortCut "$SMPROGRAMS\$(DISPLAYNAME)\$(LNKFORUNINSTALL).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 SectionEnd @@ -363,7 +364,7 @@ Section "Uninstall" ExecWait '"$INSTDIR\WeaselServer.exe" /quit' - ExecWait '"$INSTDIR\WeaselSetup.exe" /u' + ExecWait '"$INSTDIR\Weasel.Setup.exe" /u' ; Remove registry keys DeleteRegKey HKLM SOFTWARE\Rime diff --git a/weasel.sln b/weasel.sln index c248db400..f94ebbb2a 100644 --- a/weasel.sln +++ b/weasel.sln @@ -41,20 +41,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RimeWithWeasel", "RimeWithW EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WeaselDeployer", "WeaselDeployer\WeaselDeployer.vcxproj", "{F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WeaselSetup", "WeaselSetup\WeaselSetup.vcxproj", "{39F6E3F5-8F0B-4023-BC40-A66AE6C37095}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weasel.Setup", "Weasel.Setup\Weasel.Setup.csproj", "{2D028423-929D-4555-A61E-245BD9EC7383}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|Any CPU.ActiveCfg = Debug|x64 + {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|Any CPU.Build.0 = Debug|x64 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|ARM.ActiveCfg = Debug|ARM {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|ARM.Build.0 = Debug|ARM {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -63,6 +67,8 @@ Global {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|Win32.Build.0 = Debug|Win32 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|x64.ActiveCfg = Debug|x64 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Debug|x64.Build.0 = Debug|x64 + {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|Any CPU.ActiveCfg = Release|x64 + {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|Any CPU.Build.0 = Release|x64 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|ARM.ActiveCfg = Release|ARM {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|ARM.Build.0 = Release|ARM {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -71,6 +77,8 @@ Global {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|Win32.Build.0 = Release|Win32 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|x64.ActiveCfg = Release|x64 {FF9B3625-BBD6-4972-8F23-7BA57F3127E8}.Release|x64.Build.0 = Release|x64 + {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|Any CPU.ActiveCfg = Debug|x64 + {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|Any CPU.Build.0 = Debug|x64 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|ARM.ActiveCfg = Debug|ARM {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|ARM.Build.0 = Debug|ARM {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -79,6 +87,8 @@ Global {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|Win32.Build.0 = Debug|Win32 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|x64.ActiveCfg = Debug|x64 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Debug|x64.Build.0 = Debug|x64 + {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|Any CPU.ActiveCfg = Release|x64 + {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|Any CPU.Build.0 = Release|x64 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|ARM.ActiveCfg = Release|ARM {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|ARM.Build.0 = Release|ARM {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -87,6 +97,8 @@ Global {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|Win32.Build.0 = Release|Win32 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|x64.ActiveCfg = Release|x64 {10B3B8BF-7294-4661-9A8A-2FFC920FA2F4}.Release|x64.Build.0 = Release|x64 + {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|Any CPU.ActiveCfg = Debug|x64 + {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|Any CPU.Build.0 = Debug|x64 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|ARM.ActiveCfg = Debug|ARM {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|ARM.Build.0 = Debug|ARM {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -95,6 +107,8 @@ Global {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|Win32.Build.0 = Debug|Win32 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|x64.ActiveCfg = Debug|x64 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Debug|x64.Build.0 = Debug|x64 + {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|Any CPU.ActiveCfg = Release|x64 + {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|Any CPU.Build.0 = Release|x64 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|ARM.ActiveCfg = Release|ARM {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|ARM.Build.0 = Release|ARM {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -103,6 +117,8 @@ Global {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|Win32.Build.0 = Release|Win32 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|x64.ActiveCfg = Release|x64 {CE11A2DF-8D20-4B07-A935-4B0D03F0303D}.Release|x64.Build.0 = Release|x64 + {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|Any CPU.ActiveCfg = Debug|x64 + {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|Any CPU.Build.0 = Debug|x64 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|ARM.ActiveCfg = Debug|ARM {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|ARM.Build.0 = Debug|ARM {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -111,6 +127,8 @@ Global {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|Win32.Build.0 = Debug|Win32 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|x64.ActiveCfg = Debug|x64 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Debug|x64.Build.0 = Debug|x64 + {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|Any CPU.ActiveCfg = Release|x64 + {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|Any CPU.Build.0 = Release|x64 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|ARM.ActiveCfg = Release|ARM {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|ARM.Build.0 = Release|ARM {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -119,84 +137,118 @@ Global {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|Win32.Build.0 = Release|Win32 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|x64.ActiveCfg = Release|x64 {A958FE3D-9F6E-44CB-981E-F2AE181657B3}.Release|x64.Build.0 = Release|x64 + {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|Any CPU.ActiveCfg = Debug|x64 + {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|Any CPU.Build.0 = Debug|x64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|ARM.ActiveCfg = Debug|ARM {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|Win32.ActiveCfg = Debug|Win32 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|Win32.Build.0 = Debug|Win32 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|x64.ActiveCfg = Debug|x64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Debug|x64.Build.0 = Debug|x64 + {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|Any CPU.ActiveCfg = Release|x64 + {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|Any CPU.Build.0 = Release|x64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|ARM.ActiveCfg = Release|ARM {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|ARM64.ActiveCfg = Release|ARM64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|Win32.ActiveCfg = Release|Win32 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|Win32.Build.0 = Release|Win32 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|x64.ActiveCfg = Release|x64 {A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}.Release|x64.Build.0 = Release|x64 + {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|Any CPU.ActiveCfg = Debug|x64 + {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|Any CPU.Build.0 = Debug|x64 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|ARM.ActiveCfg = Debug|ARM {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|ARM64.ActiveCfg = Debug|ARM64 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|Win32.ActiveCfg = Debug|Win32 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|Win32.Build.0 = Debug|Win32 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|x64.ActiveCfg = Debug|x64 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Debug|x64.Build.0 = Debug|x64 + {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|Any CPU.ActiveCfg = Release|x64 + {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|Any CPU.Build.0 = Release|x64 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|ARM.ActiveCfg = Release|ARM {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|ARM64.ActiveCfg = Release|ARM64 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|Win32.ActiveCfg = Release|Win32 {9C1CC4BA-18FF-4890-908E-E545881C5586}.Release|x64.ActiveCfg = Release|x64 + {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|Any CPU.ActiveCfg = Debug|x64 + {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|Any CPU.Build.0 = Debug|x64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|ARM.ActiveCfg = Debug|ARM {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|Win32.ActiveCfg = Debug|Win32 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|Win32.Build.0 = Debug|Win32 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|x64.ActiveCfg = Debug|x64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Debug|x64.Build.0 = Debug|x64 + {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|Any CPU.ActiveCfg = Release|x64 + {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|Any CPU.Build.0 = Release|x64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|ARM.ActiveCfg = Release|ARM {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|ARM64.ActiveCfg = Release|ARM64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|Win32.ActiveCfg = Release|Win32 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|Win32.Build.0 = Release|Win32 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|x64.ActiveCfg = Release|x64 {26930622-CFA2-43DF-A9F3-4AA4A313B2A4}.Release|x64.Build.0 = Release|x64 + {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|Any CPU.ActiveCfg = Debug|x64 + {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|Any CPU.Build.0 = Debug|x64 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|ARM.ActiveCfg = Debug|ARM {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|ARM64.ActiveCfg = Debug|ARM64 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|Win32.ActiveCfg = Debug|Win32 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|Win32.Build.0 = Debug|Win32 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|x64.ActiveCfg = Debug|x64 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Debug|x64.Build.0 = Debug|x64 + {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|Any CPU.ActiveCfg = Release|x64 + {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|Any CPU.Build.0 = Release|x64 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|ARM.ActiveCfg = Release|ARM {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|ARM64.ActiveCfg = Release|ARM64 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|Win32.ActiveCfg = Release|Win32 {CC642427-64D7-44D9-8543-8CBBF981FAE7}.Release|x64.ActiveCfg = Release|x64 + {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|Any CPU.ActiveCfg = Debug|x64 + {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|Any CPU.Build.0 = Debug|x64 {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|ARM.ActiveCfg = Debug|ARM {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|ARM64.ActiveCfg = Debug|ARM64 {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|Win32.ActiveCfg = Debug|Win32 {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|Win32.Build.0 = Debug|Win32 {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|x64.ActiveCfg = Debug|x64 {1C497821-BD63-4F02-9094-32B185B62F23}.Debug|x64.Build.0 = Debug|x64 + {1C497821-BD63-4F02-9094-32B185B62F23}.Release|Any CPU.ActiveCfg = Release|x64 + {1C497821-BD63-4F02-9094-32B185B62F23}.Release|Any CPU.Build.0 = Release|x64 {1C497821-BD63-4F02-9094-32B185B62F23}.Release|ARM.ActiveCfg = Release|ARM {1C497821-BD63-4F02-9094-32B185B62F23}.Release|ARM64.ActiveCfg = Release|ARM64 {1C497821-BD63-4F02-9094-32B185B62F23}.Release|Win32.ActiveCfg = Release|Win32 {1C497821-BD63-4F02-9094-32B185B62F23}.Release|Win32.Build.0 = Release|Win32 {1C497821-BD63-4F02-9094-32B185B62F23}.Release|x64.ActiveCfg = Release|x64 {1C497821-BD63-4F02-9094-32B185B62F23}.Release|x64.Build.0 = Release|x64 + {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|Any CPU.ActiveCfg = Debug|x64 + {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|Any CPU.Build.0 = Debug|x64 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|ARM.ActiveCfg = Debug|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|ARM64.ActiveCfg = Debug|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|Win32.ActiveCfg = Debug|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|Win32.Build.0 = Debug|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|x64.ActiveCfg = Debug|x64 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Debug|x64.Build.0 = Debug|x64 + {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|Any CPU.ActiveCfg = Release|x64 + {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|Any CPU.Build.0 = Release|x64 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|ARM.ActiveCfg = Release|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|ARM64.ActiveCfg = Release|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|Win32.ActiveCfg = Release|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|Win32.Build.0 = Release|Win32 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|x64.ActiveCfg = Release|x64 {F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}.Release|x64.Build.0 = Release|x64 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Debug|ARM.ActiveCfg = Debug|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Debug|ARM64.ActiveCfg = Debug|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Debug|Win32.ActiveCfg = Debug|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Debug|Win32.Build.0 = Debug|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Debug|x64.ActiveCfg = Debug|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Release|ARM.ActiveCfg = Release|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Release|ARM64.ActiveCfg = Release|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Release|Win32.ActiveCfg = Release|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Release|Win32.Build.0 = Release|Win32 - {39F6E3F5-8F0B-4023-BC40-A66AE6C37095}.Release|x64.ActiveCfg = Release|Win32 + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|ARM.Build.0 = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|ARM64.Build.0 = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|Win32.ActiveCfg = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|Win32.Build.0 = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|x64.ActiveCfg = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Debug|x64.Build.0 = Debug|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|Any CPU.Build.0 = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|ARM.ActiveCfg = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|ARM.Build.0 = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|ARM64.ActiveCfg = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|ARM64.Build.0 = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|Win32.ActiveCfg = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|Win32.Build.0 = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|x64.ActiveCfg = Release|Any CPU + {2D028423-929D-4555-A61E-245BD9EC7383}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/xmake.lua b/xmake.lua index 3a61b7fe1..32d4c398c 100644 --- a/xmake.lua +++ b/xmake.lua @@ -51,9 +51,24 @@ if is_arch("x64") or is_arch("x86") then includes("RimeWithWeasel", "WeaselIPCServer", "WeaselServer", "WeaselDeployer") end -if is_arch("x86") then - includes("WeaselSetup") -end +target("Weasel.Setup") + on_build(function(target) + import("package.tools.msbuild") + + local sln = "weasel.sln" + local target_name = string.gsub(target:name(), "%.", "_") + local build_type = is_mode("debug") and "Debug" or "Release" + local platform = "Any CPU" + local configs = { + sln, + "/t:" .. target_name, + "-restore", + "/p:Configuration=" .. build_type, + "/p:Platform=" .. platform + } + + msbuild.build(target, configs) + end) if is_mode("debug") then includes("test/TestWeaselIPC")