Feature: refactor ClientList and add dialog to show it

This commit is contained in:
yuanyuanxiang
2026-01-18 22:39:36 +01:00
parent f4fe81be34
commit 5fc9ef1eb0
20 changed files with 578 additions and 362 deletions

View File

@@ -11,138 +11,89 @@
#include <location.h> #include <location.h>
#include "ScreenCapture.h" #include "ScreenCapture.h"
// by ChatGPT
bool IsWindows11()
{
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
RTL_OSVERSIONINFOW rovi = { 0 };
rovi.dwOSVersionInfoSize = sizeof(rovi);
HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
if (hMod) {
RtlGetVersionPtr rtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion");
if (rtlGetVersion) {
rtlGetVersion(&rovi);
return (rovi.dwMajorVersion == 10 && rovi.dwMinorVersion == 0 && rovi.dwBuildNumber >= 22000);
}
}
return false;
}
/************************************************************************
---------------------
作者IT1995
来源CSDN
原文https://blog.csdn.net/qq78442761/article/details/64440535
版权声明:本文为博主原创文章,转载请附上博文链接!
修改说明2019.3.29由袁沅祥修改
************************************************************************/
std::string getSystemName() std::string getSystemName()
{ {
std::string vname("未知操作系统"); typedef void(__stdcall* NTPROC)(DWORD*, DWORD*, DWORD*);
//先判断是否为win8.1或win10
typedef void(__stdcall*NTPROC)(DWORD*, DWORD*, DWORD*);
HINSTANCE hinst = LoadLibrary("ntdll.dll");
if (hinst == NULL) {
return vname;
}
if (IsWindows11()) {
vname = "Windows 11";
Mprintf("此电脑的版本为:%s\n", vname.c_str());
return vname;
}
DWORD dwMajor, dwMinor, dwBuildNumber;
NTPROC proc = (NTPROC)GetProcAddress(hinst, "RtlGetNtVersionNumbers");
if (proc==NULL) {
return vname;
}
proc(&dwMajor, &dwMinor, &dwBuildNumber);
if (dwMajor == 6 && dwMinor == 3) { //win 8.1
vname = "Windows 8.1";
Mprintf("此电脑的版本为:%s\n", vname.c_str());
return vname;
}
if (dwMajor == 10 && dwMinor == 0) { //win 10
vname = "Windows 10";
Mprintf("此电脑的版本为:%s\n", vname.c_str());
return vname;
}
//下面不能判断Win Server因为本人还未有这种系统的机子暂时不给出
//判断win8.1以下的版本 HINSTANCE hinst = LoadLibrary("ntdll.dll");
SYSTEM_INFO info; //用SYSTEM_INFO结构判断64位AMD处理器 if (!hinst) {
GetSystemInfo(&info); //调用GetSystemInfo函数填充结构 return "未知操作系统";
OSVERSIONINFOEX os; }
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (GetVersionEx((OSVERSIONINFO *)&os)) { NTPROC proc = (NTPROC)GetProcAddress(hinst, "RtlGetNtVersionNumbers");
//下面根据版本信息判断操作系统名称 if (!proc) {
switch (os.dwMajorVersion) { FreeLibrary(hinst);
//判断主版本号 return "未知操作系统";
case 4: }
switch (os.dwMinorVersion) {
//判断次版本号 DWORD dwMajor, dwMinor, dwBuildNumber;
case 0: proc(&dwMajor, &dwMinor, &dwBuildNumber);
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) dwBuildNumber &= 0xFFFF; // 高位是标志位只取低16位
vname ="Windows NT 4.0"; //1996年7月发布
else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) FreeLibrary(hinst);
vname = "Windows 95";
break; // 判断是否为 Server 版本
case 10: OSVERSIONINFOEX osvi = { sizeof(osvi) };
vname ="Windows 98"; GetVersionEx((OSVERSIONINFO*)&osvi);
break; bool isServer = (osvi.wProductType != VER_NT_WORKSTATION);
case 90:
vname = "Windows Me"; std::string vname;
break;
} if (dwMajor == 10 && dwMinor == 0) {
break; if (isServer) {
case 5: // Windows Server
switch (os.dwMinorVersion) { if (dwBuildNumber >= 20348)
//再比较dwMinorVersion的值 vname = "Windows Server 2022";
case 0: else if (dwBuildNumber >= 17763)
vname = "Windows 2000"; //1999年12月发布 vname = "Windows Server 2019";
break; else
case 1: vname = "Windows Server 2016";
vname = "Windows XP"; //2001年8月发布
break;
case 2:
if (os.wProductType == VER_NT_WORKSTATION &&
info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
vname = "Windows XP Professional x64 Edition";
else if (GetSystemMetrics(SM_SERVERR2) == 0)
vname = "Windows Server 2003"; //2003年3月发布
else if (GetSystemMetrics(SM_SERVERR2) != 0)
vname = "Windows Server 2003 R2";
break;
}
break;
case 6:
switch (os.dwMinorVersion) {
case 0:
if (os.wProductType == VER_NT_WORKSTATION)
vname = "Windows Vista";
else
vname = "Windows Server 2008"; //服务器版本
break;
case 1:
if (os.wProductType == VER_NT_WORKSTATION)
vname = "Windows 7";
else
vname = "Windows Server 2008 R2";
break;
case 2:
if (os.wProductType == VER_NT_WORKSTATION)
vname = "Windows 8";
else
vname = "Windows Server 2012";
break;
}
break;
default:
vname = "未知操作系统";
} }
Mprintf("此电脑的版本为:%s\n", vname.c_str()); else {
} else // Windows 桌面版
Mprintf("版本获取失败\n"); if (dwBuildNumber >= 22000)
vname = "Windows 11";
else
vname = "Windows 10";
}
}
else if (dwMajor == 6) {
switch (dwMinor) {
case 3:
vname = isServer ? "Windows Server 2012 R2" : "Windows 8.1";
break;
case 2:
vname = isServer ? "Windows Server 2012" : "Windows 8";
break;
case 1:
vname = isServer ? "Windows Server 2008 R2" : "Windows 7";
break;
case 0:
vname = isServer ? "Windows Server 2008" : "Windows Vista";
break;
}
}
else if (dwMajor == 5) {
switch (dwMinor) {
case 2:
vname = "Windows Server 2003";
break;
case 1:
vname = "Windows XP";
break;
case 0:
vname = "Windows 2000";
break;
}
}
if (vname.empty()) {
char buf[64];
sprintf(buf, "Windows (Build %d)", dwBuildNumber);
vname = buf;
}
Mprintf("此电脑的版本为:%s (Build %d)\n", vname.c_str(), dwBuildNumber);
return vname; return vname;
} }

View File

@@ -106,12 +106,18 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;ECB=0;CTR=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819;4838</DisableSpecificWarnings> <DisableSpecificWarnings>4018;4244;4267;4819;4838</DisableSpecificWarnings>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -142,12 +148,17 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;ECB=0;CTR=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819;4838</DisableSpecificWarnings> <DisableSpecificWarnings>4018;4244;4267;4819;4838</DisableSpecificWarnings>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>

View File

@@ -37,6 +37,8 @@ NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
#include <string.h> // CBC mode, for memset #include <string.h> // CBC mode, for memset
#include "aes.h" #include "aes.h"
#pragma intrinsic(memcpy)
/*****************************************************************************/ /*****************************************************************************/
/* Defines: */ /* Defines: */
/*****************************************************************************/ /*****************************************************************************/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -47,6 +47,7 @@
#include "SplashDlg.h" #include "SplashDlg.h"
#include <ServerServiceWrapper.h> #include <ServerServiceWrapper.h>
#include "CDlgFileSend.h" #include "CDlgFileSend.h"
#include "CClientListDlg.h"
#ifdef _DEBUG #ifdef _DEBUG
#define new DEBUG_NEW #define new DEBUG_NEW
@@ -115,49 +116,6 @@ std::string PluginPath()
return path; return path;
} }
//////////////////////////////////////////////////////////////////////////
// 保存 unordered_map 到文件
void SaveToFile(const ComputerNoteMap& data, const std::string& filename)
{
std::ofstream outFile(filename, std::ios::binary); // 打开文件(以二进制模式)
if (outFile.is_open()) {
for (const auto& pair : data) {
outFile.write(reinterpret_cast<const char*>(&pair.first), sizeof(ClientKey)); // 保存 key
int valueSize = pair.second.GetLength();
outFile.write(reinterpret_cast<const char*>(&valueSize), sizeof(int)); // 保存 value 的大小
outFile.write((char*)&pair.second, valueSize); // 保存 value 字符串
}
outFile.close();
} else {
Mprintf("Unable to open file '%s' for writing!\n", filename.c_str());
}
}
// 从文件读取 unordered_map 数据
void LoadFromFile(ComputerNoteMap& data, const std::string& filename)
{
std::ifstream inFile(filename, std::ios::binary); // 打开文件(以二进制模式)
if (inFile.is_open()) {
while (inFile.peek() != EOF) {
ClientKey key;
inFile.read(reinterpret_cast<char*>(&key), sizeof(ClientKey)); // 读取 key
int valueSize;
inFile.read(reinterpret_cast<char*>(&valueSize), sizeof(int)); // 读取 value 的大小
ClientValue value;
inFile.read((char*)&value, valueSize); // 读取 value 字符串
data[key] = value; // 插入到 map 中
}
inFile.close();
} else {
Mprintf("Unable to open file '%s' for reading!\n", filename.c_str());
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class CAboutDlg : public CDialogEx class CAboutDlg : public CDialogEx
@@ -417,6 +375,7 @@ std::string CMy2015RemoteDlg::GetHardwareID(int v)
CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogEx(CMy2015RemoteDlg::IDD, pParent) CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogEx(CMy2015RemoteDlg::IDD, pParent)
{ {
m_ClientMap = NewClientList();
g_StartTick = GetTickCount(); g_StartTick = GetTickCount();
auto s = GetMasterHash(); auto s = GetMasterHash();
char buf[17] = { 0 }; char buf[17] = { 0 };
@@ -469,6 +428,7 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogEx(CMy2015RemoteDlg::I
CMy2015RemoteDlg::~CMy2015RemoteDlg() CMy2015RemoteDlg::~CMy2015RemoteDlg()
{ {
SAFE_DELETE(m_ClientMap);
DeleteCriticalSection(&m_cs); DeleteCriticalSection(&m_cs);
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) { for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
SAFE_DELETE(m_ServerDLL[i]); SAFE_DELETE(m_ServerDLL[i]);
@@ -612,7 +572,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_PROXY_PORT, &CMy2015RemoteDlg::OnProxyPort) ON_COMMAND(ID_PROXY_PORT, &CMy2015RemoteDlg::OnProxyPort)
ON_COMMAND(ID_HOOK_WIN, &CMy2015RemoteDlg::OnHookWin) ON_COMMAND(ID_HOOK_WIN, &CMy2015RemoteDlg::OnHookWin)
ON_COMMAND(ID_RUNAS_SERVICE, &CMy2015RemoteDlg::OnRunasService) ON_COMMAND(ID_RUNAS_SERVICE, &CMy2015RemoteDlg::OnRunasService)
END_MESSAGE_MAP() ON_COMMAND(ID_HISTORY_CLIENTS, &CMy2015RemoteDlg::OnHistoryClients)
END_MESSAGE_MAP()
// CMy2015RemoteDlg 消息处理程序 // CMy2015RemoteDlg 消息处理程序
@@ -651,7 +612,7 @@ VOID CMy2015RemoteDlg::CreateSolidMenu()
if (GetPwdHash() != masterHash) { if (GetPwdHash() != masterHash) {
SubMenu->DeleteMenu(ID_TOOL_GEN_MASTER, MF_BYCOMMAND); SubMenu->DeleteMenu(ID_TOOL_GEN_MASTER, MF_BYCOMMAND);
} }
SubMenu = m_MainMenu.GetSubMenu(3); SubMenu = m_MainMenu.GetSubMenu(4);
if (!THIS_CFG.GetStr("settings", "Password").empty()) { if (!THIS_CFG.GetStr("settings", "Password").empty()) {
SubMenu->ModifyMenuA(ID_TOOL_REQUEST_AUTH, MF_STRING, ID_TOOL_REQUEST_AUTH, _T("序列号")); SubMenu->ModifyMenuA(ID_TOOL_REQUEST_AUTH, MF_STRING, ID_TOOL_REQUEST_AUTH, _T("序列号"));
} }
@@ -802,17 +763,13 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
id, v[RES_CLIENT_ID].c_str(), strIP.GetString(), path.GetString()); id, v[RES_CLIENT_ID].c_str(), strIP.GetString(), path.GetString());
} }
bool modify = false; bool modify = false;
CString loc = GetClientMapData(id, MAP_LOCATION); CString loc = m_ClientMap->GetClientMapData(id, MAP_LOCATION);
if (loc.IsEmpty()) { if (loc.IsEmpty()) {
loc = v[RES_CLIENT_LOC].c_str(); loc = v[RES_CLIENT_LOC].c_str();
if (loc.IsEmpty()) { if (loc.IsEmpty()) {
IPConverter cvt; IPConverter cvt;
loc = cvt.GetGeoLocation(data[ONLINELIST_IP].GetString()).c_str(); loc = cvt.GetGeoLocation(data[ONLINELIST_IP].GetString()).c_str();
} }
if (!loc.IsEmpty()) {
modify = true;
SetClientMapData(id, MAP_LOCATION, loc);
}
} }
bool flag = strIP == "127.0.0.1" && !v[RES_CLIENT_PUBIP].empty(); bool flag = strIP == "127.0.0.1" && !v[RES_CLIENT_PUBIP].empty();
data[ONLINELIST_IP] = flag ? v[RES_CLIENT_PUBIP].c_str() : strIP; data[ONLINELIST_IP] = flag ? v[RES_CLIENT_PUBIP].c_str() : strIP;
@@ -820,6 +777,7 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
ContextObject->SetClientInfo(data, v); ContextObject->SetClientInfo(data, v);
ContextObject->SetID(id); ContextObject->SetID(id);
ContextObject->SetGroup(groupName); ContextObject->SetGroup(groupName);
m_ClientMap->SaveClientMapData(ContextObject);
EnterCriticalSection(&m_cs); EnterCriticalSection(&m_cs);
@@ -843,14 +801,14 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
} }
if (modify) if (modify)
SaveToFile(m_ClientMap, GetDbPath()); m_ClientMap->SaveToFile(GetDbPath());
auto& m = m_ClientMap[ContextObject->ID];
m_HostList.insert(ContextObject); m_HostList.insert(ContextObject);
if (groupName == m_selectedGroup || (groupName.empty() && m_selectedGroup == "default")) { if (groupName == m_selectedGroup || (groupName.empty() && m_selectedGroup == "default")) {
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), data[ONLINELIST_IP]); int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), data[ONLINELIST_IP]);
for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) { for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) {
auto note = m_ClientMap->GetClientMapData(ContextObject->GetClientID(), MAP_NOTE);
n == ONLINELIST_COMPUTER_NAME ? n == ONLINELIST_COMPUTER_NAME ?
m_CList_Online.SetItemText(i, n, m.GetNote()[0] ? m.GetNote() : data[n]) : m_CList_Online.SetItemText(i, n, !note.IsEmpty() ? note : data[n]) :
m_CList_Online.SetItemText(i, n, data[n].IsEmpty() ? "?" : data[n]); m_CList_Online.SetItemText(i, n, data[n].IsEmpty() ? "?" : data[n]);
} }
m_CList_Online.SetItemData(i, (DWORD_PTR)ContextObject); m_CList_Online.SetItemData(i, (DWORD_PTR)ContextObject);
@@ -1195,7 +1153,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
UPDATE_SPLASH(35, "正在加载客户端数据库..."); UPDATE_SPLASH(35, "正在加载客户端数据库...");
// 将"关于..."菜单项添加到系统菜单中。 // 将"关于..."菜单项添加到系统菜单中。
SetWindowText(_T("Yama")); SetWindowText(_T("Yama"));
LoadFromFile(m_ClientMap, GetDbPath()); m_ClientMap->LoadFromFile(GetDbPath());
// IDM_ABOUTBOX 必须在系统命令范围内。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
@@ -1662,6 +1620,15 @@ void CMy2015RemoteDlg::Release()
ContextObject->Destroy(); ContextObject->Destroy();
} }
LeaveCriticalSection(&m_cs); LeaveCriticalSection(&m_cs);
m_ClientMap->SaveToFile(GetDbPath());
if (m_pClientListDlg != nullptr && ::IsWindow(m_pClientListDlg->GetSafeHwnd())) {
// 关键:调用 DestroyWindow它会触发窗口的关闭和销毁流程
m_pClientListDlg->DestroyWindow();
// 注意:如果你在对话框的 PostNcDestroy 里写了 delete this;
// 那么此时不要再 delete m_pClientListDlg只需将指针置 NULL 即可
m_pClientListDlg = nullptr;
}
Sleep(500); Sleep(500);
while (m_hFRPThread) while (m_hFRPThread)
Sleep(20); Sleep(20);
@@ -2837,6 +2804,7 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx)
BOOL authorized = AuthorizeClient(hb.SN, hb.Passcode, hb.PwdHmac); BOOL authorized = AuthorizeClient(hb.SN, hb.Passcode, hb.PwdHmac);
if (authorized) { if (authorized) {
Mprintf("%s HMAC 校验成功: %lld\n", hb.Passcode, hb.PwdHmac); Mprintf("%s HMAC 校验成功: %lld\n", hb.Passcode, hb.PwdHmac);
m_ClientMap->SetClientMapInteger(host->GetClientID(), MAP_AUTH, TRUE);
std::string tip = std::string(hb.Passcode) + " 授权成功: "; std::string tip = std::string(hb.Passcode) + " 授权成功: ";
tip += std::to_string(hb.PwdHmac) + "[" + std::string(ctx->GetClientData(ONLINELIST_IP)) + "]"; tip += std::to_string(hb.PwdHmac) + "[" + std::string(ctx->GetClientData(ONLINELIST_IP)) + "]";
CharMsg* msg = new CharMsg(tip.c_str()); CharMsg* msg = new CharMsg(tip.c_str());
@@ -3177,19 +3145,13 @@ void CMy2015RemoteDlg::OnOnlineHostnote()
while (Pos) { while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos); int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem); context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
auto f = m_ClientMap.find(ContextObject->GetClientID()); m_ClientMap->SetClientMapData(ContextObject->GetClientID(), MAP_NOTE, dlg.m_str);
if (f == m_ClientMap.end())
m_ClientMap[ContextObject->GetClientID()] = ClientValue("", dlg.m_str);
else
m_ClientMap[ContextObject->GetClientID()].UpdateNote(dlg.m_str);
m_CList_Online.SetItemText(iItem, ONLINELIST_COMPUTER_NAME, dlg.m_str); m_CList_Online.SetItemText(iItem, ONLINELIST_COMPUTER_NAME, dlg.m_str);
modified = TRUE; modified = TRUE;
} }
LeaveCriticalSection(&m_cs); LeaveCriticalSection(&m_cs);
if (modified) { if (modified) {
EnterCriticalSection(&m_cs); m_ClientMap->SaveToFile(GetDbPath());
SaveToFile(m_ClientMap, GetDbPath());
LeaveCriticalSection(&m_cs);
} }
} }
@@ -3992,11 +3954,10 @@ void CMy2015RemoteDlg::OnOnlineAddWatch()
while (Pos) { while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos); int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ctx = (context*)m_CList_Online.GetItemData(iItem); context* ctx = (context*)m_CList_Online.GetItemData(iItem);
auto f = m_ClientMap.find(ctx->GetClientID()); int r = m_ClientMap->GetClientMapInteger(ctx->GetClientID(), MAP_LEVEL);
int r = f != m_ClientMap.end() ? f->second.GetLevel() : 0; m_ClientMap->SetClientMapInteger(ctx->GetClientID(), MAP_LEVEL, ++r >= 4 ? 0 : r);
m_ClientMap[ctx->GetClientID()].UpdateLevel(++r >= 4 ? 0 : r);
} }
SaveToFile(m_ClientMap, GetDbPath()); m_ClientMap->SaveToFile(GetDbPath());
LeaveCriticalSection(&m_cs); LeaveCriticalSection(&m_cs);
} }
@@ -4015,9 +3976,8 @@ void CMy2015RemoteDlg::OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult)
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec); int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
EnterCriticalSection(&m_cs); EnterCriticalSection(&m_cs);
context* ctx = (context*)m_CList_Online.GetItemData(nRow); context* ctx = (context*)m_CList_Online.GetItemData(nRow);
auto f = m_ClientMap.find(ctx->GetClientID());
int r = f != m_ClientMap.end() ? f->second.GetLevel() : 0;
LeaveCriticalSection(&m_cs); LeaveCriticalSection(&m_cs);
int r = m_ClientMap->GetClientMapInteger(ctx->GetClientID(), MAP_LEVEL);
if (r >= 1) pLVCD->clrText = RGB(0, 0, 255); // 字体蓝 if (r >= 1) pLVCD->clrText = RGB(0, 0, 255); // 字体蓝
if (r >= 2) pLVCD->clrText = RGB(255, 0, 0); // 字体红 if (r >= 2) pLVCD->clrText = RGB(255, 0, 0); // 字体红
if (r >= 3) pLVCD->clrTextBk = RGB(255, 160, 160); // 背景红 if (r >= 3) pLVCD->clrTextBk = RGB(255, 160, 160); // 背景红
@@ -4113,14 +4073,14 @@ void CMy2015RemoteDlg::LoadListData(const std::string& group)
auto g = ctx->GetGroupName(); auto g = ctx->GetGroupName();
if ((group == _T("default") && g.empty()) || g == group) { if ((group == _T("default") && g.empty()) || g == group) {
CString strIP=ctx->GetClientData(ONLINELIST_IP); CString strIP=ctx->GetClientData(ONLINELIST_IP);
auto& m = m_ClientMap[ctx->GetClientID()];
auto pubIP = ctx->GetAdditionalData(RES_CLIENT_PUBIP); auto pubIP = ctx->GetAdditionalData(RES_CLIENT_PUBIP);
bool flag = strIP == "127.0.0.1" && !pubIP.IsEmpty(); bool flag = strIP == "127.0.0.1" && !pubIP.IsEmpty();
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), flag ? pubIP : strIP); int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), flag ? pubIP : strIP);
for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) { for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) {
auto data = ctx->GetClientData(n); auto data = ctx->GetClientData(n);
auto note = m_ClientMap->GetClientMapData(ctx->GetClientID(), MAP_NOTE);
n == ONLINELIST_COMPUTER_NAME ? n == ONLINELIST_COMPUTER_NAME ?
m_CList_Online.SetItemText(i, n, m.GetNote()[0] ? m.GetNote() : data) : m_CList_Online.SetItemText(i, n, !note.IsEmpty() ? note : data) :
m_CList_Online.SetItemText(i, n, data.IsEmpty() ? "?" : data); m_CList_Online.SetItemText(i, n, data.IsEmpty() ? "?" : data);
} }
m_CList_Online.SetItemData(i, (DWORD_PTR)ctx); m_CList_Online.SetItemData(i, (DWORD_PTR)ctx);
@@ -4805,3 +4765,22 @@ void CMy2015RemoteDlg::OnRunasService()
SubMenu->CheckMenuItem(ID_RUNAS_SERVICE, !m_runNormal ? MF_CHECKED : MF_UNCHECKED); SubMenu->CheckMenuItem(ID_RUNAS_SERVICE, !m_runNormal ? MF_CHECKED : MF_UNCHECKED);
BOOL r = m_runNormal ? ServerService_Uninstall() : ServerService_Install(); BOOL r = m_runNormal ? ServerService_Uninstall() : ServerService_Install();
} }
void CMy2015RemoteDlg::OnHistoryClients()
{
// 1. 如果窗口已经存在,直接带到前台,不要重复创建
if (m_pClientListDlg != nullptr && ::IsWindow(m_pClientListDlg->GetSafeHwnd())) {
m_pClientListDlg->ShowWindow(SW_SHOW);
m_pClientListDlg->SetForegroundWindow();
return;
}
// 2. 创建对话框实例
// 注意:如果是非模态,传进去的 m_ClientMap 引用要确保在对话框存在期间一直有效
m_pClientListDlg = new CClientListDlg(m_ClientMap, this);
// IDD_CLIENT_LIST 是你对话框的 ID
if (m_pClientListDlg->Create(IDD_DIALOG_CLIENTLIST, GetDesktopWindow())) {
m_pClientListDlg->ShowWindow(SW_SHOW);
}
}

View File

@@ -47,75 +47,8 @@ typedef struct FileTransformCmd {
} FileTransformCmd; } FileTransformCmd;
#define ID_DYNAMIC_MENU_BASE 36500 #define ID_DYNAMIC_MENU_BASE 36500
#include "HostInfo.h"
//////////////////////////////////////////////////////////////////////////
#include <unordered_map>
#include <fstream>
#include "CGridDialog.h" #include "CGridDialog.h"
#include <set>
enum {
MAP_NOTE,
MAP_LOCATION,
MAP_LEVEL,
};
struct _ClientValue {
char Note[64];
char Location[64];
char Level;
char Reserved[127]; // 预留
_ClientValue()
{
memset(this, 0, sizeof(_ClientValue));
}
_ClientValue(const CString& loc, const CString& s)
{
memset(this, 0, sizeof(_ClientValue));
strcpy_s(Note, s.GetString());
strcpy_s(Location, loc.GetString());
}
void UpdateNote(const CString& s)
{
strcpy_s(Note, s.GetString());
}
void UpdateLocation(const CString& loc)
{
strcpy_s(Location, loc.GetString());
}
void UpdateLevel(int level)
{
Level = level;
}
const char* GetNote() const
{
return Note;
}
const char* GetLocation() const
{
return Location;
}
int GetLevel() const
{
return Level;
}
int GetLength() const
{
return sizeof(_ClientValue);
}
};
typedef uint64_t ClientKey;
typedef _ClientValue ClientValue;
typedef std::unordered_map<ClientKey, ClientValue> ComputerNoteMap;
// 保存 unordered_map 到文件
void SaveToFile(const ComputerNoteMap& data, const std::string& filename);
// 从文件读取 unordered_map 数据
void LoadFromFile(ComputerNoteMap& data, const std::string& filename);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -126,6 +59,7 @@ enum {
}; };
class CSplashDlg; // 前向声明 class CSplashDlg; // 前向声明
class CClientListDlg;
#include "pwd_gen.h" #include "pwd_gen.h"
@@ -134,43 +68,9 @@ class CMy2015RemoteDlg : public CDialogEx
{ {
public: public:
static std::string GetHardwareID(int v=-1); static std::string GetHardwareID(int v=-1);
protected: _ClientList *m_ClientMap = nullptr;
ComputerNoteMap m_ClientMap; CClientListDlg* m_pClientListDlg = nullptr;
CString GetClientMapData(ClientKey key, int typ)
{
EnterCriticalSection(&m_cs);
auto f = m_ClientMap.find(key);
CString r;
if (f != m_ClientMap.end()) {
switch (typ) {
case MAP_NOTE:
r = f->second.GetNote();
break;
case MAP_LOCATION:
r = f->second.GetLocation();
break;
default:
break;
}
}
LeaveCriticalSection(&m_cs);
return r;
}
void SetClientMapData(ClientKey key, int typ, const char* value)
{
EnterCriticalSection(&m_cs);
switch (typ) {
case MAP_NOTE:
m_ClientMap[key].UpdateNote(value);
break;
case MAP_LOCATION:
m_ClientMap[key].UpdateLocation(value);
break;
default:
break;
}
LeaveCriticalSection(&m_cs);
}
// 构造 // 构造
public: public:
CMy2015RemoteDlg(CWnd* pParent = NULL); // 标准构造函数 CMy2015RemoteDlg(CWnd* pParent = NULL); // 标准构造函数
@@ -412,4 +312,5 @@ public:
afx_msg void OnProxyPort(); afx_msg void OnProxyPort();
afx_msg void OnHookWin(); afx_msg void OnHookWin();
afx_msg void OnRunasService(); afx_msg void OnRunasService();
afx_msg void OnHistoryClients();
}; };

View File

@@ -282,10 +282,12 @@
<ClInclude Include="Bmp2Video.h" /> <ClInclude Include="Bmp2Video.h" />
<ClInclude Include="Buffer.h" /> <ClInclude Include="Buffer.h" />
<ClInclude Include="BuildDlg.h" /> <ClInclude Include="BuildDlg.h" />
<ClInclude Include="CClientListDlg.h" />
<ClInclude Include="CDlgFileSend.h" /> <ClInclude Include="CDlgFileSend.h" />
<ClInclude Include="CDrawingBoard.h" /> <ClInclude Include="CDrawingBoard.h" />
<ClInclude Include="CGridDialog.h" /> <ClInclude Include="CGridDialog.h" />
<ClInclude Include="Chat.h" /> <ClInclude Include="Chat.h" />
<ClInclude Include="context.h" />
<ClInclude Include="CPasswordDlg.h" /> <ClInclude Include="CPasswordDlg.h" />
<ClInclude Include="CRcEditDlg.h" /> <ClInclude Include="CRcEditDlg.h" />
<ClInclude Include="CTextDlg.h" /> <ClInclude Include="CTextDlg.h" />
@@ -299,6 +301,7 @@
<ClInclude Include="file\CFileManagerDlg.h" /> <ClInclude Include="file\CFileManagerDlg.h" />
<ClInclude Include="file\CFileTransferModeDlg.h" /> <ClInclude Include="file\CFileTransferModeDlg.h" />
<ClInclude Include="HideScreenSpyDlg.h" /> <ClInclude Include="HideScreenSpyDlg.h" />
<ClInclude Include="HostInfo.h" />
<ClInclude Include="InputDlg.h" /> <ClInclude Include="InputDlg.h" />
<ClInclude Include="IOCPKCPServer.h" /> <ClInclude Include="IOCPKCPServer.h" />
<ClInclude Include="IOCPServer.h" /> <ClInclude Include="IOCPServer.h" />
@@ -373,6 +376,7 @@
<ClCompile Include="Bmp2Video.cpp" /> <ClCompile Include="Bmp2Video.cpp" />
<ClCompile Include="Buffer.cpp" /> <ClCompile Include="Buffer.cpp" />
<ClCompile Include="BuildDlg.cpp" /> <ClCompile Include="BuildDlg.cpp" />
<ClCompile Include="CClientListDlg.cpp" />
<ClCompile Include="CDlgFileSend.cpp" /> <ClCompile Include="CDlgFileSend.cpp" />
<ClCompile Include="CDrawingBoard.cpp" /> <ClCompile Include="CDrawingBoard.cpp" />
<ClCompile Include="CGridDialog.cpp" /> <ClCompile Include="CGridDialog.cpp" />

View File

@@ -64,6 +64,7 @@
<ClCompile Include="CDlgFileSend.cpp" /> <ClCompile Include="CDlgFileSend.cpp" />
<ClCompile Include="..\..\common\file_upload.cpp" /> <ClCompile Include="..\..\common\file_upload.cpp" />
<ClCompile Include="..\..\client\reg_startup.c" /> <ClCompile Include="..\..\client\reg_startup.c" />
<ClCompile Include="CClientListDlg.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\client\Audio.h" /> <ClInclude Include="..\..\client\Audio.h" />
@@ -140,6 +141,9 @@
<ClInclude Include="ToolbarDlg.h" /> <ClInclude Include="ToolbarDlg.h" />
<ClInclude Include="CDlgFileSend.h" /> <ClInclude Include="CDlgFileSend.h" />
<ClInclude Include="..\..\client\reg_startup.h" /> <ClInclude Include="..\..\client\reg_startup.h" />
<ClInclude Include="HostInfo.h" />
<ClInclude Include="CClientListDlg.h" />
<ClInclude Include="context.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="2015Remote.rc" /> <ResourceCompile Include="2015Remote.rc" />

View File

@@ -496,6 +496,7 @@ void CBuildDlg::OnBnClickedOk()
BOOL checked = m_BtnFileServer.GetCheck() == BST_CHECKED; BOOL checked = m_BtnFileServer.GetCheck() == BST_CHECKED;
if (checked){ if (checked){
strcpy(sc->downloadUrl, m_sDownloadUrl.IsEmpty() ? BuildPayloadUrl(m_strIP, sc->file) : m_sDownloadUrl); strcpy(sc->downloadUrl, m_sDownloadUrl.IsEmpty() ? BuildPayloadUrl(m_strIP, sc->file) : m_sDownloadUrl);
if (m_sDownloadUrl.IsEmpty()) MessageBox(CString("文件下载地址: \r\n") + sc->downloadUrl, "提示");
} }
tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" : tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" :
checked ? "\r\n提示: 载荷文件必须拷贝至\"Payloads\"目录。" : "\r\n提示: 载荷文件必须拷贝至程序目录。"; checked ? "\r\n提示: 载荷文件必须拷贝至\"Payloads\"目录。" : "\r\n提示: 载荷文件必须拷贝至程序目录。";

View File

@@ -0,0 +1,248 @@
// CClientListDlg.cpp: 实现文件
//
#include "stdafx.h"
#include "afxdialogex.h"
#include "CClientListDlg.h"
// CClientListDlg 对话框
IMPLEMENT_DYNAMIC(CClientListDlg, CDialogEx)
CClientListDlg::CClientListDlg(_ClientList* clients, CMy2015RemoteDlg* pParent)
: g_ClientList(clients), g_pParent(pParent), CDialogEx(IDD_DIALOG_CLIENTLIST, pParent)
, m_nSortColumn(-1)
, m_bSortAscending(TRUE)
{
}
CClientListDlg::~CClientListDlg()
{
}
void CClientListDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CLIENT_LIST, m_ClientList);
}
BEGIN_MESSAGE_MAP(CClientListDlg, CDialogEx)
ON_WM_SIZE()
ON_NOTIFY(LVN_COLUMNCLICK, IDC_CLIENT_LIST, &CClientListDlg::OnColumnClick)
END_MESSAGE_MAP()
// CClientListDlg 消息处理程序
BOOL CClientListDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
HICON hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_MACHINE));
SetIcon(hIcon, FALSE);
// 设置扩展样式
m_ClientList.SetExtendedStyle(
LVS_EX_FULLROWSELECT | // 整行选中
LVS_EX_GRIDLINES // 显示网格线
);
// 添加列
m_ClientList.InsertColumn(0, _T("序号"), LVCFMT_LEFT, 50);
m_ClientList.InsertColumn(1, _T("ID"), LVCFMT_LEFT, 120);
m_ClientList.InsertColumn(2, _T("备注"), LVCFMT_LEFT, 80);
m_ClientList.InsertColumn(3, _T("位置"), LVCFMT_LEFT, 100);
m_ClientList.InsertColumn(4, _T("IP"), LVCFMT_LEFT, 120);
m_ClientList.InsertColumn(5, _T("系统"), LVCFMT_LEFT, 120);
m_ClientList.InsertColumn(6, _T("安装时间"), LVCFMT_LEFT, 130);
m_ClientList.InsertColumn(7, _T("最后登录"), LVCFMT_LEFT, 130);
m_ClientList.InsertColumn(8, _T("关注级别"), LVCFMT_LEFT, 70);
m_ClientList.InsertColumn(9, _T("已授权"), LVCFMT_LEFT, 60);
// 首次加载数据
AdjustColumnWidths();
RefreshClientList();
return TRUE;
}
void CClientListDlg::RefreshClientList()
{
m_clients = g_ClientList->GetAll(); // 保存到成员变量
// 如果之前有排序,保持排序
if (m_nSortColumn >= 0) {
SortByColumn(m_nSortColumn, m_bSortAscending);
}
else {
m_ClientList.SetRedraw(FALSE);
DisplayClients();
m_ClientList.SetRedraw(TRUE);
m_ClientList.Invalidate();
}
}
void CClientListDlg::DisplayClients()
{
m_ClientList.DeleteAllItems();
int i = 0;
for (const auto& pair : m_clients) {
const ClientKey& key = pair.first;
const ClientValue& val = pair.second;
CString strNo;
strNo.Format(_T("%d"), i + 1); // 序号从1开始
CString strID;
strID.Format(_T("%llu"), key);
CString strLevel;
strLevel.Format(_T("%d"), val.Level);
CString strAuth = val.Authorized ? _T("Y") : _T("N");
int nItem = m_ClientList.InsertItem(i, strNo); // 第一列是序号
m_ClientList.SetItemText(nItem, 1, strID);
m_ClientList.SetItemText(nItem, 2, val.Note);
m_ClientList.SetItemText(nItem, 3, val.Location);
m_ClientList.SetItemText(nItem, 4, val.IP);
m_ClientList.SetItemText(nItem, 5, val.OsName);
m_ClientList.SetItemText(nItem, 6, val.InstallTime);
m_ClientList.SetItemText(nItem, 7, val.LastLoginTime);
m_ClientList.SetItemText(nItem, 8, strLevel);
m_ClientList.SetItemText(nItem, 9, strAuth);
m_ClientList.SetItemData(nItem, (DWORD_PTR)key);
i++;
}
}
void CClientListDlg::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
int nColumn = pNMLV->iSubItem;
// 序号列不排序
if (nColumn == 0) {
*pResult = 0;
return;
}
// 点击同一列切换排序方向
if (nColumn == m_nSortColumn) {
m_bSortAscending = !m_bSortAscending;
}
else {
m_nSortColumn = nColumn;
m_bSortAscending = TRUE;
}
SortByColumn(nColumn, m_bSortAscending);
*pResult = 0;
}
void CClientListDlg::SortByColumn(int nColumn, BOOL bAscending)
{
std::sort(m_clients.begin(), m_clients.end(),
[nColumn, bAscending](const std::pair<ClientKey, ClientValue>& a,
const std::pair<ClientKey, ClientValue>& b) {
int result = 0;
switch (nColumn) {
case 1: // ID
result = (a.first < b.first) ? -1 : ((a.first > b.first) ? 1 : 0);
break;
case 2: // 备注
result = strcmp(a.second.Note, b.second.Note);
break;
case 3: // 位置
result = strcmp(a.second.Location, b.second.Location);
break;
case 4: // IP
result = strcmp(a.second.IP, b.second.IP);
break;
case 5: // 系统
result = strcmp(a.second.OsName, b.second.OsName);
break;
case 6: // 安装时间
result = strcmp(a.second.InstallTime, b.second.InstallTime);
break;
case 7: // 最后登录
result = strcmp(a.second.LastLoginTime, b.second.LastLoginTime);
break;
case 8: // 关注级别
result = a.second.Level - b.second.Level;
break;
case 9: // 已授权
result = a.second.Authorized - b.second.Authorized;
break;
default:
return false;
}
return bAscending ? (result < 0) : (result > 0);
});
m_ClientList.SetRedraw(FALSE);
DisplayClients();
m_ClientList.SetRedraw(TRUE);
m_ClientList.Invalidate();
}
void CClientListDlg::AdjustColumnWidths()
{
CRect rect;
m_ClientList.GetClientRect(&rect);
int totalWidth = rect.Width() - 20;
m_ClientList.SetColumnWidth(0, totalWidth * 5 / 100); // 序号
m_ClientList.SetColumnWidth(1, totalWidth * 12 / 100); // ID
m_ClientList.SetColumnWidth(2, totalWidth * 10 / 100); // 备注
m_ClientList.SetColumnWidth(3, totalWidth * 11 / 100); // 位置
m_ClientList.SetColumnWidth(4, totalWidth * 11 / 100); // IP
m_ClientList.SetColumnWidth(5, totalWidth * 11 / 100); // 系统
m_ClientList.SetColumnWidth(6, totalWidth * 13 / 100); // 安装时间
m_ClientList.SetColumnWidth(7, totalWidth * 13 / 100); // 最后登录
m_ClientList.SetColumnWidth(8, totalWidth * 7 / 100); // 关注级别
m_ClientList.SetColumnWidth(9, totalWidth * 7 / 100); // 已授权
}
void CClientListDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
if (m_ClientList.GetSafeHwnd() == NULL) {
return; // 控件还没创建
}
// 留点边距
int margin = 10;
// 列表控件填满整个对话框(留边距)
m_ClientList.MoveWindow(margin, margin, cx - margin * 2, cy - margin * 2);
AdjustColumnWidths();
}
void CClientListDlg::OnCancel()
{
DestroyWindow();
}
void CClientListDlg::PostNcDestroy()
{
if (g_pParent) {
g_pParent->m_pClientListDlg = nullptr;
}
CDialogEx::PostNcDestroy();
delete this;
}
void CClientListDlg::OnOK()
{
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "afxdialogex.h"
#include "HostInfo.h"
#include "Resource.h"
#include <vector>
#include <algorithm>
#include "2015RemoteDlg.h"
// CClientListDlg 对话框
class CClientListDlg : public CDialogEx
{
DECLARE_DYNAMIC(CClientListDlg)
public:
CClientListDlg(_ClientList* clients, CMy2015RemoteDlg* pParent = nullptr);
virtual ~CClientListDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_CLIENTLIST };
#endif
protected:
_ClientList* g_ClientList;
CMy2015RemoteDlg* g_pParent;
std::vector<std::pair<ClientKey, ClientValue>> m_clients; // 数据副本
int m_nSortColumn; // 当前排序列
BOOL m_bSortAscending; // 是否升序
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
CListCtrl m_ClientList;
virtual BOOL OnInitDialog();
void RefreshClientList();
void DisplayClients();
void AdjustColumnWidths();
void SortByColumn(int nColumn, BOOL bAscending);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult);
virtual void OnCancel();
virtual void PostNcDestroy();
virtual void OnOK();
};

View File

@@ -0,0 +1,58 @@
#pragma once
//////////////////////////////////////////////////////////////////////////
#include <unordered_map>
#include <fstream>
#include <set>
#include "context.h"
enum {
MAP_NOTE,
MAP_LOCATION,
MAP_LEVEL,
MAP_AUTH,
};
#pragma pack(push, 1)
class _ClientValue {
public:
char Note[64];
char Location[64];
char Level;
char IP[46];
char InstallTime[20];
char LastLoginTime[20];
char OsName[32];
char Authorized;
uint64_t ID;
char Reserved[768];
_ClientValue()
{
memset(this, 0, sizeof(_ClientValue));
}
};
#pragma pack(pop)
typedef uint64_t ClientKey;
typedef _ClientValue ClientValue;
typedef std::unordered_map<ClientKey, ClientValue> ClientMap;
class _ClientList {
public:
virtual ~_ClientList() {}
virtual bool Exists(ClientKey key) = 0;
virtual CString GetClientMapData(ClientKey key, int typ) = 0;
virtual int GetClientMapInteger(ClientKey key, int typ) = 0;
virtual void SetClientMapInteger(ClientKey key, int typ, int value) = 0;
virtual void SetClientMapData(ClientKey key, int typ, const char* value) = 0;
virtual void SaveClientMapData(context* ctx) = 0;
virtual std::vector<std::pair<ClientKey, ClientValue>> GetAll() = 0;
virtual void SaveToFile(const std::string& filename) = 0;
virtual void LoadFromFile(const std::string& filename) = 0;
};
_ClientList* NewClientList();

View File

@@ -17,7 +17,7 @@ public:
{ {
return "KCP"; return "KCP";
} }
VOID InitMember(SOCKET s, Server* svr) override VOID InitMember(SOCKET s, VOID* svr) override
{ {
CONTEXT_OBJECT::InitMember(s, svr); CONTEXT_OBJECT::InitMember(s, svr);
clientAddr = {}; clientAddr = {};

View File

@@ -32,24 +32,6 @@ std::string GetRemoteIP(SOCKET sock);
#define Muncompress(dest, destLen, source, sourceLen) m_Dctx ? ZSTD_decompressDCtx(m_Dctx, dest, *(destLen), source, sourceLen):\ #define Muncompress(dest, destLen, source, sourceLen) m_Dctx ? ZSTD_decompressDCtx(m_Dctx, dest, *(destLen), source, sourceLen):\
ZSTD_decompress(dest, *(destLen), source, sourceLen) ZSTD_decompress(dest, *(destLen), source, sourceLen)
enum {
ONLINELIST_IP = 0, // IP的列顺序
ONLINELIST_ADDR, // 地址
ONLINELIST_LOCATION, // 地理位置
ONLINELIST_COMPUTER_NAME, // 计算机名/备注
ONLINELIST_OS, // 操作系统
ONLINELIST_CPU, // CPU
ONLINELIST_VIDEO, // 摄像头(有无)
ONLINELIST_PING, // PING(对方的网速)
ONLINELIST_VERSION, // 版本信息
ONLINELIST_INSTALLTIME, // 安装时间
ONLINELIST_LOGINTIME, // 活动窗口
ONLINELIST_CLIENTTYPE, // 客户端类型
ONLINELIST_PATH, // 文件路径
ONLINELIST_PUBIP,
ONLINELIST_MAX,
};
enum { enum {
PARSER_WINOS = -2, PARSER_WINOS = -2,
PARSER_FAILED = -1, // 解析失败 PARSER_FAILED = -1, // 解析失败
@@ -311,6 +293,7 @@ public:
} }
}; };
class CONTEXT_OBJECT;
typedef BOOL (CALLBACK* pfnNotifyProc)(CONTEXT_OBJECT* ContextObject); typedef BOOL (CALLBACK* pfnNotifyProc)(CONTEXT_OBJECT* ContextObject);
typedef BOOL (CALLBACK* pfnOfflineProc)(CONTEXT_OBJECT* ContextObject); typedef BOOL (CALLBACK* pfnOfflineProc)(CONTEXT_OBJECT* ContextObject);
@@ -335,39 +318,10 @@ public:
virtual void Disconnect(CONTEXT_OBJECT* ctx) {} virtual void Disconnect(CONTEXT_OBJECT* ctx) {}
}; };
class context
{
public:
// 纯虚函数
virtual VOID InitMember(SOCKET s, Server* svr)=0;
virtual BOOL Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) = 0;
virtual CString GetClientData(int index)const = 0;
virtual void GetAdditionalData(CString(&s)[RES_MAX]) const =0;
virtual CString GetAdditionalData(int index) const = 0;
virtual uint64_t GetClientID() const = 0;
virtual std::string GetPeerName() const = 0;
virtual int GetPort() const = 0;
virtual std::string GetProtocol() const = 0;
virtual int GetServerPort() const = 0;
virtual FlagType GetFlagType() const = 0;
virtual std::string GetGroupName() const = 0;
virtual uint64_t GetAliveTime()const = 0;
public:
virtual ~context() {}
virtual void Destroy() {}
virtual BOOL IsLogin() const
{
return TRUE;
}
virtual bool IsEqual(context *ctx) const
{
return this == ctx || this->GetPort() == ctx->GetPort();
}
};
// 预分配解压缩缓冲区大小 // 预分配解压缩缓冲区大小
#define PREALLOC_DECOMPRESS_SIZE (4 * 1024) #define PREALLOC_DECOMPRESS_SIZE (4 * 1024)
#include "context.h"
typedef class CONTEXT_OBJECT : public context typedef class CONTEXT_OBJECT : public context
{ {
public: public:
@@ -508,7 +462,7 @@ public:
{ {
return server->GetPort(); return server->GetPort();
} }
VOID InitMember(SOCKET s, Server *svr) VOID InitMember(SOCKET s, VOID*svr)
{ {
memset(szBuffer, 0, sizeof(char) * PACKET_LENGTH); memset(szBuffer, 0, sizeof(char) * PACKET_LENGTH);
hDlg = NULL; hDlg = NULL;
@@ -527,7 +481,7 @@ public:
Parser.Reset(); Parser.Reset();
bLogin = FALSE; bLogin = FALSE;
m_bProxyConnected = FALSE; m_bProxyConnected = FALSE;
server = svr; server = (Server*)svr;
OnlineTime = time(0); OnlineTime = time(0);
} }
uint64_t GetAliveTime()const uint64_t GetAliveTime()const
@@ -761,7 +715,7 @@ public:
{ {
return "UDP"; return "UDP";
} }
VOID InitMember(SOCKET s, Server* svr) override VOID InitMember(SOCKET s, VOID* svr) override
{ {
CONTEXT_OBJECT::InitMember(s, svr); CONTEXT_OBJECT::InitMember(s, svr);
clientAddr = {}; clientAddr = {};

View File

@@ -0,0 +1,53 @@
#pragma once
#include "common/header.h"
#include "common/commands.h"
#include <atlstr.h>
enum {
ONLINELIST_IP = 0, // IP<49><50><EFBFBD><EFBFBD>˳<EFBFBD><CBB3>
ONLINELIST_ADDR, // <20><>ַ
ONLINELIST_LOCATION, // <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
ONLINELIST_COMPUTER_NAME, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><>ע
ONLINELIST_OS, // <20><><EFBFBD><EFBFBD>ϵͳ
ONLINELIST_CPU, // CPU
ONLINELIST_VIDEO, // <20><><EFBFBD><EFBFBD>ͷ(<28><><EFBFBD><EFBFBD>)
ONLINELIST_PING, // PING(<28>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
ONLINELIST_VERSION, // <20><EFBFBD><E6B1BE>Ϣ
ONLINELIST_INSTALLTIME, // <20><>װʱ<D7B0><CAB1>
ONLINELIST_LOGINTIME, // <20><EFBFBD><EEB6AF><EFBFBD><EFBFBD>
ONLINELIST_CLIENTTYPE, // <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ONLINELIST_PATH, // <20>ļ<EFBFBD>·<EFBFBD><C2B7>
ONLINELIST_PUBIP,
ONLINELIST_MAX,
};
class context
{
public:
// <20><><EFBFBD><EFBFBD><E9BAAF>
virtual VOID InitMember(SOCKET s, VOID* svr) = 0;
virtual BOOL Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) = 0;
virtual CString GetClientData(int index)const = 0;
virtual void GetAdditionalData(CString(&s)[RES_MAX]) const = 0;
virtual CString GetAdditionalData(int index) const = 0;
virtual uint64_t GetClientID() const = 0;
virtual std::string GetPeerName() const = 0;
virtual int GetPort() const = 0;
virtual std::string GetProtocol() const = 0;
virtual int GetServerPort() const = 0;
virtual FlagType GetFlagType() const = 0;
virtual std::string GetGroupName() const = 0;
virtual uint64_t GetAliveTime()const = 0;
public:
virtual ~context() {}
virtual void Destroy() {}
virtual BOOL IsLogin() const
{
return TRUE;
}
virtual bool IsEqual(context* ctx) const
{
return this == ctx || this->GetPort() == ctx->GetPort();
}
};

View File

@@ -197,6 +197,7 @@
#define IDD_DIALOG_FILESEND 320 #define IDD_DIALOG_FILESEND 320
#define IDR_SCLOADER_X86_OLD 322 #define IDR_SCLOADER_X86_OLD 322
#define IDR_SCLOADER_X64_OLD 323 #define IDR_SCLOADER_X64_OLD 323
#define IDD_DIALOG_CLIENTLIST 324
#define IDC_MESSAGE 1000 #define IDC_MESSAGE 1000
#define IDC_ONLINE 1001 #define IDC_ONLINE 1001
#define IDC_STATIC_TIPS 1002 #define IDC_STATIC_TIPS 1002
@@ -445,6 +446,7 @@
#define IDC_STATIC_DOWNLOAD 2223 #define IDC_STATIC_DOWNLOAD 2223
#define IDC_EDIT_DOWNLOAD_URL 2224 #define IDC_EDIT_DOWNLOAD_URL 2224
#define IDC_EDIT_FILESERVER_PORT 2225 #define IDC_EDIT_FILESERVER_PORT 2225
#define IDC_CLIENT_LIST 2227
#define ID_ONLINE_UPDATE 32772 #define ID_ONLINE_UPDATE 32772
#define ID_ONLINE_MESSAGE 32773 #define ID_ONLINE_MESSAGE 32773
#define ID_ONLINE_DELETE 32775 #define ID_ONLINE_DELETE 32775
@@ -625,15 +627,17 @@
#define ID_RANDOM_NAME 32994 #define ID_RANDOM_NAME 32994
#define ID_32995 32995 #define ID_32995 32995
#define ID_DOWNLOAD_SERVERPORT 32996 #define ID_DOWNLOAD_SERVERPORT 32996
#define ID_32997 32997
#define ID_HISTORY_CLIENTS 32998
#define ID_EXIT_FULLSCREEN 40001 #define ID_EXIT_FULLSCREEN 40001
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 324 #define _APS_NEXT_RESOURCE_VALUE 326
#define _APS_NEXT_COMMAND_VALUE 32997 #define _APS_NEXT_COMMAND_VALUE 32999
#define _APS_NEXT_CONTROL_VALUE 2226 #define _APS_NEXT_CONTROL_VALUE 2228
#define _APS_NEXT_SYMED_VALUE 105 #define _APS_NEXT_SYMED_VALUE 105
#endif #endif
#endif #endif