365 lines
12 KiB
C++
365 lines
12 KiB
C++
#include "stdafx.h"
|
||
#include "PluginSettingsDlg.h"
|
||
#include "2015RemoteDlg.h"
|
||
#include "resource.h"
|
||
#include "jsoncpp/json.h"
|
||
#include <fstream>
|
||
#include <sstream>
|
||
|
||
#ifndef _WIN64
|
||
#ifdef _DEBUG
|
||
#pragma comment(lib, "jsoncpp/jsoncppd.lib")
|
||
#else
|
||
#pragma comment(lib, "jsoncpp/jsoncpp.lib")
|
||
#endif
|
||
#else
|
||
#ifdef _DEBUG
|
||
#pragma comment(lib, "jsoncpp/jsoncpp_x64d.lib")
|
||
#else
|
||
#pragma comment(lib, "jsoncpp/jsoncpp_x64.lib")
|
||
#endif
|
||
#endif
|
||
|
||
BEGIN_MESSAGE_MAP(CPluginSettingsDlg, CDialogLangEx)
|
||
ON_BN_CLICKED(IDC_BTN_SAVE, &CPluginSettingsDlg::OnBnClickedBtnSave)
|
||
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PLUGINS, &CPluginSettingsDlg::OnLvnItemchangedListPlugins)
|
||
END_MESSAGE_MAP()
|
||
|
||
CPluginSettingsDlg::CPluginSettingsDlg(std::vector<DllInfo*>& dllList, CWnd* pParent)
|
||
: CDialogLangEx(IDD_DIALOG_PLUGIN_SETTINGS, pParent)
|
||
, m_DllList(dllList)
|
||
, m_nSelectedIndex(-1)
|
||
{
|
||
}
|
||
|
||
CPluginSettingsDlg::~CPluginSettingsDlg()
|
||
{
|
||
}
|
||
|
||
void CPluginSettingsDlg::DoDataExchange(CDataExchange* pDX)
|
||
{
|
||
CDialogLangEx::DoDataExchange(pDX);
|
||
DDX_Control(pDX, IDC_LIST_PLUGINS, m_listPlugins);
|
||
DDX_Control(pDX, IDC_COMBO_RUNTYPE_P, m_comboRunType);
|
||
DDX_Control(pDX, IDC_COMBO_CALLTYPE, m_comboCallType);
|
||
DDX_Control(pDX, IDC_COMBO_MODE, m_comboMode);
|
||
DDX_Control(pDX, IDC_EDIT_INTERVAL, m_editInterval);
|
||
DDX_Control(pDX, IDC_EDIT_MAXCOUNT, m_editMaxCount);
|
||
}
|
||
|
||
BOOL CPluginSettingsDlg::OnInitDialog()
|
||
{
|
||
CDialogLangEx::OnInitDialog();
|
||
|
||
// 初始化列表控件
|
||
InitListCtrl();
|
||
|
||
// 初始化运行类型下拉框
|
||
m_comboRunType.InsertString(SHELLCODE, _TR("Shellcode"));
|
||
m_comboRunType.InsertString(MEMORYDLL, _TR("内存DLL"));
|
||
m_comboRunType.SetCurSel(MEMORYDLL);
|
||
|
||
// 初始化调用方式下拉框
|
||
m_comboCallType.InsertString(CALLTYPE_DEFAULT, _TR("自动检测"));
|
||
m_comboCallType.InsertString(CALLTYPE_IOCPTHREAD, _TR("IOCP线程"));
|
||
m_comboCallType.InsertString(CALLTYPE_FRPC_CALL, _TR("自定义FRPC[不可用]"));
|
||
m_comboCallType.InsertString(CALLTYPE_FRPC_STDCALL, _TR("标准FRPC[不可用]"));
|
||
m_comboCallType.SetCurSel(CALLTYPE_DEFAULT);
|
||
|
||
// 初始化调度模式下拉框
|
||
m_comboMode.InsertString(SCH_MODE_NONE, _TR("不自动执行"));
|
||
m_comboMode.InsertString(SCH_MODE_STARTUP, _TR("启动执行"));
|
||
m_comboMode.InsertString(SCH_MODE_DAILY, _TR("每日定时"));
|
||
m_comboMode.InsertString(SCH_MODE_WEEKLY, _TR("每周定时"));
|
||
m_comboMode.InsertString(SCH_MODE_MONTHLY, _TR("每月定时"));
|
||
m_comboMode.InsertString(SCH_MODE_YEARLY, _TR("每年定时"));
|
||
m_comboMode.InsertString(SCH_MODE_OFF, _TR("关闭执行"));
|
||
m_comboMode.SetCurSel(SCH_MODE_NONE);
|
||
|
||
// 加载配置
|
||
m_Configs = LoadPluginConfigs();
|
||
|
||
// 加载插件列表
|
||
LoadPluginsToList();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void CPluginSettingsDlg::InitListCtrl()
|
||
{
|
||
m_listPlugins.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
|
||
|
||
m_listPlugins.InsertColumn(0, _TR("名称"), LVCFMT_LEFT, 120);
|
||
m_listPlugins.InsertColumn(1, _TR("大小"), LVCFMT_RIGHT, 80);
|
||
m_listPlugins.InsertColumn(2, _TR("运行类型"), LVCFMT_LEFT, 80);
|
||
m_listPlugins.InsertColumn(3, _TR("调度模式"), LVCFMT_LEFT, 120);
|
||
m_listPlugins.InsertColumn(4, _TR("MD5"), LVCFMT_LEFT, 220);
|
||
|
||
GetDlgItem(IDC_STATIC_PLUGIN_SETTINGS)->SetWindowText(_TR("插件参数配置"));
|
||
GetDlgItem(IDC_STATIC_PLUGIN_RUNTYPE)->SetWindowText(_TR("运行类型:"));
|
||
GetDlgItem(IDC_STATIC_PLUGIN_CALLTYPE)->SetWindowText(_TR("调用方式:"));
|
||
GetDlgItem(IDC_STATIC_PLUGIN_SCHEDULE)->SetWindowText(_TR("调度模式:"));
|
||
GetDlgItem(IDC_STATIC_PLUGIN_INTERVAL)->SetWindowText(_TR("间隔(秒):"));
|
||
GetDlgItem(IDC_STATIC_PLUGIN_COUNTER)->SetWindowText(_TR("最大次数:"));
|
||
SetWindowText(_TR("插件设置"));
|
||
}
|
||
|
||
void CPluginSettingsDlg::LoadPluginsToList()
|
||
{
|
||
m_listPlugins.DeleteAllItems();
|
||
|
||
const char* runTypeNames[] = { "Shellcode", "内存DLL" };
|
||
const char* modeNames[] = { "不自动执行", "启动执行", "每日定时", "每周定时", "每月定时", "每年定时", "关闭执行", };
|
||
|
||
int index = 0;
|
||
for (const auto& dll : m_DllList) {
|
||
if (!dll || !dll->Data) continue;
|
||
|
||
// 获取 DllExecuteInfo
|
||
const char* buf = (char*)(dll->Data->Buf());
|
||
if (dll->Data->length() < 1 + sizeof(DllExecuteInfo)) continue;
|
||
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
|
||
|
||
// 查找或创建配置
|
||
PluginConfig* cfg = FindConfig(dll->Name);
|
||
|
||
m_listPlugins.InsertItem(index, CString(dll->Name.c_str()));
|
||
|
||
CString sizeStr;
|
||
sizeStr.Format(_T("%d KB"), info->Size / 1024);
|
||
m_listPlugins.SetItemText(index, 1, sizeStr);
|
||
|
||
int runType = cfg ? cfg->RunType : info->RunType;
|
||
int mode = cfg ? cfg->Mode : info->Schedule.Mode;
|
||
|
||
m_listPlugins.SetItemText(index, 2, _TR(runTypeNames[runType < RUNTYPE_MAX ? runType : MEMORYDLL]));
|
||
m_listPlugins.SetItemText(index, 3, _TR(modeNames[mode < SCH_MODE_MAX ? mode : SCH_MODE_NONE]));
|
||
m_listPlugins.SetItemText(index, 4, CString(info->Md5));
|
||
|
||
m_listPlugins.SetItemData(index, (DWORD_PTR)dll);
|
||
index++;
|
||
}
|
||
}
|
||
|
||
void CPluginSettingsDlg::OnLvnItemchangedListPlugins(NMHDR* pNMHDR, LRESULT* pResult)
|
||
{
|
||
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
|
||
*pResult = 0;
|
||
|
||
if (pNMLV->uNewState & LVIS_SELECTED) {
|
||
m_nSelectedIndex = pNMLV->iItem;
|
||
UpdateSelectedPluginInfo();
|
||
}
|
||
}
|
||
|
||
void CPluginSettingsDlg::UpdateSelectedPluginInfo()
|
||
{
|
||
if (m_nSelectedIndex < 0) return;
|
||
|
||
DllInfo* dll = reinterpret_cast<DllInfo*>(m_listPlugins.GetItemData(m_nSelectedIndex));
|
||
if (!dll || !dll->Data) return;
|
||
|
||
const char* buf = (char*)(dll->Data->Buf());
|
||
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
|
||
|
||
// 查找配置(如果有)
|
||
PluginConfig* cfg = FindConfig(dll->Name);
|
||
|
||
// 更新下拉框和编辑框
|
||
int runType = cfg ? cfg->RunType : info->RunType;
|
||
int callType = cfg ? cfg->CallType : info->CallType;
|
||
int mode = cfg ? cfg->Mode : info->Schedule.Mode;
|
||
unsigned int interval = cfg ? cfg->Interval : info->Schedule.Config.Startup.Interval;
|
||
unsigned char maxCount = cfg ? cfg->MaxCount : info->Schedule.MaxCount;
|
||
|
||
m_comboRunType.SetCurSel(runType < RUNTYPE_MAX ? runType : MEMORYDLL);
|
||
m_comboCallType.SetCurSel(callType < CALLTYPE_MAX ? callType : CALLTYPE_IOCPTHREAD);
|
||
m_comboMode.SetCurSel(mode < SCH_MODE_MAX ? mode : SCH_MODE_NONE);
|
||
|
||
CString str;
|
||
str.Format(_T("%u"), interval);
|
||
m_editInterval.SetWindowText(str);
|
||
|
||
str.Format(_T("%u"), maxCount);
|
||
m_editMaxCount.SetWindowText(str);
|
||
}
|
||
|
||
void CPluginSettingsDlg::OnBnClickedBtnSave()
|
||
{
|
||
if (m_nSelectedIndex < 0) {
|
||
MessageBoxL(_T("请先选择一个插件"), _T("提示"), MB_ICONINFORMATION);
|
||
return;
|
||
}
|
||
|
||
SaveCurrentPluginConfig();
|
||
SavePluginConfigs(m_Configs);
|
||
|
||
// 刷新列表显示
|
||
LoadPluginsToList();
|
||
|
||
// 重新选中
|
||
m_listPlugins.SetItemState(m_nSelectedIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
||
|
||
MessageBoxL(_T("配置已保存"), _T("提示"), MB_ICONINFORMATION);
|
||
}
|
||
|
||
void CPluginSettingsDlg::SaveCurrentPluginConfig()
|
||
{
|
||
if (m_nSelectedIndex < 0) return;
|
||
|
||
DllInfo* dll = reinterpret_cast<DllInfo*>(m_listPlugins.GetItemData(m_nSelectedIndex));
|
||
if (!dll || !dll->Data) return;
|
||
|
||
const char* buf = (char*)dll->Data->Buf();
|
||
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
|
||
|
||
// 查找或创建配置
|
||
PluginConfig* cfg = FindConfig(dll->Name);
|
||
if (!cfg) {
|
||
PluginConfig newCfg;
|
||
newCfg.Name = dll->Name;
|
||
m_Configs.push_back(newCfg);
|
||
cfg = &m_Configs.back();
|
||
}
|
||
|
||
cfg->Md5 = info->Md5;
|
||
cfg->RunType = m_comboRunType.GetCurSel();
|
||
cfg->CallType = m_comboCallType.GetCurSel();
|
||
cfg->Mode = (unsigned char)m_comboMode.GetCurSel();
|
||
|
||
CString str;
|
||
m_editInterval.GetWindowText(str);
|
||
cfg->Interval = _ttoi(str);
|
||
|
||
m_editMaxCount.GetWindowText(str);
|
||
cfg->MaxCount = (unsigned char)_ttoi(str);
|
||
|
||
// 更新 DllInfo 中的 Buffer(修改 DllExecuteInfo)
|
||
DllExecuteInfo* infoMut = const_cast<DllExecuteInfo*>(info);
|
||
infoMut->RunType = cfg->RunType;
|
||
infoMut->CallType = cfg->CallType;
|
||
infoMut->Schedule.Mode = cfg->Mode;
|
||
infoMut->Schedule.Config.Startup.Interval = cfg->Interval;
|
||
infoMut->Schedule.MaxCount = cfg->MaxCount;
|
||
}
|
||
|
||
PluginConfig* CPluginSettingsDlg::FindConfig(const std::string& name)
|
||
{
|
||
for (auto& cfg : m_Configs) {
|
||
if (cfg.Name == name) {
|
||
return &cfg;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
std::string CPluginSettingsDlg::GetPluginConfigPath()
|
||
{
|
||
std::string dbPath = GetDbPath();
|
||
// 获取目录部分
|
||
size_t pos = dbPath.find_last_of("\\/");
|
||
std::string dir = (pos != std::string::npos) ? dbPath.substr(0, pos + 1) : "";
|
||
return dir + "plugins.json";
|
||
}
|
||
|
||
std::vector<PluginConfig> CPluginSettingsDlg::LoadPluginConfigs()
|
||
{
|
||
std::vector<PluginConfig> configs;
|
||
std::string path = GetPluginConfigPath();
|
||
|
||
std::ifstream file(path);
|
||
if (!file.is_open()) {
|
||
return configs;
|
||
}
|
||
|
||
Json::Value root;
|
||
Json::CharReaderBuilder builder;
|
||
std::string errors;
|
||
|
||
if (!Json::parseFromStream(builder, file, &root, &errors)) {
|
||
return configs;
|
||
}
|
||
|
||
if (!root.isArray()) {
|
||
return configs;
|
||
}
|
||
|
||
for (const auto& item : root) {
|
||
PluginConfig cfg;
|
||
cfg.Name = item.get("name", "").asString();
|
||
cfg.Md5 = item.get("md5", "").asString();
|
||
cfg.RunType = item.get("runType", MEMORYDLL).asInt();
|
||
cfg.CallType = item.get("callType", CALLTYPE_IOCPTHREAD).asInt();
|
||
cfg.Mode = (unsigned char)item.get("mode", SCH_MODE_NONE).asInt();
|
||
cfg.Flags = (unsigned char)item.get("flags", 0).asInt();
|
||
cfg.Interval = item.get("interval", 0).asUInt();
|
||
cfg.MaxCount = (unsigned char)item.get("maxCount", 0).asInt();
|
||
|
||
if (!cfg.Name.empty()) {
|
||
configs.push_back(cfg);
|
||
}
|
||
}
|
||
|
||
return configs;
|
||
}
|
||
|
||
void CPluginSettingsDlg::SavePluginConfigs(const std::vector<PluginConfig>& configs)
|
||
{
|
||
std::string path = GetPluginConfigPath();
|
||
|
||
Json::Value root(Json::arrayValue);
|
||
|
||
for (const auto& cfg : configs) {
|
||
Json::Value item;
|
||
item["name"] = cfg.Name;
|
||
item["md5"] = cfg.Md5;
|
||
item["runType"] = cfg.RunType;
|
||
item["callType"] = cfg.CallType;
|
||
item["mode"] = cfg.Mode;
|
||
item["flags"] = cfg.Flags;
|
||
item["interval"] = cfg.Interval;
|
||
item["maxCount"] = cfg.MaxCount;
|
||
root.append(item);
|
||
}
|
||
|
||
std::ofstream file(path);
|
||
if (file.is_open()) {
|
||
Json::StreamWriterBuilder builder;
|
||
builder["indentation"] = " ";
|
||
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
||
writer->write(root, &file);
|
||
}
|
||
}
|
||
|
||
void CPluginSettingsDlg::PatchDllList(std::vector<DllInfo*>& dllList)
|
||
{
|
||
std::vector<PluginConfig> configs = LoadPluginConfigs();
|
||
|
||
for (auto& dll : dllList) {
|
||
if (!dll || !dll->Data) continue;
|
||
|
||
// 查找对应的配置
|
||
PluginConfig* cfg = nullptr;
|
||
for (auto& c : configs) {
|
||
if (c.Name == dll->Name) {
|
||
cfg = &c;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!cfg) continue;
|
||
|
||
// 更新 DllExecuteInfo
|
||
char* buf = (char*)dll->Data->Buf();
|
||
if (dll->Data->length() < 1 + sizeof(DllExecuteInfo)) continue;
|
||
|
||
DllExecuteInfo* info = reinterpret_cast<DllExecuteInfo*>(buf + 1);
|
||
info->RunType = cfg->RunType;
|
||
info->CallType = cfg->CallType;
|
||
info->Schedule.Mode = cfg->Mode;
|
||
info->Schedule.Flags = cfg->Flags;
|
||
info->Schedule.Config.Startup.Interval = cfg->Interval;
|
||
info->Schedule.MaxCount = cfg->MaxCount;
|
||
}
|
||
}
|