Skip to content

Commit 82dca34

Browse files
authored
Always use CustomAction to register COM DLLs (#1500)
This is a preparation to change the Mozc's installation directory from "Program Files (x86)" to "Program Files" not only for new installations but also for existing installations (#1086). The ground truth is that TSF-based IMEs need to register their COM DLLs to the registry key "HKEY_CLASSES_ROOT\CLSID", and there are basically two ways to do it in the installer (MSI file): A. Use custom action in WiX, which calls Win32 registry APIs to manually manipulate the registry. B. Declare COM information in the pre-defined database of MSI file, and let MSI engine to register the COM DLLs. Mozc started with the method A, then switched to the method B [1], then switched back to methods A only for universal installer [2], and now is fully switching back to the method A for all the installers with this commit. The problem is that the method B is feasible only when the COM DLL file name and destination path are determined at the build time, and it is not the case for both universal installer and installation directory migration. Now that all the installers we build (x64 only, ARM64 only, and universal) hit such limitation, there is no reason to keep the method B code path. [1]: e467907 [2]: 96bab12 PiperOrigin-RevId: 913011425
1 parent 06fea77 commit 82dca34

6 files changed

Lines changed: 68 additions & 71 deletions

File tree

src/win32/base/tsf_registrar.cc

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ constexpr wchar_t kTipInProcServer32[] = L"InProcServer32";
5656
constexpr wchar_t kTipThreadingModel[] = L"ThreadingModel";
5757
constexpr wchar_t kTipTextServiceModel[] = L"Apartment";
5858

59+
constexpr REGSAM AdjustRegFlagBitness(REGSAM base_flags,
60+
COMServerBitness bitness) {
61+
REGSAM flags = base_flags;
62+
switch (bitness) {
63+
case COMServerBitness::k32bit:
64+
flags |= KEY_WOW64_32KEY;
65+
flags &= ~KEY_WOW64_64KEY;
66+
break;
67+
case COMServerBitness::k64bit:
68+
flags |= KEY_WOW64_64KEY;
69+
flags &= ~KEY_WOW64_32KEY;
70+
break;
71+
}
72+
return flags;
73+
}
74+
5975
// The categories this text service is registered under.
6076
// This needs to be const as the included constants are defined as const.
6177
const GUID kCategories[] = {
@@ -78,10 +94,12 @@ const GUID kCategories[] = {
7894
// * The description of this module;
7995
// * The path to this module, and;
8096
// * The type of this module (threading moddel).
81-
HRESULT TsfRegistrar::RegisterCOMServer(const wchar_t* path, DWORD length) {
97+
HRESULT TsfRegistrar::RegisterCOMServer(const wchar_t* path, DWORD length,
98+
COMServerBitness bitness) {
8299
if (length == 0) {
83100
return E_OUTOFMEMORY;
84101
}
102+
const REGSAM reg_flags = AdjustRegFlagBitness(KEY_READ | KEY_WRITE, bitness);
85103
// Open the registry key "HKEY_CLASSES_ROOT\CLSID", which stores information
86104
// of all COM modules installed in this PC.
87105
// To register a COM module to Windows, we should create a key of its GUID
@@ -92,7 +110,7 @@ HRESULT TsfRegistrar::RegisterCOMServer(const wchar_t* path, DWORD length) {
92110
// * The threading model of this module.
93111
ATL::CRegKey parent;
94112
LONG result = parent.Open(HKEY_CLASSES_ROOT, &kTipInfoKeyPrefix[0],
95-
KEY_READ | KEY_WRITE);
113+
reg_flags);
96114
if (result != ERROR_SUCCESS) {
97115
return HRESULT_FROM_WIN32(result);
98116
}
@@ -107,7 +125,7 @@ HRESULT TsfRegistrar::RegisterCOMServer(const wchar_t* path, DWORD length) {
107125

108126
ATL::CRegKey key;
109127
result = key.Create(parent, &ime_key[0], REG_NONE, REG_OPTION_NON_VOLATILE,
110-
KEY_READ | KEY_WRITE, nullptr, nullptr);
128+
reg_flags, nullptr, nullptr);
111129
if (result != ERROR_SUCCESS) {
112130
return HRESULT_FROM_WIN32(result);
113131
}
@@ -138,7 +156,7 @@ HRESULT TsfRegistrar::RegisterCOMServer(const wchar_t* path, DWORD length) {
138156
// Unregisters this module from Windows.
139157
// This function just deletes the all registry keys under
140158
// "HKCR\CLSID\{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}".
141-
void TsfRegistrar::UnregisterCOMServer() {
159+
void TsfRegistrar::UnregisterCOMServer(COMServerBitness bitness) {
142160
// Create the registry key for this COM server.
143161
// Only Administrators can create keys under HKEY_CLASSES_ROOT.
144162
wchar_t ime_key[64] = {};
@@ -147,9 +165,10 @@ void TsfRegistrar::UnregisterCOMServer() {
147165
return;
148166
}
149167

168+
const REGSAM reg_flags = AdjustRegFlagBitness(KEY_READ | KEY_WRITE, bitness);
150169
ATL::CRegKey key;
151-
HRESULT result =
152-
key.Open(HKEY_CLASSES_ROOT, &kTipInfoKeyPrefix[0], KEY_READ | KEY_WRITE);
170+
HRESULT result = key.Open(HKEY_CLASSES_ROOT, &kTipInfoKeyPrefix[0],
171+
reg_flags);
153172
if (result != ERROR_SUCCESS) {
154173
return;
155174
}

src/win32/base/tsf_registrar.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
namespace mozc {
3838
namespace win32 {
3939

40+
enum class COMServerBitness {
41+
k64bit,
42+
k32bit,
43+
};
44+
4045
// Registers Mozc as a text input processor or unregister.
4146
class TsfRegistrar {
4247
public:
@@ -45,10 +50,14 @@ class TsfRegistrar {
4550
TsfRegistrar& operator=(const TsfRegistrar&) = delete;
4651

4752
// Registers the DLL specified with |path| as a COM server.
48-
static HRESULT RegisterCOMServer(const wchar_t* path, DWORD length);
53+
// |bitness| specifies which registry view to use: k64bit for the native
54+
// 64-bit view, k32bit for the WOW6432Node (32-bit) view.
55+
static HRESULT RegisterCOMServer(const wchar_t* path, DWORD length,
56+
COMServerBitness bitness);
4957

5058
// Unregisters the DLL from registry.
51-
static void UnregisterCOMServer();
59+
// |bitness| specifies which registry view to unregister from.
60+
static void UnregisterCOMServer(COMServerBitness bitness);
5261

5362
// Registers this COM server to the profile store for input processors.
5463
// The caller is responsible for initializing COM before call this function.

src/win32/custom_action/BUILD.bazel

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ mozc_win32_cc_prod_binary(
4141
"custom_action.h",
4242
"resource.h",
4343
],
44-
defines = select({
45-
"//:enable_win_universal_installer": ["MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER"],
46-
"//conditions:default": [],
47-
}),
4844
executable_name_map = {
4945
"Mozc": "mozc_installer_helper.dll",
5046
"GoogleJapaneseInput": "GoogleIMEJaInstallerHelper.dll",

src/win32/custom_action/custom_action.cc

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,8 @@
3333
#include <windows.h>
3434
#include <atlbase.h>
3535
#include <msiquery.h>
36-
// clang-format on
37-
38-
#if defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
3936
#include <wow64apiset.h>
40-
#endif // defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
37+
// clang-format on
4138

4239
#undef StrCat // NOLINT: TODO: triggers clang-tidy, defined by windows.h.
4340

@@ -457,44 +454,43 @@ UINT __stdcall RegisterTIP(MSIHANDLE msi_handle) {
457454
mozc::ScopedCOMInitializer com_initializer;
458455
HRESULT result = S_OK;
459456

460-
#if defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
457+
// Register 64-bit TIP COM server.
461458
// Unlike 32-bit TIP DLL, which is always x86, the expected 64-bit TIP DLL
462-
// can be x64 or ARM64X depending on the target environment. This is why
463-
// only 64-bit TIP DLL is dynamically registered here.
464-
465-
// |IsWow64Process2| is added in Windows 10 1709 / Windows Server 1709. Let's
466-
// check if the API is available before calling it.
467-
// TODO: Directly call |IsWow64Process2| after we stop supporting Windows 10.
459+
// can be x64 or ARM64X depending on the target environment.
468460
USHORT process_machine = IMAGE_FILE_MACHINE_UNKNOWN;
469461
USHORT native_machine = IMAGE_FILE_MACHINE_UNKNOWN;
470-
auto IsWow64Process2Func = reinterpret_cast<decltype(&::IsWow64Process2)>(
471-
::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "IsWow64Process2"));
472-
if (IsWow64Process2Func != nullptr) [[likely]] {
473-
result = IsWow64Process2Func(::GetCurrentProcess(), &process_machine,
474-
&native_machine);
475-
} else {
476-
// Fallback to x64.
477-
result = E_NOTIMPL;
478-
}
462+
result = IsWow64Process2(::GetCurrentProcess(), &process_machine,
463+
&native_machine);
479464
const bool is_arm64_machine =
480465
SUCCEEDED(result) && native_machine == IMAGE_FILE_MACHINE_ARM64;
481-
const std::wstring& tip64_path = GetMozcComponentPath(
466+
const std::wstring tip64_path = GetMozcComponentPath(
482467
is_arm64_machine ? mozc::kMozcTIP64X : mozc::kMozcTIP64);
483468

484-
result = mozc::win32::TsfRegistrar::RegisterCOMServer(tip64_path.c_str(),
485-
tip64_path.length());
469+
result = mozc::win32::TsfRegistrar::RegisterCOMServer(
470+
tip64_path.c_str(), tip64_path.length(),
471+
mozc::win32::COMServerBitness::k64bit);
486472
if (FAILED(result)) {
487473
LOG_ERROR_FOR_OMAHA();
488474
UnregisterTIP(msi_handle);
489475
return ERROR_INSTALL_FAILURE;
490476
}
491-
#endif // defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
492477

478+
// Register 32-bit TIP COM server.
479+
const std::wstring tip32_path = GetMozcComponentPath(mozc::kMozcTIP32);
480+
result = mozc::win32::TsfRegistrar::RegisterCOMServer(
481+
tip32_path.c_str(), tip32_path.length(),
482+
mozc::win32::COMServerBitness::k32bit);
483+
if (FAILED(result)) {
484+
LOG_ERROR_FOR_OMAHA();
485+
UnregisterTIP(msi_handle);
486+
return ERROR_INSTALL_FAILURE;
487+
}
488+
489+
// Register profiles and categories.
493490
// The path here is to retrieve Win32 resources such as icon and product name,
494491
// which does not need to match the native CPU architecture. Here we use
495492
// 32-bit TIP DLL as it is always installed even on an ARM64 target.
496-
const std::wstring resource_dll_path = GetMozcComponentPath(mozc::kMozcTIP32);
497-
result = mozc::win32::TsfRegistrar::RegisterProfiles(resource_dll_path);
493+
result = mozc::win32::TsfRegistrar::RegisterProfiles(tip32_path);
498494
if (FAILED(result)) {
499495
LOG_ERROR_FOR_OMAHA();
500496
UnregisterTIP(msi_handle);
@@ -523,13 +519,10 @@ UINT __stdcall UnregisterTIP(MSIHANDLE msi_handle) {
523519

524520
mozc::win32::TsfRegistrar::UnregisterCategories();
525521
mozc::win32::TsfRegistrar::UnregisterProfiles();
526-
527-
#if defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
528-
// Unlike 32-bit TIP DLL, which is always x86, the expected 64-bit TIP DLL
529-
// can be x64 or ARM64X depending on the target environment. This is why
530-
// only 64-bit TIP DLL is dynamically unregistered here.
531-
mozc::win32::TsfRegistrar::UnregisterCOMServer();
532-
#endif // defined(MOZC_ENABLE_WIN_UNIVERSAL_INSTALLER)
522+
mozc::win32::TsfRegistrar::UnregisterCOMServer(
523+
mozc::win32::COMServerBitness::k64bit);
524+
mozc::win32::TsfRegistrar::UnregisterCOMServer(
525+
mozc::win32::COMServerBitness::k32bit);
533526

534527
return ERROR_SUCCESS;
535528
}

src/win32/installer/installer_64bit.wxs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -296,27 +296,17 @@
296296
<ServiceControl Id="StopGoogleIMEJaCacheService" Name="GoogleIMEJaCacheService" Stop="both" Remove="uninstall" Wait="yes" />
297297
</Component>
298298
<Component Id="GIMEJaTIP32" Permanent="no" Bitness="always32">
299-
<File Id="GoogleIMEJaTIP32.dll" Name="GoogleIMEJaTIP32.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP32Path)" Vital="yes">
300-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Google Japanese Input" Id="D5A86FD5-5308-47EA-AD16-9C4EB160EC3C" />
301-
</File>
299+
<File Id="GoogleIMEJaTIP32.dll" Name="GoogleIMEJaTIP32.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP32Path)" Vital="yes" />
302300
</Component>
303301
<Component Id="GIMEJaTIP64" Permanent="no" Bitness="always64">
304-
<File Id="GoogleIMEJaTIP64.dll" Name="GoogleIMEJaTIP64.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64Path)" Vital="yes">
305-
<?if $(var.MozcTIP64ArmPath) == "" and $(var.MozcTIP64XPath) == "" and $(var.MozcUniversalInstaller) == "" ?>
306-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Google Japanese Input" Id="D5A86FD5-5308-47EA-AD16-9C4EB160EC3C" />
307-
<?endif?>
308-
</File>
302+
<File Id="GoogleIMEJaTIP64.dll" Name="GoogleIMEJaTIP64.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64Path)" Vital="yes" />
309303
</Component>
310304
<?if $(var.MozcTIP64ArmPath) != "" and $(var.MozcTIP64XPath) != "" ?>
311305
<Component Id="GIMEJaTIP64Arm" Permanent="no" Bitness="always64">
312306
<File Id="GoogleIMEJaTIP64Arm.dll" Name="GoogleIMEJaTIP64Arm.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64ArmPath)" Vital="yes" />
313307
</Component>
314308
<Component Id="GIMEJaTIP64X" Permanent="no" Bitness="always64">
315-
<File Id="GoogleIMEJaTIP64X.dll" Name="GoogleIMEJaTIP64X.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64XPath)" Vital="yes">
316-
<?if $(var.MozcUniversalInstaller) == "" ?>
317-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Google Japanese Input" Id="D5A86FD5-5308-47EA-AD16-9C4EB160EC3C" />
318-
<?endif?>
319-
</File>
309+
<File Id="GoogleIMEJaTIP64X.dll" Name="GoogleIMEJaTIP64X.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64XPath)" Vital="yes" />
320310
</Component>
321311
<?endif?>
322312
<Component Id="GIMEJaBroker" Permanent="no">

src/win32/installer/installer_oss_64bit.wxs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -271,27 +271,17 @@
271271
<ServiceControl Id="StopMozcCacheService" Name="MozcCacheService" Stop="both" Remove="uninstall" Wait="yes" />
272272
</Component>
273273
<Component Id="MozcTIP32" Permanent="no" Bitness="always32">
274-
<File Id="mozc_tip32.dll" Name="mozc_tip32.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP32Path)" Vital="yes">
275-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Mozc" Id="10A67BC8-22FA-4A59-90DC-2546652C56BF" />
276-
</File>
274+
<File Id="mozc_tip32.dll" Name="mozc_tip32.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP32Path)" Vital="yes" />
277275
</Component>
278276
<Component Id="MozcTIP64" Permanent="no" Bitness="always64">
279-
<File Id="mozc_tip64.dll" Name="mozc_tip64.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64Path)" Vital="yes">
280-
<?if $(var.MozcTIP64ArmPath) == "" and $(var.MozcTIP64XPath) == "" and $(var.MozcUniversalInstaller) == "" ?>
281-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Mozc" Id="10A67BC8-22FA-4A59-90DC-2546652C56BF" />
282-
<?endif?>
283-
</File>
277+
<File Id="mozc_tip64.dll" Name="mozc_tip64.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64Path)" Vital="yes" />
284278
</Component>
285279
<?if $(var.MozcTIP64ArmPath) != "" and $(var.MozcTIP64XPath) != "" ?>
286280
<Component Id="MozcTIP64Arm" Permanent="no" Bitness="always64">
287281
<File Id="mozc_tip64arm.dll" Name="mozc_tip64arm.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64ArmPath)" Vital="yes" />
288282
</Component>
289283
<Component Id="MozcTIP64X" Permanent="no" Bitness="always64">
290-
<File Id="mozc_tip64x.dll" Name="mozc_tip64x.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64XPath)" Vital="yes">
291-
<?if $(var.MozcUniversalInstaller) == "" ?>
292-
<Class Context="InprocServer32" ThreadingModel="apartment" Description="Mozc" Id="10A67BC8-22FA-4A59-90DC-2546652C56BF" />
293-
<?endif?>
294-
</File>
284+
<File Id="mozc_tip64x.dll" Name="mozc_tip64x.dll" DiskId="1" Checksum="yes" Source="$(var.MozcTIP64XPath)" Vital="yes" />
295285
</Component>
296286
<?endif?>
297287
<Component Id="MozcBroker" Permanent="no">

0 commit comments

Comments
 (0)