From 69f2c0dc1ce6d9464d9cd803e369425854c9e3fb Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:12:18 +1000 Subject: [PATCH 1/5] docs(windows): add kmtip readme Add a detailed desctription of kmtiparm64x.dll Fixes:#15237 Test-bot: skip --- windows/src/engine/README.md | 6 ++-- windows/src/engine/kmtip/README.md | 54 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 windows/src/engine/kmtip/README.md diff --git a/windows/src/engine/README.md b/windows/src/engine/README.md index 7e5787e43f..23d4c9b5ce 100644 --- a/windows/src/engine/README.md +++ b/windows/src/engine/README.md @@ -33,13 +33,13 @@ This is the public COM API library, used by keyman.exe, kmshell.exe, and various A helper app to refresh Windows language settings, due to a bug in Windows; read ../kmrefresh/kmrefresh.cpp for details. -## kmtip - kmtip.dll | kmtip64.dll | kmtiparm64.dll +## kmtip - kmtip.dll | kmtip64.dll | kmtiparm64x.dll Implementation of a Text Service for the Text Services Framework (TSF). This implementation is named Keyman TIP. Architecturally it sits between the TSF Manager and Keyman.exe -kmtiparm64.dll is built as an Arm64X, file it supports both x64 and arm64 on a -Windows on Arm machine. kmtip64.dll is therefore only used only on Windows x64 Machines. +kmtiparm64x.dll is built as an Arm64X, file it supports both x64 and arm64 on a +Windows on Arm machine. kmtip64.dll is therefore only used only on Windows x64 Machines. See the [kmtip README](kmtip/README.md) for deeper description of kmtiparm64x.dll. ## mcompile - mcompile.exe diff --git a/windows/src/engine/kmtip/README.md b/windows/src/engine/kmtip/README.md new file mode 100644 index 0000000000..da902e0ade --- /dev/null +++ b/windows/src/engine/kmtip/README.md @@ -0,0 +1,54 @@ +This README explains the purpose and architecture of `kmtiparm64x.dll`, for Windows on Arm devices. + +*** + +# kmtiparm64x.dll + +## Overview +`kmtiparm64x.dll` is an **Arm64X** PE (Portable Executable) binary. It is a dual-architecture library capable of servicing both native Arm64 applications and emulated x64 applications on Windows on Arm (WoA) devices. + +This DLL is needed for the Keyman Text Input Processor (TIP) to function correctly across the different binary architectures of applications running on WoA. + +## Background and Problem + +### 1. The "Mixed Architecture" Environment +Windows on Arm devices can run applications of differing architectures simultaneously: +* **Native Arm64 apps:** (e.g., Windows Explorer, Notepad, Edge). +* **Emulated x64 apps:** (e.g., Older desktop applications). +* **Emulated x86 apps:** (32-bit legacy apps). + +A Text Input Processor (TIP) is a plugin that gets **loaded directly into the process space** of the application currently receiving text input. Therefore, the TIP DLL must match the architecture of the application it is running inside. + +### 2. The Single CLSID Problem +On 64-bit Windows, there is typically a single registry entry (COM CLSID) for a 64-bit TIP. +* If we register a standard **Arm64** DLL, x64 apps will crash or fail to load it because they cannot load a pure Arm64 binary. +* If we register a standard **x64** DLL, native Arm64 apps will fail to load it. + +We cannot easily register two different DLLs for the same Class ID to handle this "split" 64-bit world. +Note: For 32-bit there exists a WOW6432Node in windows registry that allows different dlls to registerd for the same Class ID. + +## The Solution: Arm64X +`kmtiparm64x.dll` solves this by using the **Arm64X** format. It contains two complete sets of code within a single file: + +1. **Arm64 Code:** Used when the DLL is loaded by a native Arm64 process. +2. **Arm64EC (Emulation Compatible) Code:** Used when the DLL is loaded by an x64 process. + * *Note: Arm64EC code runs at native speed but uses x64 data structures and calling conventions, allowing it to interoperate seamlessly with the x64 host app.* + +### Runtime Behavior +When an application loads `kmtiparm64x.dll`: +* The Windows loader automatically detects the process architecture. +* **Automatic Selection:** + * If the host process is **x64**, Windows exposes the **Arm64EC** section. The Arm64EC section is built against the **keyman64.dll** keyman engine causing it to be loaded dynamically. + * If the host process is **Arm64**, Windows exposes the **Arm64** section. The **Arm64** section is built against the **keymanarm64.dll** keyman engine causing it to be loaded dynamically. + +* **Transparency:** The host application is unaware that the binary contains code for other platforms; it sees only what it expects + + +## Build Composition +This binary is the result of merging two distinct build targets from the source: +1. **kmtip (arm64)**: The pure native target. +2. **kmtip (arm64EC)**: The hybrid target for x64 compatibility. + +## Usage +* **Registration:** This DLL is registered against the single Keyman TIP CLSID for 64-bit contexts. +* **x86 Support:** Note that 32-bit (x86) applications still require the separate `kmtip.dll` (32-bit x86 build), as they use a completely different registry hive (Wow6432Node). From e17e91e2a6fc0480e129664cf76d2dd9c5b9e1cd Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:11:51 +1000 Subject: [PATCH 2/5] docs(windows): apply review suggestion Co-authored-by: Marc Durdin --- windows/src/engine/kmtip/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/src/engine/kmtip/README.md b/windows/src/engine/kmtip/README.md index da902e0ade..7cf6bbea10 100644 --- a/windows/src/engine/kmtip/README.md +++ b/windows/src/engine/kmtip/README.md @@ -38,7 +38,7 @@ Note: For 32-bit there exists a WOW6432Node in windows registry that allows diff When an application loads `kmtiparm64x.dll`: * The Windows loader automatically detects the process architecture. * **Automatic Selection:** - * If the host process is **x64**, Windows exposes the **Arm64EC** section. The Arm64EC section is built against the **keyman64.dll** keyman engine causing it to be loaded dynamically. + * If the host process is **x64**, Windows exposes the **Arm64EC** section. The **Arm64EC** section is built against the **keyman64.dll** keyman engine causing it to be loaded dynamically. * If the host process is **Arm64**, Windows exposes the **Arm64** section. The **Arm64** section is built against the **keymanarm64.dll** keyman engine causing it to be loaded dynamically. * **Transparency:** The host application is unaware that the binary contains code for other platforms; it sees only what it expects From d6568fb8f1afb5a34031789a1e2cc705f1be4618 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:10:41 +1000 Subject: [PATCH 3/5] docs(windows): describe kmtip as well as the arm64X --- windows/src/engine/kmtip/README.md | 110 +++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 31 deletions(-) diff --git a/windows/src/engine/kmtip/README.md b/windows/src/engine/kmtip/README.md index 7cf6bbea10..0c65d06e73 100644 --- a/windows/src/engine/kmtip/README.md +++ b/windows/src/engine/kmtip/README.md @@ -1,54 +1,102 @@ -This README explains the purpose and architecture of `kmtiparm64x.dll`, for Windows on Arm devices. - -*** - -# kmtiparm64x.dll ## Overview -`kmtiparm64x.dll` is an **Arm64X** PE (Portable Executable) binary. It is a dual-architecture library capable of servicing both native Arm64 applications and emulated x64 applications on Windows on Arm (WoA) devices. -This DLL is needed for the Keyman Text Input Processor (TIP) to function correctly across the different binary architectures of applications running on WoA. +`kmtip` is an implementation of a Text Service for the Text Services Framework +(TSF). This implementation is named Keyman TIP. Architecturally it sits between +the TSF Manager and Keyman.exe. -## Background and Problem +## Background ### 1. The "Mixed Architecture" Environment -Windows on Arm devices can run applications of differing architectures simultaneously: + +Windows on both amd64(x86-64) and on Arm devices can run applications of differing architectures simultaneously: + +On amd64 Devices: +* **Native x64 apps:** (e.g., Windows Explorer, Notepad, Edge). +* **x86 apps (WOW64):** (32-bit legacy apps). + +On Arm Devices: * **Native Arm64 apps:** (e.g., Windows Explorer, Notepad, Edge). * **Emulated x64 apps:** (e.g., Older desktop applications). * **Emulated x86 apps:** (32-bit legacy apps). -A Text Input Processor (TIP) is a plugin that gets **loaded directly into the process space** of the application currently receiving text input. Therefore, the TIP DLL must match the architecture of the application it is running inside. +A Text Input Processor (TIP) is a plugin that gets **loaded directly into the +process space** of the application currently receiving text input. Therefore, +the TIP DLL must match the architecture of the application it is running in. +Setting all this up is different on Windows on Arm and Windows on amd64 +devices. -### 2. The Single CLSID Problem -On 64-bit Windows, there is typically a single registry entry (COM CLSID) for a 64-bit TIP. -* If we register a standard **Arm64** DLL, x64 apps will crash or fail to load it because they cannot load a pure Arm64 binary. -* If we register a standard **x64** DLL, native Arm64 apps will fail to load it. -We cannot easily register two different DLLs for the same Class ID to handle this "split" 64-bit world. -Note: For 32-bit there exists a WOW6432Node in windows registry that allows different dlls to registerd for the same Class ID. +## kmtip.dll and kmtip64.dll - On amd64 Devices -## The Solution: Arm64X -`kmtiparm64x.dll` solves this by using the **Arm64X** format. It contains two complete sets of code within a single file: +On 64-bit Windows, there is a single registry entry (COM CLSID) for a 64-bit +TIP: **kmtip64.dll**. -1. **Arm64 Code:** Used when the DLL is loaded by a native Arm64 process. -2. **Arm64EC (Emulation Compatible) Code:** Used when the DLL is loaded by an x64 process. - * *Note: Arm64EC code runs at native speed but uses x64 data structures and calling conventions, allowing it to interoperate seamlessly with the x64 host app.* +For 32-bit applications, there exists a WOW6432Node in the Windows registry +that allows a different DLL to be registered for the same Class ID: +**kmtip.dll**. It is essentially two views of the registry depending on whether +the application is 32-bit or 64-bit. + + +## kmtiparm64x.dll - Arm64 Devices + +### Single Registry Entry Problem + +On Windows on Arm there is a problem because there is only a single registry +entry for the 64-bit CLSID. This means it is not possible to register both an +amd64 DLL and an Arm64 DLL, for example **kmtip64.dll** and +**kmtiparm64.dll**. + +* If we register a standard **Arm64** DLL, x64 apps will crash or fail to load + it because they cannot load a pure Arm64 binary. +* If we register a standard **x64** DLL, native Arm64 apps will fail to load + it. + +### The Solution: Arm64X + +**Arm64X** is a PE (Portable Executable) binary format. It is a dual-architecture +library +capable of servicing both native Arm64 applications and emulated x64 +applications on Windows on Arm (WoA) devices. + +`kmtiparm64x.dll` solves this problem by using the **Arm64X** format. It +contains two complete sets of code within a single file: + +1. **Arm64 Code:** Used when the DLL is loaded by a native Arm64 process. +2. **Arm64EC (Emulation Compatible) Code:** Used when the DLL is loaded by an + x64 process. + * *Note: Arm64EC code runs at native speed but uses x64 data structures and + calling conventions, allowing it to interoperate seamlessly with the x64 + host app.* ### Runtime Behavior + When an application loads `kmtiparm64x.dll`: + * The Windows loader automatically detects the process architecture. * **Automatic Selection:** - * If the host process is **x64**, Windows exposes the **Arm64EC** section. The **Arm64EC** section is built against the **keyman64.dll** keyman engine causing it to be loaded dynamically. - * If the host process is **Arm64**, Windows exposes the **Arm64** section. The **Arm64** section is built against the **keymanarm64.dll** keyman engine causing it to be loaded dynamically. + * If the host process is **x64**, Windows exposes the **Arm64EC** section. + The **Arm64EC** section is built against the **keyman64.dll** Keyman engine, + causing it to be loaded dynamically. + * If the host process is **Arm64**, Windows exposes the **Arm64** section. The + **Arm64** section is built against the **keymanarm64.dll** Keyman engine, + causing it to be loaded dynamically. -* **Transparency:** The host application is unaware that the binary contains code for other platforms; it sees only what it expects +* **Transparency:** The host application is unaware that the binary contains + code for other platforms; it sees only what it expects +### Build Composition -## Build Composition -This binary is the result of merging two distinct build targets from the source: -1. **kmtip (arm64)**: The pure native target. -2. **kmtip (arm64EC)**: The hybrid target for x64 compatibility. +This binary is the result of merging two distinct build targets from the +source: -## Usage -* **Registration:** This DLL is registered against the single Keyman TIP CLSID for 64-bit contexts. -* **x86 Support:** Note that 32-bit (x86) applications still require the separate `kmtip.dll` (32-bit x86 build), as they use a completely different registry hive (Wow6432Node). +1. **kmtip (arm64)**: The pure native target. +2. **kmtip (arm64EC)**: The hybrid target for x64 compatibility. + +### Usage + +* **Registration:** This DLL is registered against the single Keyman TIP CLSID + for 64-bit contexts. +* **x86 Support:** Note that 32-bit (x86) applications still require the + separate `kmtip.dll` (32-bit x86 build), as they use a completely different + registry hive (WOW6432Node). From 4e7d2dddca069ab8824f6dd3590f9d818e4556e6 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 12 Dec 2025 17:24:29 +1000 Subject: [PATCH 4/5] feat(windows): review comments Co-authored-by: Eberhard Beilharz --- windows/src/engine/README.md | 5 +++-- windows/src/engine/kmtip/README.md | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/windows/src/engine/README.md b/windows/src/engine/README.md index 23d4c9b5ce..3436f07b05 100644 --- a/windows/src/engine/README.md +++ b/windows/src/engine/README.md @@ -38,8 +38,9 @@ A helper app to refresh Windows language settings, due to a bug in Windows; read Implementation of a Text Service for the Text Services Framework (TSF). This implementation is named Keyman TIP. Architecturally it sits between the TSF Manager and Keyman.exe -kmtiparm64x.dll is built as an Arm64X, file it supports both x64 and arm64 on a -Windows on Arm machine. kmtip64.dll is therefore only used only on Windows x64 Machines. See the [kmtip README](kmtip/README.md) for deeper description of kmtiparm64x.dll. +kmtiparm64x.dll is built as an Arm64X file. It supports both x64 and arm64 on a +Windows on Arm machine. kmtip64.dll is therefore only used on Windows x64 Machines. +See the [kmtip README](kmtip/README.md) for deeper description of kmtip*.dll. ## mcompile - mcompile.exe diff --git a/windows/src/engine/kmtip/README.md b/windows/src/engine/kmtip/README.md index 0c65d06e73..169a728dbb 100644 --- a/windows/src/engine/kmtip/README.md +++ b/windows/src/engine/kmtip/README.md @@ -2,8 +2,8 @@ ## Overview `kmtip` is an implementation of a Text Service for the Text Services Framework -(TSF). This implementation is named Keyman TIP. Architecturally it sits between -the TSF Manager and Keyman.exe. +(TSF). This implementation is named Keyman Text Input Processor (TIP). Architecturally +it sits between the TSF Manager and Keyman.exe. ## Background @@ -45,7 +45,8 @@ the application is 32-bit or 64-bit. On Windows on Arm there is a problem because there is only a single registry entry for the 64-bit CLSID. This means it is not possible to register both an amd64 DLL and an Arm64 DLL, for example **kmtip64.dll** and -**kmtiparm64.dll**. +**kmtiparm64.dll**. (For 32-bit apps there is still the WOW6432Node that +registers `kmtip.dll`.) * If we register a standard **Arm64** DLL, x64 apps will crash or fail to load it because they cannot load a pure Arm64 binary. @@ -55,8 +56,7 @@ amd64 DLL and an Arm64 DLL, for example **kmtip64.dll** and ### The Solution: Arm64X **Arm64X** is a PE (Portable Executable) binary format. It is a dual-architecture -library -capable of servicing both native Arm64 applications and emulated x64 +library capable of servicing both native Arm64 applications and emulated x64 applications on Windows on Arm (WoA) devices. `kmtiparm64x.dll` solves this problem by using the **Arm64X** format. It @@ -87,8 +87,8 @@ When an application loads `kmtiparm64x.dll`: ### Build Composition -This binary is the result of merging two distinct build targets from the -source: +The `kmtiparm64x.dll` binary is the result of merging two distinct build +targets from the source: 1. **kmtip (arm64)**: The pure native target. 2. **kmtip (arm64EC)**: The hybrid target for x64 compatibility. From be3fbf4845d56b63db0486c519d7bbdb8ff92062 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 12 Dec 2025 17:41:56 +1000 Subject: [PATCH 5/5] docs(windows): review comments --- windows/src/engine/kmtip/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/windows/src/engine/kmtip/README.md b/windows/src/engine/kmtip/README.md index 169a728dbb..d82c974e62 100644 --- a/windows/src/engine/kmtip/README.md +++ b/windows/src/engine/kmtip/README.md @@ -31,19 +31,22 @@ devices. On 64-bit Windows, there is a single registry entry (COM CLSID) for a 64-bit TIP: **kmtip64.dll**. +`HKLM\SOFTWARE\Classes\CLSID` For 32-bit applications, there exists a WOW6432Node in the Windows registry that allows a different DLL to be registered for the same Class ID: -**kmtip.dll**. It is essentially two views of the registry depending on whether +**kmtip.dll**. +`HKLM\SOFTWARE\WOW6432Node\Classes\CLSID` +It is essentially two views of the registry depending on whether the application is 32-bit or 64-bit. ## kmtiparm64x.dll - Arm64 Devices -### Single Registry Entry Problem +### Single Registry Entry Problem for the two 64-bit architecture On Windows on Arm there is a problem because there is only a single registry -entry for the 64-bit CLSID. This means it is not possible to register both an +entry for the **64-bit** CLSID. This means it is not possible to register both an amd64 DLL and an Arm64 DLL, for example **kmtip64.dll** and **kmtiparm64.dll**. (For 32-bit apps there is still the WOW6432Node that registers `kmtip.dll`.)