Skip to content

Commit

Permalink
Merge branch 'master' into pb
Browse files Browse the repository at this point in the history
  • Loading branch information
fxliang committed Feb 25, 2024
2 parents ec9f4de + e040ab4 commit 28d5ea4
Show file tree
Hide file tree
Showing 24 changed files with 3,098 additions and 22 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/commit-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ jobs:
runs-on: windows-2022
env:
librime_build: 'submodule'
boost_version: 1.83.0
BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_83_0
boost_version: 1.84.0
BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_84_0
steps:
- name: Checkout last commit
uses: actions/checkout@v4
Expand All @@ -45,7 +45,10 @@ jobs:
# install boost if not cached
- name: Install Boost
if: steps.cache-boost.outputs.cache-hit != 'true'
run: .\install_boost.bat
shell: bash
run: |
./install_boost.bat
./build.bat boost arm64
# add msbuild to PATH
- name: Add msbuild to PATH
Expand Down Expand Up @@ -88,7 +91,7 @@ jobs:
shell: bash
run: |
./build.bat data
./build.bat hant
./build.bat hant arm64
./build.bat installer
- name: Compress Debug Symbols
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/release-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
runs-on: windows-2022
env:
librime_build: submodule
boost_version: 1.83.0
BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_83_0
boost_version: 1.84.0
BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_84_0
steps:
- name: Checkout last commit
uses: actions/checkout@v4
Expand All @@ -43,7 +43,10 @@ jobs:
# install boost if not cached
- name: Install Boost
if: steps.cache-boost.outputs.cache-hit != 'true'
run: .\install_boost.bat
shell: bash
run: |
./install_boost.bat
./build.bat boost arm64
# add msbuild to PATH
- name: Add msbuild to PATH
Expand Down Expand Up @@ -92,7 +95,7 @@ jobs:
shell: bash
run: |
./build.bat data
./build.bat hant
./build.bat hant arm64
./build.bat installer
- name: Compress Debug Symbols
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ release-notes.html
*.7z
RELEASE_CHANGELOG.md
deps/
arm64x_wrapper/*.o
arm64x_wrapper/*.dll
arm64x_wrapper/*.ime
arm64x_wrapper/*.lib
arm64x_wrapper/*.exp
170 changes: 170 additions & 0 deletions RimeWithWeasel/RimeWithWeasel.vcxproj

Large diffs are not rendered by default.

413 changes: 413 additions & 0 deletions WeaselIME/WeaselIME.vcxproj

Large diffs are not rendered by default.

226 changes: 226 additions & 0 deletions WeaselIPC/WeaselIPC.vcxproj

Large diffs are not rendered by default.

226 changes: 226 additions & 0 deletions WeaselIPCServer/WeaselIPCServer.vcxproj

Large diffs are not rendered by default.

424 changes: 424 additions & 0 deletions WeaselServer/WeaselServer.vcxproj

Large diffs are not rendered by default.

147 changes: 138 additions & 9 deletions WeaselSetup/imesetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,53 @@ BOOL is_wow64()
return TRUE;
}

typedef int (*ime_register_func)(const std::wstring& ime_path, bool register_ime, bool is_wow64, bool hant, bool silent);
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)
{
Expand All @@ -90,10 +136,9 @@ int install_ime_file(std::wstring& srcPath, const std::wstring& ext, bool hant,
MSG_NOT_SILENT_ID_CAP(silent, destPath.c_str(), IDS_STR_INSTALL_FAILED, MB_ICONERROR | MB_OK);
return 1;
}
retval += func(destPath, true, false, hant, silent);
retval += func(destPath, true, false, false, hant, silent);
if (is_wow64())
{
ireplace_last(srcPath, ext, L"x64" + ext);
PVOID OldValue = NULL;
// PW64DW64FR fnWow64DisableWow64FsRedirection = (PW64DW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "Wow64DisableWow64FsRedirection");
// PW64RW64FR fnWow64RevertWow64FsRedirection = (PW64RW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "Wow64RevertWow64FsRedirection");
Expand All @@ -102,12 +147,66 @@ int install_ime_file(std::wstring& srcPath, const std::wstring& ext, bool hant,
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, hant, silent);
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);
Expand All @@ -124,11 +223,11 @@ int uninstall_ime_file(const std::wstring& ext, bool silent, ime_register_func f
GetSystemDirectoryW(path, _countof(path));
std::wstring imePath(path);
imePath += L"\\weasel" + ext;
retval += func(imePath, false, false, false, silent);
retval += func(imePath, false, false, false, false, silent);
delete_file(imePath);
if (is_wow64())
{
retval += func(imePath, false, true, false, silent);
retval += func(imePath, false, true, false, false, silent);
PVOID OldValue = NULL;
// PW64DW64FR fnWow64DisableWow64FsRedirection = (PW64DW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "Wow64DisableWow64FsRedirection");
// PW64RW64FR fnWow64RevertWow64FsRedirection = (PW64RW64FR)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "Wow64RevertWow64FsRedirection");
Expand All @@ -137,6 +236,26 @@ int uninstall_ime_file(const std::wstring& ext, bool silent, ime_register_func f
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)
{
Expand All @@ -148,7 +267,7 @@ int uninstall_ime_file(const std::wstring& ext, bool silent, ime_register_func f
}

// 注册IME输入法
int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64, bool hant, bool silent)
int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64, bool is_wowarm, bool hant, bool silent)
{
if (is_wow64)
{
Expand Down Expand Up @@ -361,7 +480,7 @@ void enable_profile(BOOL fEnable, bool hant) {
}

// 注册TSF输入法
int register_text_service(const std::wstring& tsf_path, bool register_ime, bool is_wow64, bool hant, bool silent)
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*)();

Expand All @@ -377,12 +496,22 @@ int register_text_service(const std::wstring& tsf_path, bool register_ime, bool
{
params = L" /s " + params;
}

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 = L"regsvr32.exe"; // Application to start
shExInfo.lpFile = app.c_str(); // Application to start
shExInfo.lpParameters = params.c_str(); // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
Expand Down
16 changes: 16 additions & 0 deletions WeaselTSF/Register.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,22 @@ BOOL RegisterServer()
{
dw = GetModuleFileNameA(g_hInst, achFileName, ARRAYSIZE(achFileName));

#ifdef _M_ARM64
{
// On ARM64 we use ARM64X redirection DLL.
// When loaded, weasel.dll will be redirected to weaselARM64.dll on ARM64 processes,
// and weaselx64.dll on x64 processes.
//
// But GetModuleFileNameA will return the actual loaded DLL name aka weaselARM64.dll
// Rewrite the path to point to the redirector.

char wrapperPath[MAX_PATH];
StringCbCatA(achFileName, MAX_PATH, "\\..\\weasel.dll");
GetFullPathNameA(achFileName, MAX_PATH, wrapperPath, NULL);
memcpy(achFileName, wrapperPath, MAX_PATH);
}
#endif

fRet &= RegSetValueExA(hSubKey, NULL, 0, REG_SZ, (BYTE *)achFileName, (strlen(achFileName) + 1) * sizeof(char)) == ERROR_SUCCESS;
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, sizeof TEXTSERVICE_MODEL) == ERROR_SUCCESS;
RegCloseKey(hSubKey);
Expand Down
Loading

0 comments on commit 28d5ea4

Please sign in to comment.