284 lines
8.4 KiB
C++
284 lines
8.4 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
#include "Private.h"
|
|
#include "Globals.h"
|
|
|
|
static const WCHAR RegInfo_Prefix_CLSID[] = L"CLSID\\";
|
|
static const WCHAR RegInfo_Key_InProSvr32[] = L"InProcServer32";
|
|
static const WCHAR RegInfo_Key_ThreadModel[] = L"ThreadingModel";
|
|
|
|
static const WCHAR TEXTSERVICE_DESC[] = L"Sample IME";
|
|
|
|
static const GUID SupportCategories[] = {
|
|
GUID_TFCAT_TIP_KEYBOARD,
|
|
GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER,
|
|
GUID_TFCAT_TIPCAP_UIELEMENTENABLED,
|
|
GUID_TFCAT_TIPCAP_SECUREMODE,
|
|
GUID_TFCAT_TIPCAP_COMLESS,
|
|
GUID_TFCAT_TIPCAP_INPUTMODECOMPARTMENT,
|
|
GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT,
|
|
GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT,
|
|
};
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RegisterProfiles
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegisterProfiles()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
|
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfileMgr, (void**)&pITfInputProcessorProfileMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
WCHAR achIconFile[MAX_PATH] = {'\0'};
|
|
DWORD cchA = 0;
|
|
cchA = GetModuleFileName(Global::dllInstanceHandle, achIconFile, MAX_PATH);
|
|
cchA = cchA >= MAX_PATH ? (MAX_PATH - 1) : cchA;
|
|
achIconFile[cchA] = '\0';
|
|
|
|
size_t lenOfDesc = 0;
|
|
hr = StringCchLength(TEXTSERVICE_DESC, STRSAFE_MAX_CCH, &lenOfDesc);
|
|
if (hr != S_OK)
|
|
{
|
|
goto Exit;
|
|
}
|
|
hr = pITfInputProcessorProfileMgr->RegisterProfile(Global::SampleIMECLSID,
|
|
TEXTSERVICE_LANGID,
|
|
Global::SampleIMEGuidProfile,
|
|
TEXTSERVICE_DESC,
|
|
static_cast<ULONG>(lenOfDesc),
|
|
achIconFile,
|
|
cchA,
|
|
(UINT)TEXTSERVICE_ICON_INDEX, NULL, 0, TRUE, 0);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (pITfInputProcessorProfileMgr)
|
|
{
|
|
pITfInputProcessorProfileMgr->Release();
|
|
}
|
|
|
|
return (hr == S_OK);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnregisterProfiles
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UnregisterProfiles()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
|
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfileMgr, (void**)&pITfInputProcessorProfileMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pITfInputProcessorProfileMgr->UnregisterProfile(Global::SampleIMECLSID, TEXTSERVICE_LANGID, Global::SampleIMEGuidProfile, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (pITfInputProcessorProfileMgr)
|
|
{
|
|
pITfInputProcessorProfileMgr->Release();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RegisterCategories
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegisterCategories()
|
|
{
|
|
ITfCategoryMgr* pCategoryMgr = nullptr;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void**)&pCategoryMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for each(GUID guid in SupportCategories)
|
|
{
|
|
hr = pCategoryMgr->RegisterCategory(Global::SampleIMECLSID, guid, Global::SampleIMECLSID);
|
|
}
|
|
|
|
pCategoryMgr->Release();
|
|
|
|
return (hr == S_OK);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnregisterCategories
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UnregisterCategories()
|
|
{
|
|
ITfCategoryMgr* pCategoryMgr = S_OK;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void**)&pCategoryMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for each(GUID guid in SupportCategories)
|
|
{
|
|
pCategoryMgr->UnregisterCategory(Global::SampleIMECLSID, guid, Global::SampleIMECLSID);
|
|
}
|
|
|
|
pCategoryMgr->Release();
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RecurseDeleteKey
|
|
//
|
|
// RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
|
|
// specified key has subkeys
|
|
//----------------------------------------------------------------------------
|
|
|
|
LONG RecurseDeleteKey(_In_ HKEY hParentKey, _In_ LPCTSTR lpszKey)
|
|
{
|
|
HKEY regKeyHandle = nullptr;
|
|
LONG res = 0;
|
|
FILETIME time;
|
|
WCHAR stringBuffer[256] = {'\0'};
|
|
DWORD size = ARRAYSIZE(stringBuffer);
|
|
|
|
if (RegOpenKey(hParentKey, lpszKey, ®KeyHandle) != ERROR_SUCCESS)
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
res = ERROR_SUCCESS;
|
|
while (RegEnumKeyEx(regKeyHandle, 0, stringBuffer, &size, NULL, NULL, NULL, &time) == ERROR_SUCCESS)
|
|
{
|
|
stringBuffer[ARRAYSIZE(stringBuffer)-1] = '\0';
|
|
res = RecurseDeleteKey(regKeyHandle, stringBuffer);
|
|
if (res != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
size = ARRAYSIZE(stringBuffer);
|
|
}
|
|
RegCloseKey(regKeyHandle);
|
|
|
|
return res == ERROR_SUCCESS ? RegDeleteKey(hParentKey, lpszKey) : res;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RegisterServer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL RegisterServer()
|
|
{
|
|
DWORD copiedStringLen = 0;
|
|
HKEY regKeyHandle = nullptr;
|
|
HKEY regSubkeyHandle = nullptr;
|
|
BOOL ret = FALSE;
|
|
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
|
WCHAR achFileName[MAX_PATH] = {'\0'};
|
|
|
|
if (!CLSIDToString(Global::SampleIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
|
|
|
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, ®KeyHandle, &copiedStringLen) == ERROR_SUCCESS)
|
|
{
|
|
if (RegSetValueEx(regKeyHandle, NULL, 0, REG_SZ, (const BYTE *)TEXTSERVICE_DESC, (_countof(TEXTSERVICE_DESC))*sizeof(WCHAR)) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegCreateKeyEx(regKeyHandle, RegInfo_Key_InProSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, ®SubkeyHandle, &copiedStringLen) == ERROR_SUCCESS)
|
|
{
|
|
copiedStringLen = GetModuleFileNameW(Global::dllInstanceHandle, achFileName, ARRAYSIZE(achFileName));
|
|
copiedStringLen = (copiedStringLen >= (MAX_PATH - 1)) ? MAX_PATH : (++copiedStringLen);
|
|
if (RegSetValueEx(regSubkeyHandle, NULL, 0, REG_SZ, (const BYTE *)achFileName, (copiedStringLen)*sizeof(WCHAR)) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RegSetValueEx(regSubkeyHandle, RegInfo_Key_ThreadModel, 0, REG_SZ, (const BYTE *)TEXTSERVICE_MODEL, (_countof(TEXTSERVICE_MODEL)) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
ret = TRUE;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (regSubkeyHandle)
|
|
{
|
|
RegCloseKey(regSubkeyHandle);
|
|
regSubkeyHandle = nullptr;
|
|
}
|
|
if (regKeyHandle)
|
|
{
|
|
RegCloseKey(regKeyHandle);
|
|
regKeyHandle = nullptr;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnregisterServer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UnregisterServer()
|
|
{
|
|
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
|
|
|
if (!CLSIDToString(Global::SampleIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
|
{
|
|
return;
|
|
}
|
|
|
|
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
|
|
|
RecurseDeleteKey(HKEY_CLASSES_ROOT, achIMEKey);
|
|
}
|