Skip to content

Commit 91cbd2c

Browse files
authored
feat(install): combine IME and TSF (#257)
* feat(tsf): combine IME and TSF * fix(install): fix wow64 registry
1 parent ee9128b commit 91cbd2c

15 files changed

+183
-122
lines changed

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

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "stdafx.h"
2-
#include "Register.h"
2+
#include "TSFRegister.h"
3+
#include <WeaselCommon.h>
34
#include <VersionHelpers.hpp>
5+
#include <ComPtr.h>
46

57
#define CLSID_STRLEN 38 // strlen("{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}")
68

@@ -9,41 +11,69 @@ static const char c_szTipKeyPrefix[] = "Software\\Microsft\\CTF\\TIP\\";
911
static const char c_szInProcSvr32[] = "InprocServer32";
1012
static const char c_szModelName[] = "ThreadingModel";
1113

12-
BOOL RegisterProfiles()
13-
{
14-
WCHAR achIconFile[MAX_PATH];
15-
char achFileNameA[MAX_PATH];
16-
DWORD cchA;
17-
int cchIconFile;
18-
HRESULT hr;
19-
20-
cchA = GetModuleFileNameA(g_hInst, achFileNameA, ARRAYSIZE(achFileNameA));
21-
cchIconFile = MultiByteToWideChar(CP_ACP, 0, achFileNameA, cchA, achIconFile, ARRAYSIZE(achIconFile) - 1);
22-
achIconFile[cchIconFile] = '\0';
23-
24-
ITfInputProcessorProfiles *pInputProcessorProfiles;
25-
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
26-
IID_ITfInputProcessorProfiles, (void **) &pInputProcessorProfiles);
27-
if (hr != S_OK)
28-
return E_FAIL;
14+
#ifdef WEASEL_USING_OLDER_TSF_SDK
2915

30-
hr = pInputProcessorProfiles->Register(c_clsidTextService);
31-
if (hr != S_OK)
32-
goto Exit;
16+
/* For Windows 8 */
17+
const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT =
18+
{ 0x13A016DF, 0x560B, 0x46CD,{ 0x94, 0x7A, 0x4C, 0x3A, 0xF1, 0xE0, 0xE3, 0x5D } };
3319

34-
hr = pInputProcessorProfiles->AddLanguageProfile(
35-
c_clsidTextService,
36-
TEXTSERVICE_LANGID,
37-
c_guidProfile,
38-
TEXTSERVICE_DESC,
39-
(ULONG) wcslen(TEXTSERVICE_DESC),
40-
achIconFile,
41-
cchIconFile,
42-
TEXTSERVICE_ICON_INDEX);
20+
const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT =
21+
{ 0x25504FB4, 0x7BAB, 0x4BC1,{ 0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5 } };
4322

44-
Exit:
45-
pInputProcessorProfiles->Release();
46-
return (hr == S_OK);
23+
#endif
24+
25+
BOOL RegisterProfiles(std::wstring filename, HKL hkl)
26+
{
27+
HRESULT hr;
28+
29+
if (IsWindows8OrGreater()) {
30+
ComPtr<ITfInputProcessorProfileMgr> pInputProcessorProfileMgr;
31+
hr = pInputProcessorProfileMgr.CoCreate(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL);
32+
if (FAILED(hr))
33+
return FALSE;
34+
35+
hr = pInputProcessorProfileMgr->RegisterProfile(
36+
c_clsidTextService,
37+
TEXTSERVICE_LANGID,
38+
c_guidProfile,
39+
TEXTSERVICE_DESC,
40+
(ULONG)wcslen(TEXTSERVICE_DESC),
41+
filename.c_str(),
42+
filename.size(),
43+
TEXTSERVICE_ICON_INDEX,
44+
hkl,
45+
0,
46+
TRUE,
47+
0);
48+
}
49+
else {
50+
ComPtr<ITfInputProcessorProfiles> pInputProcessorProfiles;
51+
hr = pInputProcessorProfiles.CoCreate(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER);
52+
if (FAILED(hr))
53+
return FALSE;
54+
55+
hr = pInputProcessorProfiles->Register(c_clsidTextService);
56+
if (FAILED(hr))
57+
return FALSE;
58+
59+
hr = pInputProcessorProfiles->AddLanguageProfile(
60+
c_clsidTextService,
61+
TEXTSERVICE_LANGID,
62+
c_guidProfile,
63+
TEXTSERVICE_DESC,
64+
(ULONG)wcslen(TEXTSERVICE_DESC),
65+
filename.c_str(),
66+
filename.size(),
67+
TEXTSERVICE_ICON_INDEX);
68+
if (FAILED(hr))
69+
return FALSE;
70+
if (hkl) {
71+
hr = pInputProcessorProfiles->SubstituteKeyboardLayout(
72+
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, hkl);
73+
if (FAILED(hr)) return FALSE;
74+
}
75+
}
76+
return TRUE;
4777
}
4878

4979
void UnregisterProfiles()
@@ -52,10 +82,12 @@ void UnregisterProfiles()
5282
HRESULT hr;
5383

5484
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
55-
IID_ITfInputProcessorProfiles, (void **) &pInputProcessProfiles);
85+
IID_ITfInputProcessorProfiles, (void **)&pInputProcessProfiles);
5686
if (FAILED(hr))
5787
return;
5888

89+
pInputProcessProfiles->SubstituteKeyboardLayout(
90+
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, NULL);
5991
pInputProcessProfiles->Unregister(c_clsidTextService);
6092
pInputProcessProfiles->Release();
6193
}
@@ -65,10 +97,10 @@ BOOL RegisterCategories()
6597
ITfCategoryMgr *pCategoryMgr;
6698
HRESULT hr;
6799

68-
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **) &pCategoryMgr);
100+
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
69101
if (hr != S_OK)
70102
return FALSE;
71-
103+
72104
hr = pCategoryMgr->RegisterCategory(c_clsidTextService, GUID_TFCAT_TIP_KEYBOARD, c_clsidTextService);
73105
if (hr != S_OK)
74106
goto Exit;
@@ -97,7 +129,7 @@ void UnregisterCategories()
97129
ITfCategoryMgr *pCategoryMgr;
98130
HRESULT hr;
99131

100-
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **) &pCategoryMgr);
132+
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
101133
if (FAILED(hr))
102134
return;
103135

@@ -107,15 +139,15 @@ void UnregisterCategories()
107139

108140
static BOOL CLSIDToStringA(REFGUID refGUID, char *pchA)
109141
{
110-
static const BYTE GuidMap[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
111-
8, 9, '-', 10, 11, 12, 13, 14, 15};
142+
static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
143+
8, 9, '-', 10, 11, 12, 13, 14, 15 };
112144

113145
static const char szDigits[] = "0123456789ABCDEF";
114146

115147
int i;
116148
char *p = pchA;
117149

118-
const BYTE *pBytes = (const BYTE *) &refGUID;
150+
const BYTE *pBytes = (const BYTE *)&refGUID;
119151

120152
*p++ = '{';
121153
for (i = 0; i < sizeof(GuidMap); i++)
@@ -158,28 +190,32 @@ static LONG RecurseDeleteKeyA(HKEY hParentKey, LPCSTR lpszKey)
158190
return lRes == ERROR_SUCCESS ? RegDeleteKeyA(hParentKey, lpszKey) : lRes;
159191
}
160192

161-
BOOL RegisterServer()
193+
BOOL RegisterServer(std::wstring filename, bool wow64)
162194
{
163195
DWORD dw;
164196
HKEY hKey;
165197
HKEY hSubKey;
166198
BOOL fRet;
167199
char achIMEKey[ARRAYSIZE(c_szInfoKeyPrefix) + CLSID_STRLEN];
168-
TCHAR achFileName[MAX_PATH];
200+
DWORD flags = KEY_WRITE;
201+
if (wow64) {
202+
flags |= KEY_WOW64_32KEY;
203+
}
204+
//TCHAR achFileName[MAX_PATH];
169205

170206
if (!CLSIDToStringA(c_clsidTextService, achIMEKey + ARRAYSIZE(c_szInfoKeyPrefix) - 1))
171207
return FALSE;
172208
memcpy(achIMEKey, c_szInfoKeyPrefix, sizeof(c_szInfoKeyPrefix) - 1);
173209

174-
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dw) == ERROR_SUCCESS)
210+
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hKey, &dw) == ERROR_SUCCESS)
175211
{
176-
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *) TEXTSERVICE_DESC_A, (strlen(TEXTSERVICE_DESC_A) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
177-
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
212+
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *)TEXTSERVICE_DESC_A, (strlen(TEXTSERVICE_DESC_A) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
213+
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
178214
{
179-
dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));
215+
//dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));
180216

181-
fRet &= RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE *) achFileName, (lstrlen(achFileName) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
182-
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *) TEXTSERVICE_MODEL, (strlen(TEXTSERVICE_MODEL) + 1)) == ERROR_SUCCESS;
217+
fRet &= RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE *)filename.c_str(), (filename.size() + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
218+
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, (strlen(TEXTSERVICE_MODEL) + 1)) == ERROR_SUCCESS;
183219
RegCloseKey(hSubKey);
184220
}
185221
RegCloseKey(hKey);

WeaselSetup/TSFRegister.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include "stdafx.h"
4+
5+
BOOL RegisterProfiles(std::wstring filename, HKL hkl);
6+
void UnregisterProfiles();
7+
BOOL RegisterCategories();
8+
void UnregisterCategories();
9+
BOOL RegisterServer(std::wstring filename, bool wow64);
10+
void UnregisterServer();

WeaselSetup/WeaselSetup.cpp

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

89
CAppModule _Module;
910

@@ -14,6 +15,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
1415
LPTSTR lpCmdLine,
1516
int nCmdShow)
1617
{
18+
InitVersion();
1719
UNREFERENCED_PARAMETER(hPrevInstance);
1820

1921
HRESULT hRes = ::CoInitialize(NULL);

WeaselSetup/WeaselSetup.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
<ClInclude Include="Resource.h" />
173173
<ClInclude Include="stdafx.h" />
174174
<ClInclude Include="targetver.h" />
175+
<ClInclude Include="TSFRegister.h" />
175176
<ClInclude Include="WeaselSetup.h" />
176177
</ItemGroup>
177178
<ItemGroup>
@@ -183,6 +184,7 @@
183184
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
184185
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
185186
</ClCompile>
187+
<ClCompile Include="TSFRegister.cpp" />
186188
<ClCompile Include="WeaselSetup.cpp" />
187189
</ItemGroup>
188190
<ItemGroup>

WeaselSetup/WeaselSetup.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
<ClInclude Include="InstallOptionsDialog.h">
4040
<Filter>Header Files</Filter>
4141
</ClInclude>
42+
<ClInclude Include="TSFRegister.h">
43+
<Filter>Header Files</Filter>
44+
</ClInclude>
4245
</ItemGroup>
4346
<ItemGroup>
4447
<ClCompile Include="stdafx.cpp">
@@ -53,6 +56,9 @@
5356
<ClCompile Include="InstallOptionsDialog.cpp">
5457
<Filter>Source Files</Filter>
5558
</ClCompile>
59+
<ClCompile Include="TSFRegister.cpp">
60+
<Filter>Source Files</Filter>
61+
</ClCompile>
5662
</ItemGroup>
5763
<ItemGroup>
5864
<ResourceCompile Include="WeaselSetup.rc">

WeaselSetup/imesetup.cpp

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33
#include <vector>
44
#include <StringAlgorithm.hpp>
55
#include <WeaselCommon.h>
6-
#include <msctf.h>
6+
7+
#include "TSFRegister.h"
78

89

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

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

18+
HKL ImeHKL = 0;
19+
1720

1821
using boost::filesystem::wpath;
1922

@@ -224,6 +227,7 @@ int register_ime(const wpath& ime_path, bool register_ime, bool is_wow64, bool h
224227
if (!silent) MessageBox(NULL, msg, L"安裝失敗", MB_ICONERROR | MB_OK);
225228
return 1;
226229
}
230+
ImeHKL = hKL;
227231
return 0;
228232
}
229233

@@ -337,45 +341,28 @@ void enable_profile(BOOL fEnable, bool hant) {
337341
pProfiles->Release();
338342
}
339343
}
340-
344+
void unregister_text_service()
345+
{
346+
UnregisterProfiles();
347+
UnregisterCategories();
348+
UnregisterServer();
349+
}
341350
// 注册TSF输入法
342351
int register_text_service(const wpath& tsf_path, bool register_ime, bool is_wow64, bool hant, bool silent)
343352
{
344353
if (!register_ime)
345354
enable_profile(FALSE, hant);
346355

347-
std::wstring params = L" \"" + tsf_path.wstring() + L"\"";
348-
if (!register_ime)
349-
{
350-
params = L" /u " + params; // unregister
351-
}
352-
//if (silent) // always silent
353-
{
354-
params = L" /s " + params;
355-
}
356-
357-
SHELLEXECUTEINFO shExInfo = {0};
358-
shExInfo.cbSize = sizeof(shExInfo);
359-
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
360-
shExInfo.hwnd = 0;
361-
shExInfo.lpVerb = L"open"; // Operation to perform
362-
shExInfo.lpFile = L"regsvr32.exe"; // Application to start
363-
shExInfo.lpParameters = params.c_str(); // Additional parameters
364-
shExInfo.lpDirectory = 0;
365-
shExInfo.nShow = SW_SHOW;
366-
shExInfo.hInstApp = 0;
367-
368-
if (ShellExecuteEx(&shExInfo))
369-
{
370-
WaitForSingleObject(shExInfo.hProcess, INFINITE);
371-
CloseHandle(shExInfo.hProcess);
356+
if (register_ime) {
357+
if (!RegisterServer(tsf_path.wstring(), is_wow64) || !RegisterProfiles(tsf_path.wstring(), ImeHKL) || !RegisterCategories())
358+
{
359+
unregister_text_service();
360+
MessageBox(NULL, L"註冊輸入法錯誤", L"安装/卸載失败", MB_ICONERROR | MB_OK);
361+
return 1;
362+
}
372363
}
373-
else
374-
{
375-
WCHAR msg[100];
376-
wsprintf(msg, L"註冊輸入法錯誤 regsvr32.exe %s", params.c_str());
377-
if (!silent) MessageBox(NULL, msg, L"安装/卸載失败", MB_ICONERROR | MB_OK);
378-
return 1;
364+
else {
365+
unregister_text_service();
379366
}
380367

381368
if (register_ime)

WeaselSetup/stdafx.h

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

1617
#include <atlbase.h>
1718
#include <atlwin.h>
@@ -25,4 +26,24 @@
2526

2627
#include <boost/filesystem.hpp>
2728

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

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