From ec9f658a1d81f76fc99f7c70f0397c7769e54a64 Mon Sep 17 00:00:00 2001 From: millionart Date: Tue, 5 May 2026 19:31:49 +0800 Subject: [PATCH] fix: harden Windows IME installer smoke --- .../app/scripts/windows-ime-install-smoke.ps1 | 2 +- .../app/scripts/windows-package-msvc.test.mjs | 3 +++ .../app/src-tauri/nsis/openless-ime-hooks.nsh | 25 +++++++++++-------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/openless-all/app/scripts/windows-ime-install-smoke.ps1 b/openless-all/app/scripts/windows-ime-install-smoke.ps1 index 4b0b5dd3..a3b25de7 100644 --- a/openless-all/app/scripts/windows-ime-install-smoke.ps1 +++ b/openless-all/app/scripts/windows-ime-install-smoke.ps1 @@ -158,7 +158,7 @@ function Assert-OpenLessImeInstalled { Assert-RegistryKey -View Registry64 -SubKey "Software\Microsoft\CTF\TIP\$TextServiceClsid\Category\Category\$SystrayCategoryGuid\$TextServiceClsid" -Label "TSF systray category" foreach ($key in $ExpectedBackendKeys) { - Write-Host "[trace] backend-required key: HKLM\$key" + Assert-RegistryKey -View Registry64 -SubKey $key -Label "backend-required" } Write-Host "[ok] Windows IME backend would report installed" diff --git a/openless-all/app/scripts/windows-package-msvc.test.mjs b/openless-all/app/scripts/windows-package-msvc.test.mjs index 361eef9d..d5a17eed 100644 --- a/openless-all/app/scripts/windows-package-msvc.test.mjs +++ b/openless-all/app/scripts/windows-package-msvc.test.mjs @@ -131,6 +131,7 @@ assert.match(nsisHook, /System32\\regsvr32\.exe[\s\S]*windows-ime\\x86\\OpenLess assert.match(nsisHook, /Abort/, "NSIS install should fail if TSF registration fails"); assert.match(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x64 registration"/, "NSIS install should fail if x64 TSF registration fails"); assert.match(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x86 registration"/, "NSIS install should fail if x86 TSF registration fails"); +assert.match(nsisHook, /OPENLESS_IME_REGISTER_X86[\s\S]*\$\{If\} \$0 != 0[\s\S]*StrCpy \$1 \$0[\s\S]*OPENLESS_IME_UNREGISTER_X64[\s\S]*StrCpy \$0 \$1[\s\S]*OPENLESS_IME_ABORT_IF_FAILED \$0 "x86 registration"/, "NSIS install should roll back x64 registration before aborting on x86 registration failure"); assert.doesNotMatch(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x64 unregistration"/, "NSIS uninstall should not fail if x64 TSF unregistration fails"); assert.doesNotMatch(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x86 unregistration"/, "NSIS uninstall should not fail if x86 TSF unregistration fails"); assert.match(nsisHook, /OpenLess x64 TSF IME unregister exit code \$0/, "NSIS uninstall should log x64 TSF unregistration failures"); @@ -145,6 +146,8 @@ assert.match(imeInstallSmoke, /Software\\Classes\\CLSID\\\{6B9F3F4F-5EE7-42D6-9C assert.match(imeInstallSmoke, /Software\\WOW6432Node\\Classes\\CLSID\\\{6B9F3F4F-5EE7-42D6-9C61-9F80B03A5D7D\}\\InprocServer32/, "install smoke should check x86 COM registration"); assert.match(imeInstallSmoke, /LanguageProfile\\0x00000804\\\{9B5F5E04-23F6-47DA-9A26-D221F6C3F02E\}/, "install smoke should check the TSF language profile"); assert.match(imeInstallSmoke, /Category\\Category\\\{34745C63-B2F0-4784-8B67-5E12C8701A31\}/, "install smoke should check the keyboard TSF category"); +assert.match(imeInstallSmoke, /foreach \(\$key in \$ExpectedBackendKeys\) \{[\s\S]*Assert-RegistryKey -View Registry64 -SubKey \$key[\s\S]*\}/, "install smoke should assert every backend-required registry key exists"); +assert.doesNotMatch(imeInstallSmoke, /foreach \(\$key in \$ExpectedBackendKeys\) \{[\s\S]*Write-Host "\[trace\] backend-required key: HKLM\\\$key"[\s\S]*\}/, "install smoke must not only trace backend-required registry keys"); assert.match(ciWorkflow, /windows-ime-install-smoke\.ps1[\s\S]*-InstallerKind nsis/, "CI should install and verify the NSIS artifact"); assert.match(ciWorkflow, /windows-ime-install-smoke\.ps1[\s\S]*-InstallerKind msi/, "CI should install and verify the MSI artifact"); assert.match(ciWorkflow, /InstallerKind nsis[\s\S]*\$LASTEXITCODE -ne 0[\s\S]*NSIS installer smoke failed/, "CI should fail immediately when the NSIS smoke run fails"); diff --git a/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh b/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh index 24b7629b..34e7ab1d 100644 --- a/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh +++ b/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh @@ -18,16 +18,6 @@ ${EndIf} !macroend -!macro OPENLESS_IME_REGISTER_X86 - DetailPrint "Registering OpenLess x86 TSF IME" - ${If} ${RunningX64} - ExecWait '"$WINDIR\SysWOW64\regsvr32.exe" /s "$INSTDIR\windows-ime\x86\OpenLessIme.dll"' $0 - ${Else} - ExecWait '"$WINDIR\System32\regsvr32.exe" /s "$INSTDIR\windows-ime\x86\OpenLessIme.dll"' $0 - ${EndIf} - !insertmacro OPENLESS_IME_ABORT_IF_FAILED $0 "x86 registration" -!macroend - !macro OPENLESS_IME_UNREGISTER_X64 ${If} ${RunningX64} DetailPrint "Unregistering OpenLess x64 TSF IME" @@ -51,6 +41,21 @@ DetailPrint "OpenLess x86 TSF IME unregister exit code $0" !macroend +!macro OPENLESS_IME_REGISTER_X86 + DetailPrint "Registering OpenLess x86 TSF IME" + ${If} ${RunningX64} + ExecWait '"$WINDIR\SysWOW64\regsvr32.exe" /s "$INSTDIR\windows-ime\x86\OpenLessIme.dll"' $0 + ${Else} + ExecWait '"$WINDIR\System32\regsvr32.exe" /s "$INSTDIR\windows-ime\x86\OpenLessIme.dll"' $0 + ${EndIf} + ${If} $0 != 0 + StrCpy $1 $0 + !insertmacro OPENLESS_IME_UNREGISTER_X64 + StrCpy $0 $1 + ${EndIf} + !insertmacro OPENLESS_IME_ABORT_IF_FAILED $0 "x86 registration" +!macroend + !macro NSIS_HOOK_PREINSTALL SetOutPath "$INSTDIR\windows-ime\x64" File /oname=OpenLessIme.dll "$%OPENLESS_IME_DLL_X64%"