Skip to content

Commit

Permalink
feat(install): combine IME and TSF (#257)
Browse files Browse the repository at this point in the history
* feat(tsf): combine IME and TSF

* fix(install): fix wow64 registry
  • Loading branch information
nameoverflow authored Aug 20, 2018
1 parent ee9128b commit 91cbd2c
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 122 deletions.
132 changes: 84 additions & 48 deletions WeaselTSF/Register.cpp → WeaselSetup/TSFRegister.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Register.h"
#include "TSFRegister.h"
#include <WeaselCommon.h>
#include <VersionHelpers.hpp>
#include <ComPtr.h>

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

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

BOOL RegisterProfiles()
{
WCHAR achIconFile[MAX_PATH];
char achFileNameA[MAX_PATH];
DWORD cchA;
int cchIconFile;
HRESULT hr;

cchA = GetModuleFileNameA(g_hInst, achFileNameA, ARRAYSIZE(achFileNameA));
cchIconFile = MultiByteToWideChar(CP_ACP, 0, achFileNameA, cchA, achIconFile, ARRAYSIZE(achIconFile) - 1);
achIconFile[cchIconFile] = '\0';

ITfInputProcessorProfiles *pInputProcessorProfiles;
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
IID_ITfInputProcessorProfiles, (void **) &pInputProcessorProfiles);
if (hr != S_OK)
return E_FAIL;
#ifdef WEASEL_USING_OLDER_TSF_SDK

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

hr = pInputProcessorProfiles->AddLanguageProfile(
c_clsidTextService,
TEXTSERVICE_LANGID,
c_guidProfile,
TEXTSERVICE_DESC,
(ULONG) wcslen(TEXTSERVICE_DESC),
achIconFile,
cchIconFile,
TEXTSERVICE_ICON_INDEX);
const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT =
{ 0x25504FB4, 0x7BAB, 0x4BC1,{ 0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5 } };

Exit:
pInputProcessorProfiles->Release();
return (hr == S_OK);
#endif

BOOL RegisterProfiles(std::wstring filename, HKL hkl)
{
HRESULT hr;

if (IsWindows8OrGreater()) {
ComPtr<ITfInputProcessorProfileMgr> pInputProcessorProfileMgr;
hr = pInputProcessorProfileMgr.CoCreate(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL);
if (FAILED(hr))
return FALSE;

hr = pInputProcessorProfileMgr->RegisterProfile(
c_clsidTextService,
TEXTSERVICE_LANGID,
c_guidProfile,
TEXTSERVICE_DESC,
(ULONG)wcslen(TEXTSERVICE_DESC),
filename.c_str(),
filename.size(),
TEXTSERVICE_ICON_INDEX,
hkl,
0,
TRUE,
0);
}
else {
ComPtr<ITfInputProcessorProfiles> pInputProcessorProfiles;
hr = pInputProcessorProfiles.CoCreate(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER);
if (FAILED(hr))
return FALSE;

hr = pInputProcessorProfiles->Register(c_clsidTextService);
if (FAILED(hr))
return FALSE;

hr = pInputProcessorProfiles->AddLanguageProfile(
c_clsidTextService,
TEXTSERVICE_LANGID,
c_guidProfile,
TEXTSERVICE_DESC,
(ULONG)wcslen(TEXTSERVICE_DESC),
filename.c_str(),
filename.size(),
TEXTSERVICE_ICON_INDEX);
if (FAILED(hr))
return FALSE;
if (hkl) {
hr = pInputProcessorProfiles->SubstituteKeyboardLayout(
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, hkl);
if (FAILED(hr)) return FALSE;
}
}
return TRUE;
}

void UnregisterProfiles()
Expand All @@ -52,10 +82,12 @@ void UnregisterProfiles()
HRESULT hr;

hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
IID_ITfInputProcessorProfiles, (void **) &pInputProcessProfiles);
IID_ITfInputProcessorProfiles, (void **)&pInputProcessProfiles);
if (FAILED(hr))
return;

pInputProcessProfiles->SubstituteKeyboardLayout(
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, NULL);
pInputProcessProfiles->Unregister(c_clsidTextService);
pInputProcessProfiles->Release();
}
Expand All @@ -65,10 +97,10 @@ BOOL RegisterCategories()
ITfCategoryMgr *pCategoryMgr;
HRESULT hr;

hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **) &pCategoryMgr);
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
if (hr != S_OK)
return FALSE;

hr = pCategoryMgr->RegisterCategory(c_clsidTextService, GUID_TFCAT_TIP_KEYBOARD, c_clsidTextService);
if (hr != S_OK)
goto Exit;
Expand Down Expand Up @@ -97,7 +129,7 @@ void UnregisterCategories()
ITfCategoryMgr *pCategoryMgr;
HRESULT hr;

hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **) &pCategoryMgr);
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
if (FAILED(hr))
return;

Expand All @@ -107,15 +139,15 @@ void UnregisterCategories()

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

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

int i;
char *p = pchA;

const BYTE *pBytes = (const BYTE *) &refGUID;
const BYTE *pBytes = (const BYTE *)&refGUID;

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

BOOL RegisterServer()
BOOL RegisterServer(std::wstring filename, bool wow64)
{
DWORD dw;
HKEY hKey;
HKEY hSubKey;
BOOL fRet;
char achIMEKey[ARRAYSIZE(c_szInfoKeyPrefix) + CLSID_STRLEN];
TCHAR achFileName[MAX_PATH];
DWORD flags = KEY_WRITE;
if (wow64) {
flags |= KEY_WOW64_32KEY;
}
//TCHAR achFileName[MAX_PATH];

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

if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dw) == ERROR_SUCCESS)
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hKey, &dw) == ERROR_SUCCESS)
{
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *) TEXTSERVICE_DESC_A, (strlen(TEXTSERVICE_DESC_A) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *)TEXTSERVICE_DESC_A, (strlen(TEXTSERVICE_DESC_A) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, flags, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
{
dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));
//dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));

fRet &= RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE *) achFileName, (lstrlen(achFileName) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *) TEXTSERVICE_MODEL, (strlen(TEXTSERVICE_MODEL) + 1)) == ERROR_SUCCESS;
fRet &= RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE *)filename.c_str(), (filename.size() + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, (strlen(TEXTSERVICE_MODEL) + 1)) == ERROR_SUCCESS;
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
Expand Down
10 changes: 10 additions & 0 deletions WeaselSetup/TSFRegister.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include "stdafx.h"

BOOL RegisterProfiles(std::wstring filename, HKL hkl);
void UnregisterProfiles();
BOOL RegisterCategories();
void UnregisterCategories();
BOOL RegisterServer(std::wstring filename, bool wow64);
void UnregisterServer();
2 changes: 2 additions & 0 deletions WeaselSetup/WeaselSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "stdafx.h"
#include "WeaselSetup.h"
#include "InstallOptionsDialog.h"
#include <VersionHelpers.hpp>

CAppModule _Module;

Expand All @@ -14,6 +15,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
InitVersion();
UNREFERENCED_PARAMETER(hPrevInstance);

HRESULT hRes = ::CoInitialize(NULL);
Expand Down
2 changes: 2 additions & 0 deletions WeaselSetup/WeaselSetup.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
<ClInclude Include="Resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TSFRegister.h" />
<ClInclude Include="WeaselSetup.h" />
</ItemGroup>
<ItemGroup>
Expand All @@ -183,6 +184,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TSFRegister.cpp" />
<ClCompile Include="WeaselSetup.cpp" />
</ItemGroup>
<ItemGroup>
Expand Down
6 changes: 6 additions & 0 deletions WeaselSetup/WeaselSetup.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
<ClInclude Include="InstallOptionsDialog.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TSFRegister.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
Expand All @@ -53,6 +56,9 @@
<ClCompile Include="InstallOptionsDialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TSFRegister.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WeaselSetup.rc">
Expand Down
57 changes: 22 additions & 35 deletions WeaselSetup/imesetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
#include <vector>
#include <StringAlgorithm.hpp>
#include <WeaselCommon.h>
#include <msctf.h>

#include "TSFRegister.h"


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

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

HKL ImeHKL = 0;


using boost::filesystem::wpath;

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

Expand Down Expand Up @@ -337,45 +341,28 @@ void enable_profile(BOOL fEnable, bool hant) {
pProfiles->Release();
}
}

void unregister_text_service()
{
UnregisterProfiles();
UnregisterCategories();
UnregisterServer();
}
// 注册TSF输入法
int register_text_service(const wpath& tsf_path, bool register_ime, bool is_wow64, bool hant, bool silent)
{
if (!register_ime)
enable_profile(FALSE, hant);

std::wstring params = L" \"" + tsf_path.wstring() + L"\"";
if (!register_ime)
{
params = L" /u " + params; // unregister
}
//if (silent) // always silent
{
params = L" /s " + params;
}

SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = L"open"; // Operation to perform
shExInfo.lpFile = L"regsvr32.exe"; // Application to start
shExInfo.lpParameters = params.c_str(); // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;

if (ShellExecuteEx(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
CloseHandle(shExInfo.hProcess);
if (register_ime) {
if (!RegisterServer(tsf_path.wstring(), is_wow64) || !RegisterProfiles(tsf_path.wstring(), ImeHKL) || !RegisterCategories())
{
unregister_text_service();
MessageBox(NULL, L"註冊輸入法錯誤", L"安装/卸載失败", MB_ICONERROR | MB_OK);
return 1;
}
}
else
{
WCHAR msg[100];
wsprintf(msg, L"註冊輸入法錯誤 regsvr32.exe %s", params.c_str());
if (!silent) MessageBox(NULL, msg, L"安装/卸載失败", MB_ICONERROR | MB_OK);
return 1;
else {
unregister_text_service();
}

if (register_ime)
Expand Down
21 changes: 21 additions & 0 deletions WeaselSetup/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <windows.h>
#include <ShellAPI.h>
#include <Imm.h>
#include <msctf.h>

#include <atlbase.h>
#include <atlwin.h>
Expand All @@ -25,4 +26,24 @@

#include <boost/filesystem.hpp>

// {A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A}
extern const GUID c_clsidTextService;

// {3D02CAB6-2B8E-4781-BA20-1C9267529467}
extern const GUID c_guidProfile;

#ifndef TF_IPP_CAPS_IMMERSIVESUPPORT

#define WEASEL_USING_OLDER_TSF_SDK

/* for Windows 8 */
#define TF_TMF_IMMERSIVEMODE 0x40000000
#define TF_IPP_CAPS_IMMERSIVESUPPORT 0x00010000
#define TF_IPP_CAPS_SYSTRAYSUPPORT 0x00020000

extern const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT;
extern const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT;

#endif

// TODO: reference additional headers your program requires here
Loading

0 comments on commit 91cbd2c

Please sign in to comment.