Skip to content

Commit b60b5b1

Browse files
Prcuvunameoverflow
authored andcommitted
feat(tsf): get IME keyboard identifier by searching registry (#272)
This commit makes TSF search for Weasel IME from registry, within the user IME device ID range from 0xE020 to 0xE0FF. The search finishes on first match. By doing so TSF can be registered through regsvr32 again.
1 parent 343f27b commit b60b5b1

13 files changed

+135
-116
lines changed

WeaselSetup/TSFRegister.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

WeaselSetup/WeaselSetup.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "stdafx.h"
55
#include "WeaselSetup.h"
66
#include "InstallOptionsDialog.h"
7-
#include <VersionHelpers.hpp>
87

98
CAppModule _Module;
109

@@ -15,7 +14,6 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
1514
LPTSTR lpCmdLine,
1615
int nCmdShow)
1716
{
18-
InitVersion();
1917
UNREFERENCED_PARAMETER(hPrevInstance);
2018

2119
HRESULT hRes = ::CoInitialize(NULL);

WeaselSetup/WeaselSetup.vcxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@
9797
<ClInclude Include="Resource.h" />
9898
<ClInclude Include="stdafx.h" />
9999
<ClInclude Include="targetver.h" />
100-
<ClInclude Include="TSFRegister.h" />
101100
<ClInclude Include="WeaselSetup.h" />
102101
</ItemGroup>
103102
<ItemGroup>
@@ -107,7 +106,6 @@
107106
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
108107
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
109108
</ClCompile>
110-
<ClCompile Include="TSFRegister.cpp" />
111109
<ClCompile Include="WeaselSetup.cpp" />
112110
</ItemGroup>
113111
<ItemGroup>

WeaselSetup/WeaselSetup.vcxproj.filters

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@
3939
<ClInclude Include="InstallOptionsDialog.h">
4040
<Filter>Header Files</Filter>
4141
</ClInclude>
42-
<ClInclude Include="TSFRegister.h">
43-
<Filter>Header Files</Filter>
44-
</ClInclude>
4542
</ItemGroup>
4643
<ItemGroup>
4744
<ClCompile Include="stdafx.cpp">
@@ -56,9 +53,6 @@
5653
<ClCompile Include="InstallOptionsDialog.cpp">
5754
<Filter>Source Files</Filter>
5855
</ClCompile>
59-
<ClCompile Include="TSFRegister.cpp">
60-
<Filter>Source Files</Filter>
61-
</ClCompile>
6256
</ItemGroup>
6357
<ItemGroup>
6458
<ResourceCompile Include="WeaselSetup.rc">

WeaselSetup/imesetup.cpp

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
#include <vector>
44
#include <StringAlgorithm.hpp>
55
#include <WeaselCommon.h>
6-
7-
#include "TSFRegister.h"
6+
#include <msctf.h>
7+
#include <strsafe.h>
88

99

1010
// {A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}
11-
const GUID c_clsidTextService =
11+
static const GUID c_clsidTextService =
1212
{ 0xa3f4cded, 0xb1e9, 0x41ee, { 0x9c, 0xa6, 0x7b, 0x4d, 0xd, 0xe6, 0xcb, 0xa } };
1313

1414
// {3D02CAB6-2B8E-4781-BA20-1C9267529467}
15-
const GUID c_guidProfile =
15+
static const GUID c_guidProfile =
1616
{ 0x3d02cab6, 0x2b8e, 0x4781, { 0xba, 0x20, 0x1c, 0x92, 0x67, 0x52, 0x94, 0x67 } };
1717

18-
HKL ImeHKL = 0;
1918

2019
BOOL copy_file(const std::wstring& src, const std::wstring& dest)
2120
{
@@ -109,12 +108,12 @@ int install_ime_file(std::wstring& srcPath, const std::wstring& ext, bool hant,
109108
if (!silent) MessageBoxW(NULL, destPath.c_str(), L"安裝失敗", MB_ICONERROR | MB_OK);
110109
return 1;
111110
}
111+
retval += func(destPath, true, true, hant, silent);
112112
if (fnWow64RevertWow64FsRedirection == NULL || fnWow64RevertWow64FsRedirection(OldValue) == FALSE)
113113
{
114114
if (!silent) MessageBoxW(NULL, L"無法恢復文件系統重定向", L"安裝失敗", MB_ICONERROR | MB_OK);
115115
return 1;
116116
}
117-
retval += func(destPath, true, true, hant, silent);
118117
}
119118
return retval;
120119
}
@@ -179,9 +178,9 @@ int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64,
179178
LSTATUS ret = RegOpenKey(HKEY_LOCAL_MACHINE, KEYBOARD_LAYOUTS_KEY, &hKey);
180179
if (ret == ERROR_SUCCESS)
181180
{
182-
for (DWORD k = 0xE0200000 + (hant ? 0x0404 : 0x0804); true; k += 0x10000)
181+
for (DWORD k = 0xE0200000 + (hant ? 0x0404 : 0x0804); k <= 0xE0FF0804; k += 0x10000)
183182
{
184-
wsprintf(hkl_str, L"%08X", k);
183+
StringCchPrintfW(hkl_str, _countof(hkl_str), L"%08X", k);
185184
HKEY hSubKey;
186185
ret = RegOpenKey(hKey, hkl_str, &hSubKey);
187186
if (ret == ERROR_SUCCESS)
@@ -248,11 +247,10 @@ int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64,
248247
{
249248
DWORD dwErr = GetLastError();
250249
WCHAR msg[100];
251-
wsprintf(msg, L"註冊輸入法錯誤 ImmInstallIME: HKL=%x Err=%x", hKL, dwErr);
250+
StringCchPrintfW(msg, _countof(msg), L"註冊輸入法錯誤 ImmInstallIME: HKL=%x Err=%x", hKL, dwErr);
252251
if (!silent) MessageBox(NULL, msg, L"安裝失敗", MB_ICONERROR | MB_OK);
253252
return 1;
254253
}
255-
ImeHKL = hKL;
256254
return 0;
257255
}
258256

@@ -366,28 +364,45 @@ void enable_profile(BOOL fEnable, bool hant) {
366364
pProfiles->Release();
367365
}
368366
}
369-
void unregister_text_service()
370-
{
371-
UnregisterProfiles();
372-
UnregisterCategories();
373-
UnregisterServer();
374-
}
367+
375368
// 注册TSF输入法
376369
int register_text_service(const std::wstring& tsf_path, bool register_ime, bool is_wow64, bool hant, bool silent)
377370
{
371+
using RegisterServerFunction = HRESULT (STDAPICALLTYPE *)();
372+
378373
if (!register_ime)
379374
enable_profile(FALSE, hant);
380375

381-
if (register_ime) {
382-
if (!RegisterServer(tsf_path, is_wow64) || !RegisterProfiles(tsf_path, ImeHKL) || !RegisterCategories())
383-
{
384-
unregister_text_service();
385-
MessageBox(NULL, L"註冊輸入法錯誤", L"安装/卸載失败", MB_ICONERROR | MB_OK);
386-
return 1;
387-
}
376+
std::wstring params = L" \"" + tsf_path + L"\"";
377+
if (!register_ime)
378+
{
379+
params = L" /u " + params; // unregister
388380
}
389-
else {
390-
unregister_text_service();
381+
//if (silent) // always silent
382+
{
383+
params = L" /s " + params;
384+
}
385+
SHELLEXECUTEINFOW shExInfo = { 0 };
386+
shExInfo.cbSize = sizeof(shExInfo);
387+
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
388+
shExInfo.hwnd = 0;
389+
shExInfo.lpVerb = L"open"; // Operation to perform
390+
shExInfo.lpFile = L"regsvr32.exe"; // Application to start
391+
shExInfo.lpParameters = params.c_str(); // Additional parameters
392+
shExInfo.lpDirectory = 0;
393+
shExInfo.nShow = SW_SHOW;
394+
shExInfo.hInstApp = 0;
395+
if (ShellExecuteExW(&shExInfo))
396+
{
397+
WaitForSingleObject(shExInfo.hProcess, INFINITE);
398+
CloseHandle(shExInfo.hProcess);
399+
}
400+
else
401+
{
402+
WCHAR msg[100];
403+
StringCchPrintfW(msg, _countof(msg), L"註冊輸入法錯誤 regsvr32.exe %s", params.c_str());
404+
if (!silent) MessageBoxW(NULL, msg, L"安装/卸載失败", MB_ICONERROR | MB_OK);
405+
return 1;
391406
}
392407

393408
if (register_ime)

WeaselSetup/stdafx.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <windows.h>
1313
#include <ShellAPI.h>
1414
#include <Imm.h>
15-
#include <msctf.h>
1615

1716
#include <atlbase.h>
1817
#include <atlwin.h>
@@ -24,26 +23,6 @@
2423
#include <wtl/atlmisc.h>
2524
#include <wtl/atldlgs.h>
2625

27-
// {A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}
28-
extern const GUID c_clsidTextService;
29-
30-
// {3D02CAB6-2B8E-4781-BA20-1C9267529467}
31-
extern const GUID c_guidProfile;
32-
33-
#ifndef TF_IPP_CAPS_IMMERSIVESUPPORT
34-
35-
#define WEASEL_USING_OLDER_TSF_SDK
36-
37-
/* for Windows 8 */
38-
#define TF_TMF_IMMERSIVEMODE 0x40000000
39-
#define TF_IPP_CAPS_IMMERSIVESUPPORT 0x00010000
40-
#define TF_IPP_CAPS_SYSTRAYSUPPORT 0x00020000
41-
42-
extern const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT;
43-
extern const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT;
44-
45-
#endif
46-
4726
// TODO: reference additional headers your program requires here
4827

4928
#include <string>

WeaselTSF/Globals.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
#include "stdafx.h"
55
#include <WeaselCommon.h>
66

7+
#ifdef WEASEL_HANT
8+
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
9+
#else
10+
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
11+
#endif
12+
13+
#define TEXTSERVICE_DESC WEASEL_IME_NAME
14+
#define TEXTSERVICE_DESC_A "Weasel"
15+
#define TEXTSERVICE_MODEL "Apartment"
16+
17+
#define TEXTSERVICE_ICON_INDEX 0
718

819
void DllAddRef();
920
void DllRelease();

WeaselSetup/TSFRegister.cpp renamed to WeaselTSF/Register.cpp

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "stdafx.h"
2-
#include "TSFRegister.h"
3-
#include <WeaselCommon.h>
2+
#include "Register.h"
3+
#include <strsafe.h>
44
#include <VersionHelpers.hpp>
55

66
#define CLSID_STRLEN 38 // strlen("{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}")
@@ -10,22 +10,43 @@ static const char c_szTipKeyPrefix[] = "Software\\Microsft\\CTF\\TIP\\";
1010
static const char c_szInProcSvr32[] = "InprocServer32";
1111
static const char c_szModelName[] = "ThreadingModel";
1212

13-
#ifdef WEASEL_USING_OLDER_TSF_SDK
14-
15-
/* For Windows 8 */
16-
const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT =
17-
{ 0x13A016DF, 0x560B, 0x46CD,{ 0x94, 0x7A, 0x4C, 0x3A, 0xF1, 0xE0, 0xE3, 0x5D } };
18-
19-
const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT =
20-
{ 0x25504FB4, 0x7BAB, 0x4BC1,{ 0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5 } };
21-
22-
#endif
13+
HKL FindIME()
14+
{
15+
HKL hKL = NULL;
16+
WCHAR key[9];
17+
HKEY hKey;
18+
LSTATUS ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts", 0, KEY_READ, &hKey);
19+
if (ret == ERROR_SUCCESS)
20+
{
21+
for (DWORD id = (0xE0200000 | TEXTSERVICE_LANGID); hKL == NULL && id <= (0xE0FF0000 | TEXTSERVICE_LANGID); id += 0x10000)
22+
{
23+
StringCchPrintfW(key, _countof(key), L"%08X", id);
24+
HKEY hSubKey;
25+
ret = RegOpenKeyExW(hKey, key, 0, KEY_READ, &hSubKey);
26+
if (ret == ERROR_SUCCESS)
27+
{
28+
WCHAR data[32];
29+
DWORD type;
30+
DWORD size = sizeof data;
31+
ret = RegQueryValueExW(hSubKey, L"Ime File", NULL, &type, (LPBYTE)data, &size);
32+
if (ret == ERROR_SUCCESS && type == REG_SZ && _wcsicmp(data, L"weasel.ime") == 0)
33+
hKL = (HKL)id;
34+
}
35+
RegCloseKey(hSubKey);
36+
}
37+
}
38+
RegCloseKey(hKey);
39+
return hKL;
40+
}
2341

24-
BOOL RegisterProfiles(std::wstring filename, HKL hkl)
42+
BOOL RegisterProfiles()
2543
{
44+
WCHAR achIconFile[MAX_PATH];
45+
ULONG cchIconFile = GetModuleFileNameW(g_hInst, achIconFile, ARRAYSIZE(achIconFile));
2646
HRESULT hr;
2747

28-
if (IsWindows8OrGreater()) {
48+
if (IsWindows8OrGreater())
49+
{
2950
CComPtr<ITfInputProcessorProfileMgr> pInputProcessorProfileMgr;
3051
hr = pInputProcessorProfileMgr.CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL);
3152
if (FAILED(hr))
@@ -37,15 +58,16 @@ BOOL RegisterProfiles(std::wstring filename, HKL hkl)
3758
c_guidProfile,
3859
TEXTSERVICE_DESC,
3960
(ULONG)wcslen(TEXTSERVICE_DESC),
40-
filename.c_str(),
41-
filename.size(),
61+
achIconFile,
62+
cchIconFile,
4263
TEXTSERVICE_ICON_INDEX,
43-
hkl,
64+
FindIME(),
4465
0,
4566
TRUE,
4667
0);
4768
}
48-
else {
69+
else
70+
{
4971
CComPtr<ITfInputProcessorProfiles> pInputProcessorProfiles;
5072
hr = pInputProcessorProfiles.CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER);
5173
if (FAILED(hr))
@@ -61,16 +83,16 @@ BOOL RegisterProfiles(std::wstring filename, HKL hkl)
6183
c_guidProfile,
6284
TEXTSERVICE_DESC,
6385
(ULONG)wcslen(TEXTSERVICE_DESC),
64-
filename.c_str(),
65-
filename.size(),
86+
achIconFile,
87+
cchIconFile,
6688
TEXTSERVICE_ICON_INDEX);
6789
if (FAILED(hr))
6890
return FALSE;
69-
if (hkl) {
70-
hr = pInputProcessorProfiles->SubstituteKeyboardLayout(
71-
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, hkl);
72-
if (FAILED(hr)) return FALSE;
73-
}
91+
92+
hr = pInputProcessorProfiles->SubstituteKeyboardLayout(
93+
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, FindIME());
94+
if (FAILED(hr))
95+
return FALSE;
7496
}
7597
return TRUE;
7698
}
@@ -108,7 +130,6 @@ BOOL RegisterCategories()
108130
if (hr != S_OK)
109131
goto Exit;
110132

111-
InitVersion();
112133
if (IsWindows8OrGreater())
113134
{
114135
hr = pCategoryMgr->RegisterCategory(c_clsidTextService, GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT, c_clsidTextService);
@@ -189,32 +210,28 @@ static LONG RecurseDeleteKeyA(HKEY hParentKey, LPCSTR lpszKey)
189210
return lRes == ERROR_SUCCESS ? RegDeleteKeyA(hParentKey, lpszKey) : lRes;
190211
}
191212

192-
BOOL RegisterServer(std::wstring filename, bool wow64)
213+
BOOL RegisterServer()
193214
{
194215
DWORD dw;
195216
HKEY hKey;
196217
HKEY hSubKey;
197218
BOOL fRet;
198219
char achIMEKey[ARRAYSIZE(c_szInfoKeyPrefix) + CLSID_STRLEN];
199-
DWORD flags = KEY_WRITE;
200-
if (wow64) {
201-
flags |= KEY_WOW64_64KEY;
202-
}
203-
//TCHAR achFileName[MAX_PATH];
220+
char achFileName[MAX_PATH];
204221

205222
if (!CLSIDToStringA(c_clsidTextService, achIMEKey + ARRAYSIZE(c_szInfoKeyPrefix) - 1))
206223
return FALSE;
207224
memcpy(achIMEKey, c_szInfoKeyPrefix, sizeof(c_szInfoKeyPrefix) - 1);
208225

209-
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hKey, &dw) == ERROR_SUCCESS)
226+
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dw) == ERROR_SUCCESS)
210227
{
211-
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *)TEXTSERVICE_DESC_A, (strlen(TEXTSERVICE_DESC_A) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
212-
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
228+
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *)TEXTSERVICE_DESC_A, sizeof TEXTSERVICE_DESC_A) == ERROR_SUCCESS;
229+
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
213230
{
214-
//dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));
231+
dw = GetModuleFileNameA(g_hInst, achFileName, ARRAYSIZE(achFileName));
215232

216-
fRet &= RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE *)filename.c_str(), (filename.size() + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
217-
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, (strlen(TEXTSERVICE_MODEL) + 1)) == ERROR_SUCCESS;
233+
fRet &= RegSetValueExA(hSubKey, NULL, 0, REG_SZ, (BYTE *)achFileName, (strlen(achFileName) + 1) * sizeof(char)) == ERROR_SUCCESS;
234+
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, sizeof TEXTSERVICE_MODEL) == ERROR_SUCCESS;
218235
RegCloseKey(hSubKey);
219236
}
220237
RegCloseKey(hKey);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy