diff --git a/openless-all/app/scripts/windows-ime-install-smoke.ps1 b/openless-all/app/scripts/windows-ime-install-smoke.ps1 index fd9d7e1b..4b0b5dd3 100644 --- a/openless-all/app/scripts/windows-ime-install-smoke.ps1 +++ b/openless-all/app/scripts/windows-ime-install-smoke.ps1 @@ -33,6 +33,25 @@ function Test-IsAdministrator { return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } +function Join-ProcessArguments { + param( + [string[]]$ArgumentList = @() + ) + + $quoted = foreach ($argument in $ArgumentList) { + if ($argument.Length -eq 0) { + '""' + } elseif ($argument -notmatch '[\s"]') { + $argument + } else { + $escaped = $argument -replace '(\\*)"', '$1$1\"' + $escaped = $escaped -replace '(\\+)$', '$1$1' + '"' + $escaped + '"' + } + } + return ($quoted -join " ") +} + function Invoke-CheckedProcess { param( [Parameter(Mandatory = $true)] @@ -42,8 +61,9 @@ function Invoke-CheckedProcess { [string]$Label ) - Write-Host "[run] $Label`: $FilePath $($ArgumentList -join ' ')" - $process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Wait -PassThru + $commandLine = Join-ProcessArguments $ArgumentList + Write-Host "[run] $Label`: $FilePath $commandLine" + $process = Start-Process -FilePath $FilePath -ArgumentList $commandLine -Wait -PassThru if ($process.ExitCode -ne 0) { throw "$Label failed with exit code $($process.ExitCode)" } diff --git a/openless-all/app/scripts/windows-package-msvc.test.mjs b/openless-all/app/scripts/windows-package-msvc.test.mjs index 339037cc..167bfd18 100644 --- a/openless-all/app/scripts/windows-package-msvc.test.mjs +++ b/openless-all/app/scripts/windows-package-msvc.test.mjs @@ -128,8 +128,13 @@ assert.match(nsisHook, /File \/oname=OpenLessIme\.dll/, "NSIS should embed OpenL assert.match(nsisHook, /Sysnative\\regsvr32\.exe/, "NSIS should use 64-bit regsvr32 for the x64 IME"); assert.match(nsisHook, /SysWOW64\\regsvr32\.exe/, "NSIS should use 32-bit regsvr32 for the x86 IME"); assert.match(nsisHook, /Abort/, "NSIS install should fail if TSF registration fails"); +assert.match(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x64 unregistration"/, "NSIS uninstall should fail if x64 TSF unregistration fails"); +assert.match(nsisHook, /OPENLESS_IME_ABORT_IF_FAILED \$0 "x86 unregistration"/, "NSIS uninstall should fail if x86 TSF unregistration fails"); assert.match(imeInstallSmoke, /\[ValidateSet\("nsis", "msi"\)\]/, "install smoke should support both Windows installers"); +assert.match(imeInstallSmoke, /Join-ProcessArguments/, "install smoke should quote process arguments before Start-Process"); +assert.match(imeInstallSmoke, /\$commandLine = Join-ProcessArguments \$ArgumentList/, "install smoke should build a single quoted command line"); +assert.match(imeInstallSmoke, /Start-Process -FilePath \$FilePath -ArgumentList \$commandLine/, "install smoke should pass a single quoted command line to Start-Process"); assert.match(imeInstallSmoke, /OpenLessImeSubmit/, "install smoke should preserve TSF backend context"); assert.match(imeInstallSmoke, /Software\\Classes\\CLSID\\\{6B9F3F4F-5EE7-42D6-9C61-9F80B03A5D7D\}\\InprocServer32/, "install smoke should check x64 COM registration"); assert.match(imeInstallSmoke, /Software\\WOW6432Node\\Classes\\CLSID\\\{6B9F3F4F-5EE7-42D6-9C61-9F80B03A5D7D\}\\InprocServer32/, "install smoke should check x86 COM registration"); 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 18cbc038..ca3ce498 100644 --- a/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh +++ b/openless-all/app/src-tauri/nsis/openless-ime-hooks.nsh @@ -33,14 +33,14 @@ ExecWait '"$WINDIR\System32\regsvr32.exe" /s /u "$INSTDIR\windows-ime\x64\OpenLessIme.dll"' $0 ${EnableX64FSRedirection} ${EndIf} - DetailPrint "OpenLess x64 TSF IME unregister exit code $0" + !insertmacro OPENLESS_IME_ABORT_IF_FAILED $0 "x64 unregistration" ${EndIf} !macroend !macro OPENLESS_IME_UNREGISTER_X86 DetailPrint "Unregistering OpenLess x86 TSF IME" ExecWait '"$WINDIR\SysWOW64\regsvr32.exe" /s /u "$INSTDIR\windows-ime\x86\OpenLessIme.dll"' $0 - DetailPrint "OpenLess x86 TSF IME unregister exit code $0" + !insertmacro OPENLESS_IME_ABORT_IF_FAILED $0 "x86 unregistration" !macroend !macro NSIS_HOOK_PREINSTALL