2021SC@SDUSC
在之前的文章中,我们对Weasel输入法的总体结构和相关的头文件WeaselIPC.h进行了分析,接下来我们将从WeaselServer.cpp开始,对于代码的其他部分进行具体的分析。
一、WeaselServer.cpp总体介绍:
Weasel作为一个可以进行网络化使用的输入法,网络化共享模块的使用是使其与其他输入法不同的重要原因,WeaselServer.cpp作为Weasel网络化部分的重要一环,主要配置了远程服务器相关的重要服务,使得输入法可以通过服务器实现对于文字库的文字系统的实时更新,使得当处于不同网络环境下的用户导入全新的文字库时,可以实现所有用户的文字库进行同时更新,接下来将通过代码进行具体功能的分析.
二、代码驱动的功能分析
总体模块代码如下图所示:
// WeaselServer.cpp : main source file for WeaselServer.exe
//
// WTL MessageLoop 封装了消息循环. 实现了 getmessage/dispatchmessage....
#include "stdafx.h"
#include "resource.h"
#include "WeaselService.h"
#include <WeaselIPC.h>
#include <WeaselUI.h>
#include <RimeWithWeasel.h>
#include <WeaselUtility.h>
#include <winsparkle.h>
#include <functional>
#include <memory>
CAppModule _Module;
typedef enum PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef enum MONITOR_DPI_TYPE {
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
InitVersion();
// Set DPI awareness (Windows 8.1+)
if (IsWindows8Point1OrGreater())
{
using PSPDA = HRESULT (WINAPI *)(PROCESS_DPI_AWARENESS);
HMODULE shcore_module = ::LoadLibrary(_T("shcore.dll"));
if (shcore_module != NULL)
{
PSPDA SetProcessDpiAwareness = (PSPDA)::GetProcAddress(shcore_module, "SetProcessDpiAwareness");
SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
::FreeLibrary(shcore_module);
}
}
// 防止服务进程开启输入法
ImmDisableIME(-1);
WCHAR user_name[20] = {0};
DWORD size = _countof(user_name);
GetUserName(user_name, &size);
if (!_wcsicmp(user_name, L"SYSTEM"))
{
return 1;
}
HRESULT hRes = ::CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call instead to
// make the EXE free threaded. This means that calls come in on a random RPC thread.
//HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
ATLASSERT(SUCCEEDED(hRes));
// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
::DefWindowProc(NULL, 0, 0, 0L);
AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls
hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));
if (!wcscmp(L"/userdir", lpstrCmdLine))
{
CreateDirectory(WeaselUserDataPath().c_str(), NULL);
WeaselServerApp::explore(WeaselUserDataPath());
return 0;
}
if (!wcscmp(L"/weaseldir", lpstrCmdLine))
{
WeaselServerApp::explore(WeaselServerApp::install_dir());
return 0;
}
// command line option /q stops the running server
bool quit = !wcscmp(L"/q", lpstrCmdLine) || !wcscmp(L"/quit", lpstrCmdLine);
// restart if already running
{
weasel::Client client;
if (client.Connect()) // try to connect to running server
{
client.ShutdownServer();
}
if (quit)
return 0;
}
bool check_updates = !wcscmp(L"/update", lpstrCmdLine);
if (check_updates)
{
WeaselServerApp::check_update();
}
CreateDirectory(WeaselUserDataPath().c_str(), NULL);
int nRet = 0;
try
{
WeaselServerApp app;
if (IsWindowsVistaOrGreater())
{
PRAR RegisterApplicationRestart = (PRAR)::GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "RegisterApplicationRestart");
RegisterApplicationRestart(NULL, 0);
}
nRet = app.Run();
}
catch (...)
{
// bad luck...
nRet = -1;
}
_Module.Term();
::CoUninitialize();
return nRet;
}
首先,我们来看代码的起始部分:
typedef enum PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef enum MONITOR_DPI_TYPE {
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;
利用了两个枚举变量来设置server在不同的环境中所应该进行的分辨率DPI模式,PROCESS_DPI_AWARENESS规定了server是否能够获得具体DPI的三种状态,当进程无法取得具体的分辨率时,对应的int数为0,当进程可以从操作系统得到具体的DPI数值时,对应的DPI为1,当进程从之前的监视器获得具体的DPI数值时,所对应的int数值为2.
第二个枚举变量则设置了监视器所监视的DPI类型,0代表主要检测有效的DPI,1代表检测角DPI,2代表检测行DPI,监视器默认被设置为监视有效DPI.
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
InitVersion();
// Set DPI awareness (Windows 8.1+)
if (IsWindows8Point1OrGreater())
{
using PSPDA = HRESULT (WINAPI *)(PROCESS_DPI_AWARENESS);
HMODULE shcore_module = ::LoadLibrary(_T("shcore.dll"));
if (shcore_module != NULL)
{
PSPDA SetProcessDpiAwareness = (PSPDA)::GetProcAddress(shcore_module, "SetProcessDpiAwareness");
SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
::FreeLibrary(shcore_module);
}
}
此段代码根据Windows的版本来确定DPI的监视状态,如果Windows的版本时8.1以及更高的版本,就将DPI的监视模式设置为可见的.
ImmDisableIME(-1);
WCHAR user_name[20] = {0};
DWORD size = _countof(user_name);
GetUserName(user_name, &size);
if (!_wcsicmp(user_name, L"SYSTEM"))
{
return 1;
}
接下来利用ImmDisableIME方法确保server文件不会将输入法打开,ImmDisableIME文件是一个定义在imm.h中的布尔类型方法,当其中传入的值为-1时,则关闭了输入法的启动渠道,使输入法无法启动.本段代码还利用了一个变长的user_name数组来存储登录server时传入的用户名,并通过user_name与SYSTEM进行比较,如果相同,则为SYSTEM模式.