Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tsf): get IME keyboard identifier by searching registry #272

Merged
merged 1 commit into from
Sep 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions WeaselSetup/TSFRegister.h

This file was deleted.

2 changes: 0 additions & 2 deletions WeaselSetup/WeaselSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "stdafx.h"
#include "WeaselSetup.h"
#include "InstallOptionsDialog.h"
#include <VersionHelpers.hpp>

CAppModule _Module;

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

HRESULT hRes = ::CoInitialize(NULL);
Expand Down
2 changes: 0 additions & 2 deletions WeaselSetup/WeaselSetup.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
<ClInclude Include="Resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TSFRegister.h" />
<ClInclude Include="WeaselSetup.h" />
</ItemGroup>
<ItemGroup>
Expand All @@ -107,7 +106,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TSFRegister.cpp" />
<ClCompile Include="WeaselSetup.cpp" />
</ItemGroup>
<ItemGroup>
Expand Down
6 changes: 0 additions & 6 deletions WeaselSetup/WeaselSetup.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@
<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 @@ -56,9 +53,6 @@
<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
65 changes: 40 additions & 25 deletions WeaselSetup/imesetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
#include <vector>
#include <StringAlgorithm.hpp>
#include <WeaselCommon.h>

#include "TSFRegister.h"
#include <msctf.h>
#include <strsafe.h>


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

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

HKL ImeHKL = 0;

BOOL copy_file(const std::wstring& src, const std::wstring& dest)
{
Expand Down Expand Up @@ -109,12 +108,12 @@ int install_ime_file(std::wstring& srcPath, const std::wstring& ext, bool hant,
if (!silent) MessageBoxW(NULL, destPath.c_str(), L"安裝失敗", MB_ICONERROR | MB_OK);
return 1;
}
retval += func(destPath, true, true, hant, silent);
if (fnWow64RevertWow64FsRedirection == NULL || fnWow64RevertWow64FsRedirection(OldValue) == FALSE)
{
if (!silent) MessageBoxW(NULL, L"無法恢復文件系統重定向", L"安裝失敗", MB_ICONERROR | MB_OK);
return 1;
}
retval += func(destPath, true, true, hant, silent);
}
return retval;
}
Expand Down Expand Up @@ -179,9 +178,9 @@ int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64,
LSTATUS ret = RegOpenKey(HKEY_LOCAL_MACHINE, KEYBOARD_LAYOUTS_KEY, &hKey);
if (ret == ERROR_SUCCESS)
{
for (DWORD k = 0xE0200000 + (hant ? 0x0404 : 0x0804); true; k += 0x10000)
for (DWORD k = 0xE0200000 + (hant ? 0x0404 : 0x0804); k <= 0xE0FF0804; k += 0x10000)
{
wsprintf(hkl_str, L"%08X", k);
StringCchPrintfW(hkl_str, _countof(hkl_str), L"%08X", k);
HKEY hSubKey;
ret = RegOpenKey(hKey, hkl_str, &hSubKey);
if (ret == ERROR_SUCCESS)
Expand Down Expand Up @@ -248,11 +247,10 @@ int register_ime(const std::wstring& ime_path, bool register_ime, bool is_wow64,
{
DWORD dwErr = GetLastError();
WCHAR msg[100];
wsprintf(msg, L"註冊輸入法錯誤 ImmInstallIME: HKL=%x Err=%x", hKL, dwErr);
StringCchPrintfW(msg, _countof(msg), L"註冊輸入法錯誤 ImmInstallIME: HKL=%x Err=%x", hKL, dwErr);
if (!silent) MessageBox(NULL, msg, L"安裝失敗", MB_ICONERROR | MB_OK);
return 1;
}
ImeHKL = hKL;
return 0;
}

Expand Down Expand Up @@ -366,28 +364,45 @@ void enable_profile(BOOL fEnable, bool hant) {
pProfiles->Release();
}
}
void unregister_text_service()
{
UnregisterProfiles();
UnregisterCategories();
UnregisterServer();
}

// 注册TSF输入法
int register_text_service(const std::wstring& tsf_path, bool register_ime, bool is_wow64, bool hant, bool silent)
{
using RegisterServerFunction = HRESULT (STDAPICALLTYPE *)();

if (!register_ime)
enable_profile(FALSE, hant);

if (register_ime) {
if (!RegisterServer(tsf_path, is_wow64) || !RegisterProfiles(tsf_path, ImeHKL) || !RegisterCategories())
{
unregister_text_service();
MessageBox(NULL, L"註冊輸入法錯誤", L"安装/卸載失败", MB_ICONERROR | MB_OK);
return 1;
}
std::wstring params = L" \"" + tsf_path + L"\"";
if (!register_ime)
{
params = L" /u " + params; // unregister
}
else {
unregister_text_service();
//if (silent) // always silent
{
params = L" /s " + params;
}
SHELLEXECUTEINFOW 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 (ShellExecuteExW(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
CloseHandle(shExInfo.hProcess);
}
else
{
WCHAR msg[100];
StringCchPrintfW(msg, _countof(msg), L"註冊輸入法錯誤 regsvr32.exe %s", params.c_str());
if (!silent) MessageBoxW(NULL, msg, L"安装/卸載失败", MB_ICONERROR | MB_OK);
return 1;
}

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

#include <atlbase.h>
#include <atlwin.h>
Expand All @@ -24,26 +23,6 @@
#include <wtl/atlmisc.h>
#include <wtl/atldlgs.h>

// {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

#include <string>
11 changes: 11 additions & 0 deletions WeaselTSF/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
#include "stdafx.h"
#include <WeaselCommon.h>

#ifdef WEASEL_HANT
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
#else
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
#endif

#define TEXTSERVICE_DESC WEASEL_IME_NAME
#define TEXTSERVICE_DESC_A "Weasel"
#define TEXTSERVICE_MODEL "Apartment"

#define TEXTSERVICE_ICON_INDEX 0

void DllAddRef();
void DllRelease();
Expand Down
93 changes: 55 additions & 38 deletions WeaselSetup/TSFRegister.cpp → WeaselTSF/Register.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "stdafx.h"
#include "TSFRegister.h"
#include <WeaselCommon.h>
#include "Register.h"
#include <strsafe.h>
#include <VersionHelpers.hpp>

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

#ifdef WEASEL_USING_OLDER_TSF_SDK

/* For Windows 8 */
const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT =
{ 0x13A016DF, 0x560B, 0x46CD,{ 0x94, 0x7A, 0x4C, 0x3A, 0xF1, 0xE0, 0xE3, 0x5D } };

const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT =
{ 0x25504FB4, 0x7BAB, 0x4BC1,{ 0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5 } };

#endif
HKL FindIME()
{
HKL hKL = NULL;
WCHAR key[9];
HKEY hKey;
LSTATUS ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts", 0, KEY_READ, &hKey);
if (ret == ERROR_SUCCESS)
{
for (DWORD id = (0xE0200000 | TEXTSERVICE_LANGID); hKL == NULL && id <= (0xE0FF0000 | TEXTSERVICE_LANGID); id += 0x10000)
{
StringCchPrintfW(key, _countof(key), L"%08X", id);
HKEY hSubKey;
ret = RegOpenKeyExW(hKey, key, 0, KEY_READ, &hSubKey);
if (ret == ERROR_SUCCESS)
{
WCHAR data[32];
DWORD type;
DWORD size = sizeof data;
ret = RegQueryValueExW(hSubKey, L"Ime File", NULL, &type, (LPBYTE)data, &size);
if (ret == ERROR_SUCCESS && type == REG_SZ && _wcsicmp(data, L"weasel.ime") == 0)
hKL = (HKL)id;
}
RegCloseKey(hSubKey);
}
}
RegCloseKey(hKey);
return hKL;
}

BOOL RegisterProfiles(std::wstring filename, HKL hkl)
BOOL RegisterProfiles()
{
WCHAR achIconFile[MAX_PATH];
ULONG cchIconFile = GetModuleFileNameW(g_hInst, achIconFile, ARRAYSIZE(achIconFile));
HRESULT hr;

if (IsWindows8OrGreater()) {
if (IsWindows8OrGreater())
{
CComPtr<ITfInputProcessorProfileMgr> pInputProcessorProfileMgr;
hr = pInputProcessorProfileMgr.CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL);
if (FAILED(hr))
Expand All @@ -37,15 +58,16 @@ BOOL RegisterProfiles(std::wstring filename, HKL hkl)
c_guidProfile,
TEXTSERVICE_DESC,
(ULONG)wcslen(TEXTSERVICE_DESC),
filename.c_str(),
filename.size(),
achIconFile,
cchIconFile,
TEXTSERVICE_ICON_INDEX,
hkl,
FindIME(),
0,
TRUE,
0);
}
else {
else
{
CComPtr<ITfInputProcessorProfiles> pInputProcessorProfiles;
hr = pInputProcessorProfiles.CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER);
if (FAILED(hr))
Expand All @@ -61,16 +83,16 @@ BOOL RegisterProfiles(std::wstring filename, HKL hkl)
c_guidProfile,
TEXTSERVICE_DESC,
(ULONG)wcslen(TEXTSERVICE_DESC),
filename.c_str(),
filename.size(),
achIconFile,
cchIconFile,
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;
}

hr = pInputProcessorProfiles->SubstituteKeyboardLayout(
c_clsidTextService, TEXTSERVICE_LANGID, c_guidProfile, FindIME());
if (FAILED(hr))
return FALSE;
}
return TRUE;
}
Expand Down Expand Up @@ -108,7 +130,6 @@ BOOL RegisterCategories()
if (hr != S_OK)
goto Exit;

InitVersion();
if (IsWindows8OrGreater())
{
hr = pCategoryMgr->RegisterCategory(c_clsidTextService, GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT, c_clsidTextService);
Expand Down Expand Up @@ -189,32 +210,28 @@ static LONG RecurseDeleteKeyA(HKEY hParentKey, LPCSTR lpszKey)
return lRes == ERROR_SUCCESS ? RegDeleteKeyA(hParentKey, lpszKey) : lRes;
}

BOOL RegisterServer(std::wstring filename, bool wow64)
BOOL RegisterServer()
{
DWORD dw;
HKEY hKey;
HKEY hSubKey;
BOOL fRet;
char achIMEKey[ARRAYSIZE(c_szInfoKeyPrefix) + CLSID_STRLEN];
DWORD flags = KEY_WRITE;
if (wow64) {
flags |= KEY_WOW64_64KEY;
}
//TCHAR achFileName[MAX_PATH];
char 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, flags, NULL, &hKey, &dw) == ERROR_SUCCESS)
if (fRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, 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, flags, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
fRet &= RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE *)TEXTSERVICE_DESC_A, sizeof TEXTSERVICE_DESC_A) == ERROR_SUCCESS;
if (fRet &= RegCreateKeyExA(hKey, c_szInProcSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, &dw) == ERROR_SUCCESS)
{
//dw = GetModuleFileName(g_hInst, achFileName, ARRAYSIZE(achFileName));
dw = GetModuleFileNameA(g_hInst, achFileName, ARRAYSIZE(achFileName));

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;
fRet &= RegSetValueExA(hSubKey, NULL, 0, REG_SZ, (BYTE *)achFileName, (strlen(achFileName) + 1) * sizeof(char)) == ERROR_SUCCESS;
fRet &= RegSetValueExA(hSubKey, c_szModelName, 0, REG_SZ, (BYTE *)TEXTSERVICE_MODEL, sizeof TEXTSERVICE_MODEL) == ERROR_SUCCESS;
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
Expand Down
Loading