mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-21 23:13:08 +08:00
Feature: Support customizing client name and install directory
This commit is contained in:
@@ -106,7 +106,8 @@ std::string GetPwdHash();
|
||||
#include <shlobj.h>
|
||||
#include "ZstdArchive.h"
|
||||
|
||||
bool RegisterZstaMenu(const std::string& exePath) {
|
||||
bool RegisterZstaMenu(const std::string& exePath)
|
||||
{
|
||||
HKEY hKey;
|
||||
const char* compressText = "压缩为 ZSTA 文件";
|
||||
const char* extractText = "解压 ZSTA 文件";
|
||||
@@ -159,7 +160,8 @@ bool RegisterZstaMenu(const std::string& exePath) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterZstaMenu() {
|
||||
bool UnregisterZstaMenu()
|
||||
{
|
||||
RegDeleteTreeA(HKEY_CLASSES_ROOT, "*\\shell\\CompressToZsta");
|
||||
RegDeleteTreeA(HKEY_CLASSES_ROOT, "Directory\\shell\\CompressToZsta");
|
||||
RegDeleteTreeA(HKEY_CLASSES_ROOT, ".zsta");
|
||||
@@ -168,7 +170,8 @@ bool UnregisterZstaMenu() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string RemoveTrailingSlash(const std::string& path) {
|
||||
std::string RemoveTrailingSlash(const std::string& path)
|
||||
{
|
||||
std::string p = path;
|
||||
while (!p.empty() && (p.back() == '/' || p.back() == '\\')) {
|
||||
p.pop_back();
|
||||
@@ -176,7 +179,8 @@ std::string RemoveTrailingSlash(const std::string& path) {
|
||||
return p;
|
||||
}
|
||||
|
||||
std::string RemoveZstaExtension(const std::string& path) {
|
||||
std::string RemoveZstaExtension(const std::string& path)
|
||||
{
|
||||
if (path.size() >= 5) {
|
||||
std::string ext = path.substr(path.size() - 5);
|
||||
for (char& c : ext) c = tolower(c);
|
||||
@@ -323,7 +327,8 @@ BOOL LaunchAsAdmin(const char* szFilePath, const char* verb)
|
||||
return ShellExecuteExA(&shExecInfo);
|
||||
}
|
||||
|
||||
BOOL CMy2015RemoteApp::ProcessZstaCmd() {
|
||||
BOOL CMy2015RemoteApp::ProcessZstaCmd()
|
||||
{
|
||||
// 检查是否已注册右键菜单
|
||||
char exePath[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
||||
@@ -332,7 +337,7 @@ BOOL CMy2015RemoteApp::ProcessZstaCmd() {
|
||||
HKEY hKey;
|
||||
bool needRegister = false;
|
||||
if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "ZstaArchive\\shell\\extract\\command",
|
||||
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
char regPath[MAX_PATH * 2] = { 0 };
|
||||
DWORD size = sizeof(regPath);
|
||||
RegQueryValueExA(hKey, NULL, NULL, NULL, (BYTE*)regPath, &size);
|
||||
@@ -342,8 +347,7 @@ BOOL CMy2015RemoteApp::ProcessZstaCmd() {
|
||||
if (strstr(regPath, exePath) == NULL) {
|
||||
needRegister = true; // 路径不同,需要重新注册
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
needRegister = true; // 未注册
|
||||
}
|
||||
|
||||
@@ -380,7 +384,7 @@ BOOL CMy2015RemoteApp::InitInstance()
|
||||
if (!ProcessZstaCmd()) {
|
||||
Mprintf("[InitInstance] 处理自定义压缩/解压命令后退出。\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#if _DEBUG
|
||||
BOOL runNormal = TRUE;
|
||||
@@ -459,15 +463,14 @@ BOOL CMy2015RemoteApp::InitInstance()
|
||||
// 例如修改为公司或组织名
|
||||
SetRegistryKey(_T("YAMA"));
|
||||
|
||||
// 注册一个事件,用于进程间通信
|
||||
// 请勿修改此事件名称,否则可能导致无法启动程序、鉴权失败等问题
|
||||
// 注册一个事件,用于进程间通信
|
||||
// 请勿修改此事件名称,否则可能导致无法启动程序、鉴权失败等问题
|
||||
char eventName[64] = { 0 };
|
||||
sprintf(eventName, "YAMA_%d", GetCurrentProcessId());
|
||||
HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, eventName);
|
||||
if (hEvent == NULL) {
|
||||
Mprintf("[InitInstance] 创建事件失败,错误码: %d\n", GetLastError());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("[InitInstance] 创建事件成功,事件名: %s\n", eventName);
|
||||
}
|
||||
|
||||
@@ -490,7 +493,7 @@ BOOL CMy2015RemoteApp::InitInstance()
|
||||
if (hEvent) {
|
||||
SAFE_CLOSE_HANDLE(hEvent);
|
||||
Mprintf("[InitInstance] 关闭事件句柄。\n");
|
||||
}
|
||||
}
|
||||
|
||||
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
|
||||
// 而不是启动应用程序的消息泵。
|
||||
|
||||
Binary file not shown.
@@ -330,22 +330,22 @@ DllInfo* ReadTinyRunDll(int pid)
|
||||
|
||||
DllInfo* ReadFrpcDll()
|
||||
{
|
||||
std::string name = FRPC_DLL_NAME;
|
||||
DWORD fileSize = 0;
|
||||
BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize);
|
||||
// 设置输出参数
|
||||
auto md5 = CalcMD5FromBytes(dllData, fileSize);
|
||||
DllExecuteInfoNew info = { MEMORYDLL, fileSize, CALLTYPE_FRPC_CALL };
|
||||
memcpy(info.Name, name.c_str(), name.length());
|
||||
memcpy(info.Md5, md5.c_str(), md5.length());
|
||||
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfoNew) + fileSize];
|
||||
buffer[0] = CMD_EXECUTE_DLL_NEW;
|
||||
memcpy(buffer + 1, &info, sizeof(DllExecuteInfoNew));
|
||||
memcpy(buffer + 1 + sizeof(DllExecuteInfoNew), dllData, fileSize);
|
||||
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfoNew) + fileSize, 0, md5);
|
||||
SAFE_DELETE_ARRAY(dllData);
|
||||
SAFE_DELETE_ARRAY(buffer);
|
||||
return new DllInfo{ name, buf };
|
||||
std::string name = FRPC_DLL_NAME;
|
||||
DWORD fileSize = 0;
|
||||
BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize);
|
||||
// 设置输出参数
|
||||
auto md5 = CalcMD5FromBytes(dllData, fileSize);
|
||||
DllExecuteInfoNew info = { MEMORYDLL, fileSize, CALLTYPE_FRPC_CALL };
|
||||
memcpy(info.Name, name.c_str(), name.length());
|
||||
memcpy(info.Md5, md5.c_str(), md5.length());
|
||||
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfoNew) + fileSize];
|
||||
buffer[0] = CMD_EXECUTE_DLL_NEW;
|
||||
memcpy(buffer + 1, &info, sizeof(DllExecuteInfoNew));
|
||||
memcpy(buffer + 1 + sizeof(DllExecuteInfoNew), dllData, fileSize);
|
||||
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfoNew) + fileSize, 0, md5);
|
||||
SAFE_DELETE_ARRAY(dllData);
|
||||
SAFE_DELETE_ARRAY(buffer);
|
||||
return new DllInfo{ name, buf };
|
||||
}
|
||||
|
||||
std::vector<DllInfo*> ReadAllDllFilesWindows(const std::string& dirPath)
|
||||
@@ -605,10 +605,10 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
||||
ON_COMMAND(ID_ONLINE_INJ_NOTEPAD, &CMy2015RemoteDlg::OnOnlineInjNotepad)
|
||||
ON_COMMAND(ID_PARAM_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnParamLoginNotify)
|
||||
ON_COMMAND(ID_PARAM_ENABLE_LOG, &CMy2015RemoteDlg::OnParamEnableLog)
|
||||
ON_COMMAND(ID_PROXY_PORT, &CMy2015RemoteDlg::OnProxyPort)
|
||||
ON_COMMAND(ID_HOOK_WIN, &CMy2015RemoteDlg::OnHookWin)
|
||||
ON_COMMAND(ID_RUNAS_SERVICE, &CMy2015RemoteDlg::OnRunasService)
|
||||
END_MESSAGE_MAP()
|
||||
ON_COMMAND(ID_PROXY_PORT, &CMy2015RemoteDlg::OnProxyPort)
|
||||
ON_COMMAND(ID_HOOK_WIN, &CMy2015RemoteDlg::OnHookWin)
|
||||
ON_COMMAND(ID_RUNAS_SERVICE, &CMy2015RemoteDlg::OnRunasService)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CMy2015RemoteDlg 消息处理程序
|
||||
@@ -847,8 +847,8 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
|
||||
std::string tip = flag ? " (" + v[RES_CLIENT_PUBIP] + ") " : "";
|
||||
ShowMessage("操作成功",strIP + tip.c_str() + "主机上线[" + loc + "]");
|
||||
|
||||
CharMsg *title = new CharMsg("主机上线");
|
||||
CharMsg *text = new CharMsg(strIP + CString(tip.c_str()) + _T(" 主机上线 [") + loc + _T("]"));
|
||||
CharMsg *title = new CharMsg("主机上线");
|
||||
CharMsg *text = new CharMsg(strIP + CString(tip.c_str()) + _T(" 主机上线 [") + loc + _T("]"));
|
||||
LeaveCriticalSection(&m_cs);
|
||||
Mprintf("主机[%s]上线: %s\n", v[RES_CLIENT_PUBIP].empty() ? strIP : v[RES_CLIENT_PUBIP].c_str(),
|
||||
std::to_string(id).c_str());
|
||||
@@ -861,7 +861,8 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CMy2015RemoteDlg::OnShowNotify(WPARAM wParam, LPARAM lParam) {
|
||||
LRESULT CMy2015RemoteDlg::OnShowNotify(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CharMsg* title = (CharMsg*)wParam, * text = (CharMsg*)lParam;
|
||||
|
||||
if (::IsWindow(m_Nid.hWnd)) {
|
||||
@@ -875,8 +876,8 @@ LRESULT CMy2015RemoteDlg::OnShowNotify(WPARAM wParam, LPARAM lParam) {
|
||||
Shell_NotifyIcon(NIM_MODIFY, &nidCopy);
|
||||
SetTimer(TIMER_CLEAR_BALLOON, nidCopy.uTimeout, nullptr);
|
||||
}
|
||||
if (title->needFree) delete title;
|
||||
if (text->needFree) delete text;
|
||||
if (title->needFree) delete title;
|
||||
if (text->needFree) delete text;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1286,7 +1287,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
SubMenu->CheckMenuItem(ID_PARAM_ENABLE_LOG, m_settings.EnableLog ? MF_CHECKED : MF_UNCHECKED);
|
||||
m_bHookWIN = THIS_CFG.GetInt("settings", "HookWIN", 0);
|
||||
SubMenu->CheckMenuItem(ID_HOOK_WIN, m_bHookWIN ? MF_CHECKED : MF_UNCHECKED);
|
||||
m_runNormal = THIS_CFG.GetInt("settings", "RunNormal", 0);
|
||||
m_runNormal = THIS_CFG.GetInt("settings", "RunNormal", 0);
|
||||
SubMenu->CheckMenuItem(ID_RUNAS_SERVICE, !m_runNormal ? MF_CHECKED : MF_UNCHECKED);
|
||||
std::map<int, std::string> myMap = {{SOFTWARE_CAMERA, "摄像头"}, {SOFTWARE_TELEGRAM, "电报" }};
|
||||
std::string str = myMap[n];
|
||||
@@ -1573,8 +1574,7 @@ void CMy2015RemoteDlg::OnTimer(UINT_PTR nIDEvent)
|
||||
if (nIDEvent == TIMER_CLOSEWND) {
|
||||
DeletePopupWindow();
|
||||
}
|
||||
if (nIDEvent == TIMER_CLEAR_BALLOON)
|
||||
{
|
||||
if (nIDEvent == TIMER_CLEAR_BALLOON) {
|
||||
KillTimer(TIMER_CLEAR_BALLOON);
|
||||
|
||||
// 清除气球通知
|
||||
@@ -2317,9 +2317,9 @@ bool SendData(void* user, FileChunkPacket* chunk, BYTE* data, int size)
|
||||
if (!ctx->Send2Client(data, size)) {
|
||||
return false;
|
||||
}
|
||||
CDlgFileSend* dlg = (CDlgFileSend*)ctx->hDlg;
|
||||
CDlgFileSend* dlg = (CDlgFileSend*)ctx->hDlg;
|
||||
BYTE* name = data + sizeof(FileChunkPacket);
|
||||
dlg->UpdateProgress(CString((char*)name, chunk->nameLength), chunk);
|
||||
dlg->UpdateProgress(CString((char*)name, chunk->nameLength), chunk);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2328,7 +2328,7 @@ void delay_cancel(CONTEXT_OBJECT* ctx, int sec)
|
||||
{
|
||||
if (!ctx) return;
|
||||
CDlgFileSend* dlg = (CDlgFileSend*)ctx->hDlg;
|
||||
dlg->FinishFileSend(TRUE);
|
||||
dlg->FinishFileSend(TRUE);
|
||||
Sleep(sec*1000);
|
||||
dlg->PostMessageA(WM_CLOSE);
|
||||
ctx->hDlg = NULL;
|
||||
@@ -2346,7 +2346,7 @@ BOOL CMy2015RemoteDlg::AuthorizeClient(const std::string& sn, const std::string&
|
||||
{
|
||||
if (sn.empty() || passcode.empty() || hmac == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
static const char* superAdmin = getenv("YAMA_PWD");
|
||||
std::string pwd = superAdmin ? superAdmin : m_superPass;
|
||||
return VerifyMessage(pwd, (BYTE*)passcode.c_str(), passcode.length(), hmac);
|
||||
@@ -2355,22 +2355,20 @@ BOOL CMy2015RemoteDlg::AuthorizeClient(const std::string& sn, const std::string&
|
||||
// 从char数组解析出多个路径
|
||||
std::vector<std::string> ParseMultiStringPath(const char* buffer, size_t size)
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
std::vector<std::string> paths;
|
||||
|
||||
const char* p = buffer;
|
||||
const char* end = buffer + size;
|
||||
const char* p = buffer;
|
||||
const char* end = buffer + size;
|
||||
|
||||
while (p < end)
|
||||
{
|
||||
size_t len = strlen(p);
|
||||
if (len > 0)
|
||||
{
|
||||
paths.emplace_back(p, len);
|
||||
}
|
||||
p += len + 1;
|
||||
}
|
||||
while (p < end) {
|
||||
size_t len = strlen(p);
|
||||
if (len > 0) {
|
||||
paths.emplace_back(p, len);
|
||||
}
|
||||
p += len + 1;
|
||||
}
|
||||
|
||||
return paths;
|
||||
return paths;
|
||||
}
|
||||
|
||||
VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
||||
@@ -2406,7 +2404,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
||||
valid = (hash256 == fixedKey);
|
||||
}
|
||||
if (valid) {
|
||||
valid = AuthorizeClient(sn, passcode, hmac);
|
||||
valid = AuthorizeClient(sn, passcode, hmac);
|
||||
if (valid) {
|
||||
Mprintf("%s 校验成功, HMAC 校验成功: %s\n", passcode.c_str(), sn.c_str());
|
||||
std::string tip = passcode + " 校验成功: " + sn;
|
||||
@@ -2429,20 +2427,20 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
||||
}
|
||||
case COMMAND_GET_FILE: {
|
||||
// 发送文件
|
||||
std::string dir = (char*)(szBuffer + 1);
|
||||
char* ptr = (char*)szBuffer + 1 + dir.length() + 1;
|
||||
std::string dir = (char*)(szBuffer + 1);
|
||||
char* ptr = (char*)szBuffer + 1 + dir.length() + 1;
|
||||
auto md5 = CalcMD5FromBytes((BYTE*)ptr, len - 2 - dir.length());
|
||||
if (!m_CmdList.PopCmd(md5)) {
|
||||
Mprintf("【警告】文件传输指令非法或已过期: %s\n", md5.c_str());
|
||||
ContextObject->CancelIO();
|
||||
break;
|
||||
}
|
||||
auto files = *ptr ? ParseMultiStringPath(ptr, len - 2 - dir.length()) : std::vector<std::string>{};
|
||||
auto files = *ptr ? ParseMultiStringPath(ptr, len - 2 - dir.length()) : std::vector<std::string> {};
|
||||
if (!files.empty()) {
|
||||
CDlgFileSend* dlg = new CDlgFileSend(this, ContextObject->GetServer(), ContextObject, TRUE);
|
||||
dlg->Create(IDD_DIALOG_FILESEND, GetDesktopWindow());
|
||||
dlg->ShowWindow(SW_HIDE);
|
||||
ContextObject->hDlg = dlg;
|
||||
CDlgFileSend* dlg = new CDlgFileSend(this, ContextObject->GetServer(), ContextObject, TRUE);
|
||||
dlg->Create(IDD_DIALOG_FILESEND, GetDesktopWindow());
|
||||
dlg->ShowWindow(SW_HIDE);
|
||||
ContextObject->hDlg = dlg;
|
||||
std::string hash = GetPwdHash(), hmac = GetHMAC(100);
|
||||
std::thread(FileBatchTransferWorker, files, dir, ContextObject, SendData, FinishSend,
|
||||
hash, hmac).detach();
|
||||
@@ -2460,7 +2458,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
||||
ContextObject->hDlg = dlg;
|
||||
}
|
||||
DialogBase* dlg = (DialogBase*)ContextObject->hDlg;
|
||||
dlg->OnReceiveComplete();
|
||||
dlg->OnReceiveComplete();
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2518,39 +2516,38 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
||||
break;
|
||||
}
|
||||
case CMD_EXECUTE_DLL: { // 请求DLL(执行代码)【L】
|
||||
case CMD_EXECUTE_DLL_NEW:
|
||||
DllExecuteInfo *info = (DllExecuteInfo*)ContextObject->InDeCompressedBuffer.GetBuffer(1);
|
||||
if (std::string(info->Name) == TINY_DLL_NAME) {
|
||||
auto tinyRun = ReadTinyRunDll(info->Pid);
|
||||
Buffer* buf = tinyRun->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), tinyRun->Data->length());
|
||||
SAFE_DELETE(tinyRun);
|
||||
break;
|
||||
}
|
||||
else if (std::string(info->Name) == FRPC_DLL_NAME) {
|
||||
auto frpc = ReadFrpcDll();
|
||||
Buffer* buf = frpc->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), frpc->Data->length());
|
||||
SAFE_DELETE(frpc);
|
||||
break;
|
||||
}
|
||||
for (std::vector<DllInfo*>::const_iterator i=m_DllList.begin(); i!=m_DllList.end(); ++i) {
|
||||
DllInfo* dll = *i;
|
||||
if (dll->Name == info->Name) {
|
||||
// TODO 如果是UDP,发送大包数据基本上不可能成功
|
||||
ContextObject->Send2Client(dll->Data->Buf(), dll->Data->length());
|
||||
case CMD_EXECUTE_DLL_NEW:
|
||||
DllExecuteInfo *info = (DllExecuteInfo*)ContextObject->InDeCompressedBuffer.GetBuffer(1);
|
||||
if (std::string(info->Name) == TINY_DLL_NAME) {
|
||||
auto tinyRun = ReadTinyRunDll(info->Pid);
|
||||
Buffer* buf = tinyRun->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), tinyRun->Data->length());
|
||||
SAFE_DELETE(tinyRun);
|
||||
break;
|
||||
} else if (std::string(info->Name) == FRPC_DLL_NAME) {
|
||||
auto frpc = ReadFrpcDll();
|
||||
Buffer* buf = frpc->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), frpc->Data->length());
|
||||
SAFE_DELETE(frpc);
|
||||
break;
|
||||
}
|
||||
for (std::vector<DllInfo*>::const_iterator i=m_DllList.begin(); i!=m_DllList.end(); ++i) {
|
||||
DllInfo* dll = *i;
|
||||
if (dll->Name == info->Name) {
|
||||
// TODO 如果是UDP,发送大包数据基本上不可能成功
|
||||
ContextObject->Send2Client(dll->Data->Buf(), dll->Data->length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto dll = ReadPluginDll(PluginPath() + "\\" + info->Name, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, info->Pid, info->Is32Bit });
|
||||
if (dll) {
|
||||
Buffer* buf = dll->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), dll->Data->length());
|
||||
SAFE_DELETE(dll);
|
||||
}
|
||||
Sleep(20);
|
||||
break;
|
||||
}
|
||||
auto dll = ReadPluginDll(PluginPath() + "\\" + info->Name, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, info->Pid, info->Is32Bit });
|
||||
if (dll) {
|
||||
Buffer* buf = dll->Data;
|
||||
ContextObject->Send2Client(buf->Buf(), dll->Data->length());
|
||||
SAFE_DELETE(dll);
|
||||
}
|
||||
Sleep(20);
|
||||
break;
|
||||
}
|
||||
case COMMAND_PROXY: { // 代理映射【x】
|
||||
g_2015RemoteDlg->SendMessage(WM_OPENPROXYDIALOG, 0, (LPARAM)ContextObject);
|
||||
break;
|
||||
@@ -2783,14 +2780,14 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx)
|
||||
// 回复心跳
|
||||
// if(0)
|
||||
{
|
||||
BOOL authorized = AuthorizeClient(hb.SN, hb.Passcode, hb.PwdHmac);
|
||||
if (authorized) {
|
||||
Mprintf("%s HMAC 校验成功: %lld\n", hb.Passcode, hb.PwdHmac);
|
||||
std::string tip = std::string(hb.Passcode) + " 授权成功: ";
|
||||
tip += std::to_string(hb.PwdHmac) + "[" + std::string(ctx->GetClientData(ONLINELIST_IP)) + "]";
|
||||
CharMsg* msg = new CharMsg(tip.c_str());
|
||||
PostMessageA(WM_SHOWMESSAGE, (WPARAM)msg, NULL);
|
||||
}
|
||||
BOOL authorized = AuthorizeClient(hb.SN, hb.Passcode, hb.PwdHmac);
|
||||
if (authorized) {
|
||||
Mprintf("%s HMAC 校验成功: %lld\n", hb.Passcode, hb.PwdHmac);
|
||||
std::string tip = std::string(hb.Passcode) + " 授权成功: ";
|
||||
tip += std::to_string(hb.PwdHmac) + "[" + std::string(ctx->GetClientData(ONLINELIST_IP)) + "]";
|
||||
CharMsg* msg = new CharMsg(tip.c_str());
|
||||
PostMessageA(WM_SHOWMESSAGE, (WPARAM)msg, NULL);
|
||||
}
|
||||
HeartbeatACK ack = { hb.Time, (char)authorized };
|
||||
BYTE buf[sizeof(HeartbeatACK) + 1] = { CMD_HEARTBEAT_ACK};
|
||||
memcpy(buf + 1, &ack, sizeof(HeartbeatACK));
|
||||
@@ -3171,33 +3168,31 @@ char* ReadFileToBuffer(const std::string &path, size_t& outSize)
|
||||
|
||||
BOOL WriteBinaryToFile(const char* path, const char* data, ULONGLONG size, LONGLONG offset)
|
||||
{
|
||||
std::string filePath = path;
|
||||
std::fstream outFile;
|
||||
std::string filePath = path;
|
||||
std::fstream outFile;
|
||||
|
||||
if (offset == 0) {
|
||||
// offset=0 时截断文件,等同覆盖写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
}
|
||||
else if (offset == -1) {
|
||||
// offset=-1 时追加写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out | std::ios::app);
|
||||
}
|
||||
else {
|
||||
// 非0偏移,保留原内容,定位写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::in | std::ios::out);
|
||||
if (offset == 0) {
|
||||
// offset=0 时截断文件,等同覆盖写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
} else if (offset == -1) {
|
||||
// offset=-1 时追加写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out | std::ios::app);
|
||||
} else {
|
||||
// 非0偏移,保留原内容,定位写入
|
||||
outFile.open(filePath, std::ios::binary | std::ios::in | std::ios::out);
|
||||
|
||||
// 文件不存在时创建
|
||||
if (!outFile) {
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out);
|
||||
}
|
||||
}
|
||||
// 文件不存在时创建
|
||||
if (!outFile) {
|
||||
outFile.open(filePath, std::ios::binary | std::ios::out);
|
||||
}
|
||||
}
|
||||
|
||||
if (!outFile) {
|
||||
Mprintf("Failed to open or create the file: %s.\n", filePath.c_str());
|
||||
return FALSE;
|
||||
}
|
||||
if (!outFile) {
|
||||
Mprintf("Failed to open or create the file: %s.\n", filePath.c_str());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 追加模式不需要 seekp, 其他情况定位到指定位置
|
||||
// 追加模式不需要 seekp, 其他情况定位到指定位置
|
||||
if (offset != -1) {
|
||||
// 定位到指定位置
|
||||
outFile.seekp(offset, std::ios::beg);
|
||||
@@ -3210,20 +3205,19 @@ BOOL WriteBinaryToFile(const char* path, const char* data, ULONGLONG size, LONGL
|
||||
}
|
||||
}
|
||||
|
||||
// 写入二进制数据
|
||||
outFile.write(data, size);
|
||||
// 写入二进制数据
|
||||
outFile.write(data, size);
|
||||
|
||||
if (outFile.good()) {
|
||||
Mprintf("Binary data written successfully to %s.\n", filePath.c_str());
|
||||
}
|
||||
else {
|
||||
Mprintf("Failed to write data to file.\n");
|
||||
outFile.close();
|
||||
return FALSE;
|
||||
}
|
||||
if (outFile.good()) {
|
||||
Mprintf("Binary data written successfully to %s.\n", filePath.c_str());
|
||||
} else {
|
||||
Mprintf("Failed to write data to file.\n");
|
||||
outFile.close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
outFile.close();
|
||||
return TRUE;
|
||||
outFile.close();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int run_cmd(std::string cmdLine)
|
||||
@@ -4289,74 +4283,74 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam
|
||||
do {
|
||||
static CDialogBase* operateWnd = nullptr;
|
||||
KBDLLHOOKSTRUCT* pKey = (KBDLLHOOKSTRUCT*)lParam;
|
||||
// 先判断是否需要处理的热键
|
||||
bool bNeedCheck = false;
|
||||
if (wParam == WM_SYSKEYDOWN || wParam == WM_SYSKEYUP) {
|
||||
// 所有系统键都需要检查
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Win 键 (开始菜单、Win+D/E/R/L 等)
|
||||
else if (pKey->vkCode == VK_LWIN || pKey->vkCode == VK_RWIN) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Alt+Tab (切换窗口)
|
||||
else if (pKey->vkCode == VK_TAB && (pKey->flags & LLKHF_ALTDOWN)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Alt+Esc (循环切换窗口)
|
||||
else if (pKey->vkCode == VK_ESCAPE && (pKey->flags & LLKHF_ALTDOWN)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Ctrl+Shift+Esc (任务管理器)
|
||||
else if (pKey->vkCode == VK_ESCAPE &&
|
||||
(GetAsyncKeyState(VK_CONTROL) & 0x8000) &&
|
||||
(GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Ctrl+Esc (开始菜单)
|
||||
else if (pKey->vkCode == VK_ESCAPE && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// F12 (调试器热键)
|
||||
else if (pKey->vkCode == VK_F12 || pKey->vkCode == VK_F10) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Print Screen (截图)
|
||||
else if (pKey->vkCode == VK_SNAPSHOT) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Win+Tab (任务视图)
|
||||
else if (pKey->vkCode == VK_TAB &&
|
||||
(GetAsyncKeyState(VK_LWIN) & 0x8000 || GetAsyncKeyState(VK_RWIN) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
if (bNeedCheck && g_2015RemoteDlg->m_bHookWIN) {
|
||||
// 先判断是否需要处理的热键
|
||||
bool bNeedCheck = false;
|
||||
if (wParam == WM_SYSKEYDOWN || wParam == WM_SYSKEYUP) {
|
||||
// 所有系统键都需要检查
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Win 键 (开始菜单、Win+D/E/R/L 等)
|
||||
else if (pKey->vkCode == VK_LWIN || pKey->vkCode == VK_RWIN) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Alt+Tab (切换窗口)
|
||||
else if (pKey->vkCode == VK_TAB && (pKey->flags & LLKHF_ALTDOWN)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Alt+Esc (循环切换窗口)
|
||||
else if (pKey->vkCode == VK_ESCAPE && (pKey->flags & LLKHF_ALTDOWN)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Ctrl+Shift+Esc (任务管理器)
|
||||
else if (pKey->vkCode == VK_ESCAPE &&
|
||||
(GetAsyncKeyState(VK_CONTROL) & 0x8000) &&
|
||||
(GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Ctrl+Esc (开始菜单)
|
||||
else if (pKey->vkCode == VK_ESCAPE && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// F12 (调试器热键)
|
||||
else if (pKey->vkCode == VK_F12 || pKey->vkCode == VK_F10) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Print Screen (截图)
|
||||
else if (pKey->vkCode == VK_SNAPSHOT) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
// Win+Tab (任务视图)
|
||||
else if (pKey->vkCode == VK_TAB &&
|
||||
(GetAsyncKeyState(VK_LWIN) & 0x8000 || GetAsyncKeyState(VK_RWIN) & 0x8000)) {
|
||||
bNeedCheck = true;
|
||||
}
|
||||
if (bNeedCheck && g_2015RemoteDlg->m_bHookWIN) {
|
||||
HWND hFore = ::GetForegroundWindow();
|
||||
auto screen = (CScreenSpyDlg*)g_2015RemoteDlg->GetRemoteWindow(hFore);
|
||||
auto screen = (CScreenSpyDlg*)g_2015RemoteDlg->GetRemoteWindow(hFore);
|
||||
if (screen && screen->m_bIsCtrl) {
|
||||
MSG msg = { 0 };
|
||||
msg.hwnd = hFore;
|
||||
msg.message = (UINT)wParam;
|
||||
msg.wParam = pKey->vkCode;
|
||||
msg.lParam = (pKey->scanCode << 16) | 1;
|
||||
MSG msg = { 0 };
|
||||
msg.hwnd = hFore;
|
||||
msg.message = (UINT)wParam;
|
||||
msg.wParam = pKey->vkCode;
|
||||
msg.lParam = (pKey->scanCode << 16) | 1;
|
||||
|
||||
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
|
||||
msg.lParam |= (1 << 31) | (1 << 30);
|
||||
}
|
||||
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
|
||||
msg.lParam |= (1 << 31) | (1 << 30);
|
||||
}
|
||||
|
||||
// 扩展键标志 (bit 24)
|
||||
if (pKey->flags & LLKHF_EXTENDED) {
|
||||
msg.lParam |= (1 << 24);
|
||||
}
|
||||
// 扩展键标志 (bit 24)
|
||||
if (pKey->flags & LLKHF_EXTENDED) {
|
||||
msg.lParam |= (1 << 24);
|
||||
}
|
||||
|
||||
msg.time = pKey->time;
|
||||
msg.pt.x = 0;
|
||||
msg.pt.y = 0;
|
||||
msg.time = pKey->time;
|
||||
msg.pt.x = 0;
|
||||
msg.pt.y = 0;
|
||||
screen->SendScaledMouseMessage(&msg, false);
|
||||
// 返回 1 阻止本地系统处理
|
||||
return 1;
|
||||
// 返回 1 阻止本地系统处理
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 只在按下时处理
|
||||
if (wParam == WM_KEYDOWN) {
|
||||
// 检测 Ctrl+C / Ctrl+X
|
||||
@@ -4382,7 +4376,7 @@ LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam
|
||||
auto files = GetClipboardFiles(result);
|
||||
if (!files.empty()) {
|
||||
// 获取远程目录
|
||||
auto str = BuildMultiStringPath(files);
|
||||
auto str = BuildMultiStringPath(files);
|
||||
BYTE* szBuffer = new BYTE[81 + str.size()];
|
||||
szBuffer[0] = { COMMAND_GET_FOLDER };
|
||||
std::string masterId = GetPwdHash(), hmac = GetHMAC(100);
|
||||
@@ -4574,63 +4568,60 @@ void CMy2015RemoteDlg::OnParamEnableLog()
|
||||
|
||||
bool IsDateGreaterOrEqual(const char* date1, const char* date2)
|
||||
{
|
||||
const char* months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
const char* months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
auto parseDate = [&months](const char* date, int& year, int& month, int& day) {
|
||||
char mon[4] = { 0 };
|
||||
sscanf(date, "%3s %d %d", mon, &day, &year);
|
||||
month = 0;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (strcmp(mon, months[i]) == 0) {
|
||||
month = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
auto parseDate = [&months](const char* date, int& year, int& month, int& day) {
|
||||
char mon[4] = { 0 };
|
||||
sscanf(date, "%3s %d %d", mon, &day, &year);
|
||||
month = 0;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (strcmp(mon, months[i]) == 0) {
|
||||
month = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int y1, m1, d1, y2, m2, d2;
|
||||
parseDate(date1, y1, m1, d1);
|
||||
parseDate(date2, y2, m2, d2);
|
||||
int y1, m1, d1, y2, m2, d2;
|
||||
parseDate(date1, y1, m1, d1);
|
||||
parseDate(date2, y2, m2, d2);
|
||||
|
||||
if (y1 != y2) return y1 >= y2;
|
||||
if (m1 != m2) return m1 >= m2;
|
||||
return d1 >= d2;
|
||||
if (y1 != y2) return y1 >= y2;
|
||||
if (m1 != m2) return m1 >= m2;
|
||||
return d1 >= d2;
|
||||
}
|
||||
|
||||
std::string GetAuthKey(const char* token, long long timestamp)
|
||||
{
|
||||
char tsStr[32];
|
||||
sprintf_s(tsStr, "%lld", timestamp);
|
||||
char tsStr[32];
|
||||
sprintf_s(tsStr, "%lld", timestamp);
|
||||
|
||||
HCRYPTPROV hProv = 0;
|
||||
HCRYPTHASH hHash = 0;
|
||||
std::string result;
|
||||
HCRYPTPROV hProv = 0;
|
||||
HCRYPTHASH hHash = 0;
|
||||
std::string result;
|
||||
|
||||
if (CryptAcquireContextW(&hProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
|
||||
{
|
||||
CryptHashData(hHash, (BYTE*)token, (DWORD)strlen(token), 0);
|
||||
CryptHashData(hHash, (BYTE*)tsStr, (DWORD)strlen(tsStr), 0);
|
||||
if (CryptAcquireContextW(&hProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
|
||||
CryptHashData(hHash, (BYTE*)token, (DWORD)strlen(token), 0);
|
||||
CryptHashData(hHash, (BYTE*)tsStr, (DWORD)strlen(tsStr), 0);
|
||||
|
||||
BYTE hash[16];
|
||||
DWORD cbHash = sizeof(hash);
|
||||
if (CryptGetHashParam(hHash, HP_HASHVAL, hash, &cbHash, 0))
|
||||
{
|
||||
char hex[33];
|
||||
for (int i = 0; i < 16; i++)
|
||||
sprintf_s(hex + i * 2, 3, "%02x", hash[i]);
|
||||
result = hex;
|
||||
}
|
||||
CryptDestroyHash(hHash);
|
||||
}
|
||||
CryptReleaseContext(hProv, 0);
|
||||
}
|
||||
BYTE hash[16];
|
||||
DWORD cbHash = sizeof(hash);
|
||||
if (CryptGetHashParam(hHash, HP_HASHVAL, hash, &cbHash, 0)) {
|
||||
char hex[33];
|
||||
for (int i = 0; i < 16; i++)
|
||||
sprintf_s(hex + i * 2, 3, "%02x", hash[i]);
|
||||
result = hex;
|
||||
}
|
||||
CryptDestroyHash(hHash);
|
||||
}
|
||||
CryptReleaseContext(hProv, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// 基于FRP将客户端端口代理到主控程序的公网
|
||||
@@ -4646,66 +4637,65 @@ void CMy2015RemoteDlg::OnProxyPort()
|
||||
}
|
||||
CInputDialog dlg(this);
|
||||
dlg.Init("代理端口", "请输入客户端端口:");
|
||||
if (IDOK != dlg.DoModal() || atoi(dlg.m_str) <= 0 || atoi(dlg.m_str) >= 65536) {
|
||||
return;
|
||||
}
|
||||
if (IDOK != dlg.DoModal() || atoi(dlg.m_str) <= 0 || atoi(dlg.m_str) >= 65536) {
|
||||
return;
|
||||
}
|
||||
uint64_t timestamp = time(nullptr);
|
||||
std::string key = GetAuthKey(pwd.c_str(), timestamp);
|
||||
int serverPort = THIS_CFG.GetInt("frp", "server_port", 7000);
|
||||
int serverPort = THIS_CFG.GetInt("frp", "server_port", 7000);
|
||||
int localPort = atoi(dlg.m_str);
|
||||
auto frpc = ReadFrpcDll();
|
||||
auto frpc = ReadFrpcDll();
|
||||
FrpcParam param(key.c_str(), timestamp, ip.c_str(), serverPort, localPort, localPort);
|
||||
EnterCriticalSection(&m_cs);
|
||||
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
|
||||
BOOL sent = FALSE;
|
||||
while (Pos) {
|
||||
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
|
||||
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
|
||||
if (!ctx->IsLogin())
|
||||
continue;
|
||||
EnterCriticalSection(&m_cs);
|
||||
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
|
||||
BOOL sent = FALSE;
|
||||
while (Pos) {
|
||||
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
|
||||
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
|
||||
if (!ctx->IsLogin())
|
||||
continue;
|
||||
CString date = ctx->GetClientData(ONLINELIST_VERSION);
|
||||
if (IsDateGreaterOrEqual(date, "Dec 22 2025")) {
|
||||
Buffer* buf = frpc->Data;
|
||||
if (IsDateGreaterOrEqual(date, "Dec 22 2025")) {
|
||||
Buffer* buf = frpc->Data;
|
||||
BYTE cmd[1 + sizeof(DllExecuteInfoNew)] = {0};
|
||||
memcpy(cmd, buf->Buf(), 1 + sizeof(DllExecuteInfoNew));
|
||||
DllExecuteInfoNew* p = (DllExecuteInfoNew*)(cmd + 1);
|
||||
SetParameters(p, (char*)¶m, sizeof(param));
|
||||
ctx->Send2Client(cmd, 1 + sizeof(DllExecuteInfoNew));
|
||||
sent = TRUE;
|
||||
}
|
||||
else {
|
||||
PostMessageA(WM_SHOWNOTIFY, (WPARAM)new CharMsg("版本不支持"),
|
||||
(LPARAM)new CharMsg("客户端版本最低要求: " + CString("Dec 22 2025")));
|
||||
ctx->Send2Client(cmd, 1 + sizeof(DllExecuteInfoNew));
|
||||
sent = TRUE;
|
||||
} else {
|
||||
PostMessageA(WM_SHOWNOTIFY, (WPARAM)new CharMsg("版本不支持"),
|
||||
(LPARAM)new CharMsg("客户端版本最低要求: " + CString("Dec 22 2025")));
|
||||
}
|
||||
break;
|
||||
}
|
||||
LeaveCriticalSection(&m_cs);
|
||||
SAFE_DELETE(frpc);
|
||||
}
|
||||
LeaveCriticalSection(&m_cs);
|
||||
SAFE_DELETE(frpc);
|
||||
if (sent)
|
||||
MessageBoxA(CString("请通过") + ip.c_str() + ":" + std::to_string(localPort).c_str() + "访问代理端口!",
|
||||
"提示", MB_ICONINFORMATION);
|
||||
MessageBoxA(CString("请通过") + ip.c_str() + ":" + std::to_string(localPort).c_str() + "访问代理端口!",
|
||||
"提示", MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
|
||||
void CMy2015RemoteDlg::OnHookWin()
|
||||
{
|
||||
m_bHookWIN = !m_bHookWIN;
|
||||
MessageBoxA(CString("远程控制时,") + (m_bHookWIN ? "" : "不") + CString("转发系统热键到远程桌面。"),
|
||||
"提示", MB_ICONINFORMATION);
|
||||
THIS_CFG.SetInt("settings", "HookWIN", m_bHookWIN);
|
||||
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
|
||||
SubMenu->CheckMenuItem(ID_HOOK_WIN, m_bHookWIN ? MF_CHECKED : MF_UNCHECKED);
|
||||
m_bHookWIN = !m_bHookWIN;
|
||||
MessageBoxA(CString("远程控制时,") + (m_bHookWIN ? "" : "不") + CString("转发系统热键到远程桌面。"),
|
||||
"提示", MB_ICONINFORMATION);
|
||||
THIS_CFG.SetInt("settings", "HookWIN", m_bHookWIN);
|
||||
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
|
||||
SubMenu->CheckMenuItem(ID_HOOK_WIN, m_bHookWIN ? MF_CHECKED : MF_UNCHECKED);
|
||||
}
|
||||
|
||||
|
||||
void CMy2015RemoteDlg::OnRunasService()
|
||||
{
|
||||
m_runNormal = !m_runNormal;
|
||||
MessageBoxA(m_runNormal ? CString("以传统方式启动主控程序,没有守护进程。") :
|
||||
CString("以“服务+代理”形式启动主控程序,会开机自启及被守护。"),
|
||||
"提示", MB_ICONINFORMATION);
|
||||
THIS_CFG.SetInt("settings", "RunNormal", m_runNormal);
|
||||
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
|
||||
SubMenu->CheckMenuItem(ID_RUNAS_SERVICE, !m_runNormal ? MF_CHECKED : MF_UNCHECKED);
|
||||
MessageBoxA(m_runNormal ? CString("以传统方式启动主控程序,没有守护进程。") :
|
||||
CString("以“服务+代理”形式启动主控程序,会开机自启及被守护。"),
|
||||
"提示", MB_ICONINFORMATION);
|
||||
THIS_CFG.SetInt("settings", "RunNormal", m_runNormal);
|
||||
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
|
||||
SubMenu->CheckMenuItem(ID_RUNAS_SERVICE, !m_runNormal ? MF_CHECKED : MF_UNCHECKED);
|
||||
BOOL r = m_runNormal ? ServerService_Uninstall() : ServerService_Install();
|
||||
}
|
||||
|
||||
@@ -29,18 +29,20 @@ typedef struct DllInfo {
|
||||
typedef struct FileTransformCmd {
|
||||
CLock Lock;
|
||||
std::map<std::string, uint64_t> CmdTime;
|
||||
void PutCmd(const std::string& str) {
|
||||
Lock.Lock();
|
||||
CmdTime[str] = time(0);
|
||||
Lock.Unlock();
|
||||
}
|
||||
bool PopCmd(const std::string& str, int timeoutSec = 10) {
|
||||
Lock.Lock();
|
||||
bool valid = CmdTime.find(str) != CmdTime.end() && time(0) - CmdTime[str] < timeoutSec;
|
||||
CmdTime.erase(str);
|
||||
Lock.Unlock();
|
||||
return valid;
|
||||
}
|
||||
void PutCmd(const std::string& str)
|
||||
{
|
||||
Lock.Lock();
|
||||
CmdTime[str] = time(0);
|
||||
Lock.Unlock();
|
||||
}
|
||||
bool PopCmd(const std::string& str, int timeoutSec = 10)
|
||||
{
|
||||
Lock.Lock();
|
||||
bool valid = CmdTime.find(str) != CmdTime.end() && time(0) - CmdTime[str] < timeoutSec;
|
||||
CmdTime.erase(str);
|
||||
Lock.Unlock();
|
||||
return valid;
|
||||
}
|
||||
} FileTransformCmd;
|
||||
|
||||
#define ID_DYNAMIC_MENU_BASE 36500
|
||||
|
||||
@@ -73,16 +73,20 @@ public:
|
||||
{
|
||||
return md5;
|
||||
}
|
||||
BYTE GetBYTE(int idx=0) const {
|
||||
BYTE GetBYTE(int idx=0) const
|
||||
{
|
||||
return idx >= len ? 0 : buf[idx];
|
||||
}
|
||||
LPBYTE GetBuffer(int idx=0) const {
|
||||
LPBYTE GetBuffer(int idx=0) const
|
||||
{
|
||||
return idx >= len ? 0 : buf + idx;
|
||||
}
|
||||
int GetBufferLength() const {
|
||||
int GetBufferLength() const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
BOOL CopyBuffer(PVOID pDst, ULONG nLen, ULONG ulPos=0) {
|
||||
BOOL CopyBuffer(PVOID pDst, ULONG nLen, ULONG ulPos=0)
|
||||
{
|
||||
if (len - ulPos < nLen) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "InputDlg.h"
|
||||
#include <bcrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include "Resource.h"
|
||||
// #include <ntstatus.h>
|
||||
|
||||
enum Index {
|
||||
@@ -71,6 +72,30 @@ LPBYTE ReadResource(int resourceId, DWORD &dwSize)
|
||||
}
|
||||
|
||||
|
||||
CString GenerateRandomName(int nLength)
|
||||
{
|
||||
if (nLength <= 0) nLength = 8;
|
||||
|
||||
static const TCHAR szChars[] = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||
static const int nCharsCount = _countof(szChars) - 1;
|
||||
|
||||
static bool bSeeded = false;
|
||||
if (!bSeeded) {
|
||||
srand((unsigned)time(NULL));
|
||||
bSeeded = true;
|
||||
}
|
||||
|
||||
CString strName;
|
||||
LPTSTR pBuf = strName.GetBuffer(nLength);
|
||||
|
||||
for (int i = 0; i < nLength; i++) {
|
||||
pBuf[i] = szChars[rand() % nCharsCount];
|
||||
}
|
||||
|
||||
strName.ReleaseBuffer(nLength);
|
||||
return strName;
|
||||
}
|
||||
|
||||
CBuildDlg::CBuildDlg(CWnd* pParent)
|
||||
: CDialog(CBuildDlg::IDD, pParent)
|
||||
, m_strIP(_T(""))
|
||||
@@ -78,6 +103,8 @@ CBuildDlg::CBuildDlg(CWnd* pParent)
|
||||
, m_strFindden(FLAG_FINDEN)
|
||||
, m_sGroupName(_T("default"))
|
||||
, m_strEncryptIP(_T("是"))
|
||||
, m_sInstallDir(_T(""))
|
||||
, m_sInstallName(_T(""))
|
||||
{
|
||||
|
||||
}
|
||||
@@ -104,6 +131,12 @@ void CBuildDlg::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_Control(pDX, IDC_COMBO_PAYLOAD, m_ComboPayload);
|
||||
DDX_Control(pDX, IDC_STATIC_PAYLOAD, m_StaticPayload);
|
||||
DDX_Control(pDX, IDC_SLIDER_CLIENT_SIZE, m_SliderClientSize);
|
||||
DDX_Control(pDX, IDC_EDIT_INSTALL_DIR, m_EditInstallDir);
|
||||
DDX_Control(pDX, IDC_EDIT_INSTALL_NAME, m_EditInstallName);
|
||||
DDX_Text(pDX, IDC_EDIT_INSTALL_DIR, m_sInstallDir);
|
||||
DDV_MaxChars(pDX, m_sInstallDir, 31);
|
||||
DDX_Text(pDX, IDC_EDIT_INSTALL_NAME, m_sInstallName);
|
||||
DDV_MaxChars(pDX, m_sInstallName, 31);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +148,12 @@ BEGIN_MESSAGE_MAP(CBuildDlg, CDialog)
|
||||
ON_COMMAND(ID_MENU_ENCRYPT_IP, &CBuildDlg::OnMenuEncryptIp)
|
||||
ON_COMMAND(ID_CLIENT_RUNAS_ADMIN, &CBuildDlg::OnClientRunasAdmin)
|
||||
ON_CBN_SELCHANGE(IDC_COMBO_COMPRESS, &CBuildDlg::OnCbnSelchangeComboCompress)
|
||||
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CBuildDlg::OnToolTipNotify)
|
||||
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CBuildDlg::OnToolTipNotify)
|
||||
ON_EN_CHANGE(IDC_EDIT_INSTALL_DIR, &CBuildDlg::OnEnChangeEditInstallDir)
|
||||
ON_EN_CHANGE(IDC_EDIT_INSTALL_NAME, &CBuildDlg::OnEnChangeEditInstallName)
|
||||
ON_EN_KILLFOCUS(IDC_EDIT_INSTALL_DIR, &CBuildDlg::OnEnKillfocusEditInstallDir)
|
||||
ON_EN_KILLFOCUS(IDC_EDIT_INSTALL_NAME, &CBuildDlg::OnEnKillfocusEditInstallName)
|
||||
ON_COMMAND(ID_RANDOM_NAME, &CBuildDlg::OnRandomName)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -182,17 +220,53 @@ void generate_random_iv(unsigned char* iv, size_t len)
|
||||
|
||||
ULONGLONG GetFileSize(const char* path)
|
||||
{
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!file) {
|
||||
Mprintf("Failed to open file: %s.\n", path);
|
||||
return 0;
|
||||
}
|
||||
if (!file) {
|
||||
Mprintf("Failed to open file: %s.\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONGLONG size = file.tellg();
|
||||
file.close();
|
||||
ULONGLONG size = file.tellg();
|
||||
file.close();
|
||||
|
||||
return size;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool IsValidFileName(const CString& strName)
|
||||
{
|
||||
if (strName.IsEmpty()) return false;
|
||||
|
||||
// 检查非法字符
|
||||
LPCTSTR szInvalidChars = _T("\\/:*?\"<>|");
|
||||
if (strName.FindOneOf(szInvalidChars) != -1)
|
||||
return false;
|
||||
|
||||
// 检查保留名称 (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
|
||||
CString strUpper = strName;
|
||||
strUpper.MakeUpper();
|
||||
int nDot = strUpper.Find(_T('.'));
|
||||
CString strBase = (nDot != -1) ? strUpper.Left(nDot) : strUpper;
|
||||
|
||||
LPCTSTR szReserved[] = {
|
||||
_T("CON"), _T("PRN"), _T("AUX"), _T("NUL"),
|
||||
_T("COM1"), _T("COM2"), _T("COM3"), _T("COM4"), _T("COM5"),
|
||||
_T("COM6"), _T("COM7"), _T("COM8"), _T("COM9"),
|
||||
_T("LPT1"), _T("LPT2"), _T("LPT3"), _T("LPT4"), _T("LPT5"),
|
||||
_T("LPT6"), _T("LPT7"), _T("LPT8"), _T("LPT9"), NULL
|
||||
};
|
||||
|
||||
for (int i = 0; szReserved[i]; i++) {
|
||||
if (strBase == szReserved[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
// 不能以空格或点结尾
|
||||
TCHAR chLast = strName[strName.GetLength() - 1];
|
||||
if (chLast == _T(' ') || chLast == _T('.'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBuildDlg::OnBnClickedOk()
|
||||
@@ -282,6 +356,8 @@ void CBuildDlg::OnBnClickedOk()
|
||||
g_ConnectAddress.iHeaderEnc = m_ComboEncrypt.GetCurSel();
|
||||
memcpy(g_ConnectAddress.pwdHash, GetPwdHash().c_str(), sizeof(g_ConnectAddress.pwdHash));
|
||||
memcpy(g_ConnectAddress.szGroupName, m_sGroupName, m_sGroupName.GetLength());
|
||||
memcpy(g_ConnectAddress.installDir, m_sInstallDir, m_sInstallDir.GetLength());
|
||||
memcpy(g_ConnectAddress.installName, m_sInstallName, m_sInstallName.GetLength());
|
||||
|
||||
if (!g_ConnectAddress.IsValid()) {
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
@@ -374,24 +450,24 @@ void CBuildDlg::OnBnClickedOk()
|
||||
PathRenameExtension(strSeverFile.GetBuffer(MAX_PATH), _T(".exe"));
|
||||
strSeverFile.ReleaseBuffer();
|
||||
if (strSeverFile != old) DeleteFileA(old);
|
||||
int n = m_ComboPayload.GetCurSel();
|
||||
CString payload = strSeverFile;
|
||||
if (n) {
|
||||
static std::map<int, std::string> m = {
|
||||
{ Payload_Raw, "*.bin|*.bin|"}, { Payload_BMP, "*.bmp|*.bmp|"},
|
||||
{ Payload_JPG, "*.jpg|*.jpg|"}, { Payload_PNG, "*.png|*.png|"},
|
||||
{ Payload_ZIP, "*.zip|*.zip|"}, { Payload_PDF, "*.pdf|*.pdf|"},
|
||||
};
|
||||
payload = GetFilePath(NULL, m[n].c_str(), n != Payload_Raw);
|
||||
sc->offset = n == Payload_Raw ? 0 : GetFileSize(payload);
|
||||
int n = m_ComboPayload.GetCurSel();
|
||||
CString payload = strSeverFile;
|
||||
if (n) {
|
||||
static std::map<int, std::string> m = {
|
||||
{ Payload_Raw, "*.bin|*.bin|"}, { Payload_BMP, "*.bmp|*.bmp|"},
|
||||
{ Payload_JPG, "*.jpg|*.jpg|"}, { Payload_PNG, "*.png|*.png|"},
|
||||
{ Payload_ZIP, "*.zip|*.zip|"}, { Payload_PDF, "*.pdf|*.pdf|"},
|
||||
};
|
||||
payload = GetFilePath(NULL, m[n].c_str(), n != Payload_Raw);
|
||||
sc->offset = n == Payload_Raw ? 0 : GetFileSize(payload);
|
||||
strcpy(sc->file, PathFindFileNameA(payload));
|
||||
tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" : "\r\n提示: 载荷文件必须拷贝至程序目录。";
|
||||
}
|
||||
tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" : "\r\n提示: 载荷文件必须拷贝至程序目录。";
|
||||
}
|
||||
BOOL r = WriteBinaryToFile(strSeverFile.GetString(), (char*)data, dwSize);
|
||||
if (r) {
|
||||
r = WriteBinaryToFile(payload.GetString(), (char*)srcData, srcLen, n == Payload_Raw ? 0 : -1);
|
||||
if (!r) tip = "\r\n警告: 生成载荷失败!";
|
||||
}else{
|
||||
if (r) {
|
||||
r = WriteBinaryToFile(payload.GetString(), (char*)srcData, srcLen, n == Payload_Raw ? 0 : -1);
|
||||
if (!r) tip = "\r\n警告: 生成载荷失败!";
|
||||
} else {
|
||||
MessageBox("文件生成失败: \r\n" + strSeverFile, "提示", MB_ICONINFORMATION);
|
||||
}
|
||||
SAFE_DELETE_ARRAY(srcData);
|
||||
@@ -407,7 +483,7 @@ void CBuildDlg::OnBnClickedOk()
|
||||
}
|
||||
int size = m_SliderClientSize.GetPos() * 2.56 * 1024 * 1024;
|
||||
if (size > 0) {
|
||||
std::vector<char> padding(size, time(0)%256);
|
||||
std::vector<char> padding(size, time(0)%256);
|
||||
WriteBinaryToFile(strSeverFile.GetString(), padding.data(), size, -1);
|
||||
}
|
||||
MessageBox("生成成功! 文件位于:\r\n" + strSeverFile + tip, "提示", MB_ICONINFORMATION);
|
||||
@@ -497,27 +573,34 @@ BOOL CBuildDlg::OnInitDialog()
|
||||
::SetMenu(this->GetSafeHwnd(), m_MainMenu.GetSafeHmenu()); // 为窗口设置菜单
|
||||
::DrawMenuBar(this->GetSafeHwnd()); // 显示菜单
|
||||
|
||||
BOOL b = THIS_CFG.GetInt("settings", "RandomName", 0);
|
||||
if (b) {
|
||||
m_EditInstallDir.SetWindowTextA(m_sInstallDir = GenerateRandomName(5 + time(0) % 10));
|
||||
m_EditInstallName.SetWindowTextA(m_sInstallName = GenerateRandomName(5 + time(0) % 10));
|
||||
}
|
||||
SubMenu->CheckMenuItem(ID_RANDOM_NAME, b ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// 异常: OCX 属性页应返回 FALSE
|
||||
}
|
||||
|
||||
CString CBuildDlg::GetFilePath(CString type, CString filter, BOOL isOpen) {
|
||||
CComPtr<IShellFolder> spDesktop;
|
||||
HRESULT hr = SHGetDesktopFolder(&spDesktop);
|
||||
if (FAILED(hr)) {
|
||||
MessageBox("Explorer 未正确初始化! 请稍后再试。", "提示");
|
||||
return "";
|
||||
}
|
||||
// 过滤器:显示所有文件和特定类型文件(例如文本文件)
|
||||
CFileDialog fileDlg(isOpen, type, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, AfxGetMainWnd());
|
||||
int ret = 0;
|
||||
try {
|
||||
ret = fileDlg.DoModal();
|
||||
}
|
||||
catch (...) {
|
||||
MessageBox("文件对话框未成功打开! 请稍后再试。", "提示");
|
||||
return "";
|
||||
}
|
||||
CString CBuildDlg::GetFilePath(CString type, CString filter, BOOL isOpen)
|
||||
{
|
||||
CComPtr<IShellFolder> spDesktop;
|
||||
HRESULT hr = SHGetDesktopFolder(&spDesktop);
|
||||
if (FAILED(hr)) {
|
||||
MessageBox("Explorer 未正确初始化! 请稍后再试。", "提示");
|
||||
return "";
|
||||
}
|
||||
// 过滤器:显示所有文件和特定类型文件(例如文本文件)
|
||||
CFileDialog fileDlg(isOpen, type, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, AfxGetMainWnd());
|
||||
int ret = 0;
|
||||
try {
|
||||
ret = fileDlg.DoModal();
|
||||
} catch (...) {
|
||||
MessageBox("文件对话框未成功打开! 请稍后再试。", "提示");
|
||||
return "";
|
||||
}
|
||||
if (ret == IDOK) {
|
||||
CString name = fileDlg.GetPathName();
|
||||
return name;
|
||||
@@ -592,21 +675,135 @@ void CBuildDlg::OnClientRunasAdmin()
|
||||
void CBuildDlg::OnCbnSelchangeComboCompress()
|
||||
{
|
||||
m_ComboPayload.ShowWindow(m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC_AES ? SW_SHOW : SW_HIDE);
|
||||
m_StaticPayload.ShowWindow(m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC_AES ? SW_SHOW : SW_HIDE);
|
||||
m_StaticPayload.ShowWindow(m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC_AES ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
|
||||
BOOL CBuildDlg::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
TOOLTIPTEXTA* pTTT = (TOOLTIPTEXTA*)pNMHDR;
|
||||
UINT nID = pNMHDR->idFrom;
|
||||
if (pTTT->uFlags & TTF_IDISHWND) {
|
||||
if (pTTT->uFlags & TTF_IDISHWND) {
|
||||
// idFrom is actually the HWND of the tool
|
||||
nID = ::GetDlgCtrlID((HWND)nID);
|
||||
}
|
||||
if (nID == IDC_SLIDER_CLIENT_SIZE) {
|
||||
int size = m_SliderClientSize.GetPos() * 2.56;
|
||||
int size = m_SliderClientSize.GetPos() * 2.56;
|
||||
sprintf_s(pTTT->szText, "%dM", size);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void CBuildDlg::OnEnChangeEditInstallDir()
|
||||
{
|
||||
static bool bProcessing = false;
|
||||
if (bProcessing) return;
|
||||
bProcessing = true;
|
||||
|
||||
CString strText;
|
||||
GetDlgItemText(IDC_EDIT_INSTALL_DIR, strText);
|
||||
|
||||
// Windows 文件名非法字符: \ / : * ? " < > |
|
||||
LPCTSTR szInvalidChars = _T("\\/:*?\"<>|"); // 纯文件名
|
||||
|
||||
bool bModified = false;
|
||||
for (int i = strText.GetLength() - 1; i >= 0; i--) {
|
||||
if (_tcschr(szInvalidChars, strText[i]) != NULL) {
|
||||
strText.Delete(i);
|
||||
bModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bModified) {
|
||||
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_INSTALL_DIR);
|
||||
int nSel = pEdit->GetSel() & 0xFFFF; // 获取光标位置
|
||||
SetDlgItemText(IDC_EDIT_INSTALL_DIR, strText);
|
||||
pEdit->SetSel(nSel - 1, nSel - 1); // 恢复光标
|
||||
}
|
||||
|
||||
bProcessing = false;
|
||||
}
|
||||
|
||||
|
||||
void CBuildDlg::OnEnChangeEditInstallName()
|
||||
{
|
||||
static bool bProcessing = false;
|
||||
if (bProcessing) return;
|
||||
bProcessing = true;
|
||||
|
||||
CString strText;
|
||||
GetDlgItemText(IDC_EDIT_INSTALL_NAME, strText);
|
||||
|
||||
// Windows 文件名非法字符: \ / : * ? " < > |
|
||||
LPCTSTR szInvalidChars = _T("\\/:*?\"<>|"); // 纯文件名
|
||||
|
||||
bool bModified = false;
|
||||
for (int i = strText.GetLength() - 1; i >= 0; i--) {
|
||||
if (_tcschr(szInvalidChars, strText[i]) != NULL) {
|
||||
strText.Delete(i);
|
||||
bModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bModified) {
|
||||
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_INSTALL_NAME);
|
||||
int nSel = pEdit->GetSel() & 0xFFFF; // 获取光标位置
|
||||
SetDlgItemText(IDC_EDIT_INSTALL_NAME, strText);
|
||||
pEdit->SetSel(nSel - 1, nSel - 1); // 恢复光标
|
||||
}
|
||||
|
||||
bProcessing = false;
|
||||
}
|
||||
|
||||
|
||||
void CBuildDlg::OnEnKillfocusEditInstallDir()
|
||||
{
|
||||
CString strText;
|
||||
GetDlgItemText(IDC_EDIT_INSTALL_DIR, strText);
|
||||
|
||||
if (strText.IsEmpty()) return;
|
||||
|
||||
if (!IsValidFileName(strText)) {
|
||||
MessageBoxA(_T("文件名不合法,请检查:\n")
|
||||
_T("1. 不能包含 \\ / : * ? \" < > |\n")
|
||||
_T("2. 不能是系统保留名称 (CON, PRN 等)\n")
|
||||
_T("3. 不能以空格或点结尾"), "提示", MB_ICONWARNING);
|
||||
|
||||
GetDlgItem(IDC_EDIT_INSTALL_DIR)->SetFocus();
|
||||
((CEdit*)GetDlgItem(IDC_EDIT_INSTALL_DIR))->SetWindowTextA("");
|
||||
((CEdit*)GetDlgItem(IDC_EDIT_INSTALL_DIR))->SetSel(0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBuildDlg::OnEnKillfocusEditInstallName()
|
||||
{
|
||||
CString strText;
|
||||
GetDlgItemText(IDC_EDIT_INSTALL_NAME, strText);
|
||||
|
||||
if (strText.IsEmpty()) return;
|
||||
|
||||
if (!IsValidFileName(strText)) {
|
||||
MessageBoxA(_T("文件名不合法,请检查:\n")
|
||||
_T("1. 不能包含 \\ / : * ? \" < > |\n")
|
||||
_T("2. 不能是系统保留名称 (CON, PRN 等)\n")
|
||||
_T("3. 不能以空格或点结尾"), "提示", MB_ICONWARNING);
|
||||
|
||||
GetDlgItem(IDC_EDIT_INSTALL_NAME)->SetFocus();
|
||||
((CEdit*)GetDlgItem(IDC_EDIT_INSTALL_NAME))->SetWindowTextA("");
|
||||
((CEdit*)GetDlgItem(IDC_EDIT_INSTALL_NAME))->SetSel(0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBuildDlg::OnRandomName()
|
||||
{
|
||||
BOOL b = !THIS_CFG.GetInt("settings", "RandomName", 0);
|
||||
m_EditInstallDir.SetWindowTextA(m_sInstallDir = b ? GenerateRandomName(5 + time(0) % 10) : "");
|
||||
m_EditInstallName.SetWindowTextA(m_sInstallName = b ? GenerateRandomName(5 + time(0) % 10) : "");
|
||||
|
||||
CMenu* SubMenu = m_MainMenu.GetSubMenu(0);
|
||||
SubMenu->CheckMenuItem(ID_RANDOM_NAME, b ? MF_CHECKED : MF_UNCHECKED);
|
||||
THIS_CFG.SetInt("settings", "RandomName", b);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
CString GetFilePath(CString type, CString filter, BOOL isOpen = TRUE);
|
||||
BOOL OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult);
|
||||
BOOL OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult);
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
public:
|
||||
@@ -53,4 +53,13 @@ public:
|
||||
afx_msg void OnCbnSelchangeComboCompress();
|
||||
CStatic m_StaticPayload;
|
||||
CSliderCtrl m_SliderClientSize;
|
||||
CEdit m_EditInstallDir;
|
||||
CEdit m_EditInstallName;
|
||||
CString m_sInstallDir;
|
||||
CString m_sInstallName;
|
||||
afx_msg void OnEnChangeEditInstallDir();
|
||||
afx_msg void OnEnChangeEditInstallName();
|
||||
afx_msg void OnEnKillfocusEditInstallDir();
|
||||
afx_msg void OnEnKillfocusEditInstallName();
|
||||
afx_msg void OnRandomName();
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
IMPLEMENT_DYNAMIC(CDlgFileSend, CDialog)
|
||||
|
||||
CDlgFileSend::CDlgFileSend(CWnd* pParent, Server* IOCPServer, CONTEXT_OBJECT* ContextObject, BOOL sendFile)
|
||||
: DialogBase(CDlgFileSend::IDD, pParent, IOCPServer, ContextObject, IDI_File), m_bIsSending(sendFile)
|
||||
: DialogBase(CDlgFileSend::IDD, pParent, IOCPServer, ContextObject, IDI_File), m_bIsSending(sendFile)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,15 +20,15 @@ CDlgFileSend::~CDlgFileSend()
|
||||
|
||||
void CDlgFileSend::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
DDX_Control(pDX, IDC_PROGRESS_FILESEND, m_Progress);
|
||||
CDialog::DoDataExchange(pDX);
|
||||
DDX_Control(pDX, IDC_PROGRESS_FILESEND, m_Progress);
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CDlgFileSend, CDialog)
|
||||
ON_WM_CLOSE()
|
||||
ON_MESSAGE(WM_UPDATEFILEPROGRESS, &CDlgFileSend::OnUpdateFileProgress)
|
||||
ON_MESSAGE(WM_FINISHFILESEND, &CDlgFileSend::OnFinishFileSend)
|
||||
ON_WM_CLOSE()
|
||||
ON_MESSAGE(WM_UPDATEFILEPROGRESS, &CDlgFileSend::OnUpdateFileProgress)
|
||||
ON_MESSAGE(WM_FINISHFILESEND, &CDlgFileSend::OnFinishFileSend)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -38,87 +38,91 @@ std::string GetHMAC(int offset);
|
||||
|
||||
void RecvData(void* ptr)
|
||||
{
|
||||
FileChunkPacket* pkt = (FileChunkPacket*)ptr;
|
||||
FileChunkPacket* pkt = (FileChunkPacket*)ptr;
|
||||
}
|
||||
|
||||
void CDlgFileSend::OnReceiveComplete(void) {
|
||||
LPBYTE szBuffer = m_ContextObject->InDeCompressedBuffer.GetBuffer();
|
||||
unsigned len = m_ContextObject->InDeCompressedBuffer.GetBufferLen();
|
||||
std::string hash = GetPwdHash(), hmac = GetHMAC(100);
|
||||
CONNECT_ADDRESS addr = { 0 };
|
||||
memcpy(addr.pwdHash, hash.c_str(), min(hash.length(), sizeof(addr.pwdHash)));
|
||||
int n = RecvFileChunk((char*)szBuffer, len, &addr, RecvData, hash, hmac);
|
||||
if (n) {
|
||||
Mprintf("RecvFileChunk failed: %d. hash: %s, hmac: %s\n", n, hash.c_str(), hmac.c_str());
|
||||
}
|
||||
BYTE* name = szBuffer + sizeof(FileChunkPacket);
|
||||
FileChunkPacket* chunk = (FileChunkPacket*)szBuffer;
|
||||
UpdateProgress(CString((char*)name, chunk->nameLength), chunk);
|
||||
void CDlgFileSend::OnReceiveComplete(void)
|
||||
{
|
||||
LPBYTE szBuffer = m_ContextObject->InDeCompressedBuffer.GetBuffer();
|
||||
unsigned len = m_ContextObject->InDeCompressedBuffer.GetBufferLen();
|
||||
std::string hash = GetPwdHash(), hmac = GetHMAC(100);
|
||||
CONNECT_ADDRESS addr = { 0 };
|
||||
memcpy(addr.pwdHash, hash.c_str(), min(hash.length(), sizeof(addr.pwdHash)));
|
||||
int n = RecvFileChunk((char*)szBuffer, len, &addr, RecvData, hash, hmac);
|
||||
if (n) {
|
||||
Mprintf("RecvFileChunk failed: %d. hash: %s, hmac: %s\n", n, hash.c_str(), hmac.c_str());
|
||||
}
|
||||
BYTE* name = szBuffer + sizeof(FileChunkPacket);
|
||||
FileChunkPacket* chunk = (FileChunkPacket*)szBuffer;
|
||||
UpdateProgress(CString((char*)name, chunk->nameLength), chunk);
|
||||
}
|
||||
|
||||
void CDlgFileSend::UpdateProgress(CString file, const FileChunkPacket *chunk) {
|
||||
PostMessageA(WM_UPDATEFILEPROGRESS, (WPARAM)new CString(file), (LPARAM)new FileChunkPacket(*chunk));
|
||||
void CDlgFileSend::UpdateProgress(CString file, const FileChunkPacket *chunk)
|
||||
{
|
||||
PostMessageA(WM_UPDATEFILEPROGRESS, (WPARAM)new CString(file), (LPARAM)new FileChunkPacket(*chunk));
|
||||
}
|
||||
|
||||
void CDlgFileSend::FinishFileSend(BOOL succeed) {
|
||||
PostMessageA(WM_FINISHFILESEND, NULL, (LPARAM)succeed);
|
||||
void CDlgFileSend::FinishFileSend(BOOL succeed)
|
||||
{
|
||||
PostMessageA(WM_FINISHFILESEND, NULL, (LPARAM)succeed);
|
||||
}
|
||||
|
||||
LRESULT CDlgFileSend::OnUpdateFileProgress(WPARAM wParam, LPARAM lParam) {
|
||||
CString* pFile = (CString*)wParam;
|
||||
FileChunkPacket* pChunk = (FileChunkPacket*)lParam;
|
||||
LRESULT CDlgFileSend::OnUpdateFileProgress(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CString* pFile = (CString*)wParam;
|
||||
FileChunkPacket* pChunk = (FileChunkPacket*)lParam;
|
||||
|
||||
CString status;
|
||||
double percent = pChunk->fileSize > 0 ? double(pChunk->offset) / pChunk->fileSize * 100.0 : 100.0;
|
||||
m_bIsSending ?
|
||||
status.Format("发送文件(%d/%d): %.2f%%", 1 + pChunk->fileIndex, pChunk->totalNum, percent):
|
||||
status.Format("接收文件(%d/%d): %.2f%%", 1 + pChunk->fileIndex, pChunk->totalNum, percent);
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, status);
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENT_FILE, *pFile);
|
||||
m_Progress.SetPos(percent);
|
||||
ShowWindow(SW_SHOW);
|
||||
CString status;
|
||||
double percent = pChunk->fileSize > 0 ? double(pChunk->offset) / pChunk->fileSize * 100.0 : 100.0;
|
||||
m_bIsSending ?
|
||||
status.Format("发送文件(%d/%d): %.2f%%", 1 + pChunk->fileIndex, pChunk->totalNum, percent):
|
||||
status.Format("接收文件(%d/%d): %.2f%%", 1 + pChunk->fileIndex, pChunk->totalNum, percent);
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, status);
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENT_FILE, *pFile);
|
||||
m_Progress.SetPos(percent);
|
||||
ShowWindow(SW_SHOW);
|
||||
|
||||
delete pChunk;
|
||||
delete pFile;
|
||||
return 0;
|
||||
delete pChunk;
|
||||
delete pFile;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CDlgFileSend::OnFinishFileSend(WPARAM wParam, LPARAM lParam) {
|
||||
BOOL success = (BOOL)lParam;
|
||||
m_bIsSending ?
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, success ? "文件发送完成" : "文件发送失败"):
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, success ? "文件接收完成" : "文件接收失败");
|
||||
if (success)
|
||||
m_Progress.SetPos(100);
|
||||
ShowWindow(SW_SHOW);
|
||||
LRESULT CDlgFileSend::OnFinishFileSend(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
BOOL success = (BOOL)lParam;
|
||||
m_bIsSending ?
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, success ? "文件发送完成" : "文件发送失败"):
|
||||
SetDlgItemTextA(IDC_STATIC_CURRENTINDEX, success ? "文件接收完成" : "文件接收失败");
|
||||
if (success)
|
||||
m_Progress.SetPos(100);
|
||||
ShowWindow(SW_SHOW);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL CDlgFileSend::OnInitDialog()
|
||||
{
|
||||
DialogBase::OnInitDialog();
|
||||
DialogBase::OnInitDialog();
|
||||
|
||||
SetIcon(m_hIcon, FALSE);
|
||||
SetIcon(m_hIcon, FALSE);
|
||||
|
||||
SetWindowTextA(m_bIsSending ? "发送文件" : "接收文件");
|
||||
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
||||
if (pSysMenu != nullptr)
|
||||
{
|
||||
pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
|
||||
}
|
||||
SetWindowTextA(m_bIsSending ? "发送文件" : "接收文件");
|
||||
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
||||
if (pSysMenu != nullptr) {
|
||||
pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CDlgFileSend::OnClose()
|
||||
{
|
||||
CancelIO();
|
||||
// 等待数据处理完毕
|
||||
if (IsProcessing()) {
|
||||
ShowWindow(SW_HIDE);
|
||||
return;
|
||||
}
|
||||
CancelIO();
|
||||
// 等待数据处理完毕
|
||||
if (IsProcessing()) {
|
||||
ShowWindow(SW_HIDE);
|
||||
return;
|
||||
}
|
||||
|
||||
DialogBase::OnClose();
|
||||
DialogBase::OnClose();
|
||||
}
|
||||
|
||||
@@ -12,29 +12,29 @@
|
||||
|
||||
class CDlgFileSend : public DialogBase
|
||||
{
|
||||
DECLARE_DYNAMIC(CDlgFileSend)
|
||||
DECLARE_DYNAMIC(CDlgFileSend)
|
||||
|
||||
public:
|
||||
CDlgFileSend(CWnd* pParent = NULL, Server* IOCPServer = NULL,
|
||||
CONTEXT_OBJECT* ContextObject = NULL, BOOL sendFile = TRUE);
|
||||
virtual ~CDlgFileSend();
|
||||
void OnReceiveComplete(void);
|
||||
void UpdateProgress(CString file, const FileChunkPacket *chunk);
|
||||
void FinishFileSend(BOOL succeed);
|
||||
CDlgFileSend(CWnd* pParent = NULL, Server* IOCPServer = NULL,
|
||||
CONTEXT_OBJECT* ContextObject = NULL, BOOL sendFile = TRUE);
|
||||
virtual ~CDlgFileSend();
|
||||
void OnReceiveComplete(void);
|
||||
void UpdateProgress(CString file, const FileChunkPacket *chunk);
|
||||
void FinishFileSend(BOOL succeed);
|
||||
|
||||
BOOL m_bIsSending;
|
||||
enum { IDD = IDD_DIALOG_FILESEND };
|
||||
BOOL m_bIsSending;
|
||||
enum { IDD = IDD_DIALOG_FILESEND };
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
afx_msg LRESULT OnUpdateFileProgress(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnFinishFileSend(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnUpdateFileProgress(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg LRESULT OnFinishFileSend(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
public:
|
||||
CProgressCtrl m_Progress;
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnClose();
|
||||
CProgressCtrl m_Progress;
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnClose();
|
||||
};
|
||||
|
||||
@@ -43,8 +43,9 @@ std::string GetHMAC(int offset)
|
||||
return hmac;
|
||||
}
|
||||
|
||||
void SetHMAC(const std::string str, int offset) {
|
||||
Validation* v = (Validation*)(g_MasterID + offset);
|
||||
void SetHMAC(const std::string str, int offset)
|
||||
{
|
||||
Validation* v = (Validation*)(g_MasterID + offset);
|
||||
std::string hmac(v->Checksum, 16);
|
||||
if (hmac.c_str()[0] == 0) {
|
||||
memcpy(v->Checksum, str.c_str(), min(16, str.length()));
|
||||
@@ -151,12 +152,12 @@ void CPasswordDlg::OnCbnSelchangeComboBind()
|
||||
std::string hardwareID = CMy2015RemoteDlg::GetHardwareID(m_nBindType);
|
||||
m_sDeviceID = getFixedLengthID(hashSHA256(hardwareID)).c_str();
|
||||
m_EditDeviceID.SetWindowTextA(m_sDeviceID);
|
||||
auto master = THIS_CFG.GetStr("settings", "master", "");
|
||||
auto master = THIS_CFG.GetStr("settings", "master", "");
|
||||
if (m_nBindType == 1) {
|
||||
MessageBoxA("请确认是否正确设置公网地址(IP或域名)?\r\n"
|
||||
"绑定IP后主控只能使用指定IP,绑定域名后\r\n"
|
||||
"主控只能使用指定域名。当前公网地址: \r\n"
|
||||
+ CString(master.empty() ? "未设置" : master.c_str()), "提示", MB_OK | MB_ICONWARNING);
|
||||
"主控只能使用指定域名。当前公网地址: \r\n"
|
||||
+ CString(master.empty() ? "未设置" : master.c_str()), "提示", MB_OK | MB_ICONWARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1345,20 +1345,20 @@ void CFileManagerDlg::OnLocalCompress()
|
||||
if (m_list_local.GetItemData(nItem)) {
|
||||
file += '\\';
|
||||
}
|
||||
paths.push_back(file.GetBuffer(0));
|
||||
paths.push_back(file.GetBuffer(0));
|
||||
}
|
||||
std::string target = m_Local_Path.GetString() + ToPekingDateTime(0) + ".zsta";
|
||||
std::string target = m_Local_Path.GetString() + ToPekingDateTime(0) + ".zsta";
|
||||
zsta::Error err = zsta::CZstdArchive::Compress(paths, target);
|
||||
if (err != zsta::Error::Success) {
|
||||
::MessageBoxA(m_hWnd, "压缩失败: " + CString(zsta::CZstdArchive::GetErrorString(err)),
|
||||
"错误", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
else {
|
||||
::MessageBoxA(m_hWnd, "压缩失败: " + CString(zsta::CZstdArchive::GetErrorString(err)),
|
||||
"错误", MB_OK | MB_ICONERROR);
|
||||
} else {
|
||||
FixedLocalFileList(".");
|
||||
}
|
||||
}
|
||||
|
||||
bool HasZstaExtension(const std::string& path) {
|
||||
bool HasZstaExtension(const std::string& path)
|
||||
{
|
||||
if (path.size() < 5) return false;
|
||||
std::string ext = path.substr(path.size() - 5);
|
||||
// 转小写比较
|
||||
@@ -1366,7 +1366,8 @@ bool HasZstaExtension(const std::string& path) {
|
||||
return ext == ".zsta";
|
||||
}
|
||||
|
||||
std::string GetExtractDir(const std::string& archivePath) {
|
||||
std::string GetExtractDir(const std::string& archivePath)
|
||||
{
|
||||
if (archivePath.size() >= 5) {
|
||||
std::string ext = archivePath.substr(archivePath.size() - 5);
|
||||
for (char& c : ext) c = tolower(c);
|
||||
@@ -1379,7 +1380,7 @@ std::string GetExtractDir(const std::string& archivePath) {
|
||||
|
||||
void CFileManagerDlg::OnLocalUnCompress()
|
||||
{
|
||||
BOOL needRefresh = FALSE;
|
||||
BOOL needRefresh = FALSE;
|
||||
POSITION pos = m_list_local.GetFirstSelectedItemPosition();
|
||||
while (pos) {
|
||||
int nItem = m_list_local.GetNextSelectedItem(pos);
|
||||
@@ -1387,17 +1388,15 @@ void CFileManagerDlg::OnLocalUnCompress()
|
||||
// 如果是目录
|
||||
if (m_list_local.GetItemData(nItem)) {
|
||||
continue;
|
||||
}
|
||||
else if (HasZstaExtension(file.GetString())){
|
||||
} else if (HasZstaExtension(file.GetString())) {
|
||||
std::string path(file.GetBuffer(0));
|
||||
std::string destDir = GetExtractDir(path);
|
||||
zsta::Error err = zsta::CZstdArchive::Extract(path, destDir);
|
||||
if (err != zsta::Error::Success) {
|
||||
::MessageBoxA(m_hWnd, "解压失败: " + CString(zsta::CZstdArchive::GetErrorString(err)),
|
||||
"错误", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
else {
|
||||
needRefresh = TRUE;
|
||||
"错误", MB_OK | MB_ICONERROR);
|
||||
} else {
|
||||
needRefresh = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1456,7 +1455,7 @@ void CFileManagerDlg::OnRemoteCompress()
|
||||
if (paths.size() <= 1) {
|
||||
::MessageBoxA(m_hWnd, "请先选择要压缩的文件或文件夹!", "提示", MB_OK | MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto pathsMultiString = BuildMultiStringPath(paths);
|
||||
BYTE* bPacket = (BYTE*)LocalAlloc(LPTR, pathsMultiString.size() + 1);
|
||||
if (bPacket) {
|
||||
@@ -1477,16 +1476,15 @@ void CFileManagerDlg::OnRemoteUnCompress()
|
||||
// 如果是目录
|
||||
if (m_list_remote.GetItemData(nItem)) {
|
||||
continue;
|
||||
}
|
||||
else if (HasZstaExtension(file.GetString())) {
|
||||
paths.push_back(file.GetBuffer(0));
|
||||
} else if (HasZstaExtension(file.GetString())) {
|
||||
paths.push_back(file.GetBuffer(0));
|
||||
}
|
||||
}
|
||||
if (paths.empty()) {
|
||||
::MessageBoxA(m_hWnd, "请先选择要解压的.zsta文件!", "提示", MB_OK | MB_ICONWARNING);
|
||||
::MessageBoxA(m_hWnd, "请先选择要解压的.zsta文件!", "提示", MB_OK | MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
auto pathsMultiString = BuildMultiStringPath(paths);
|
||||
}
|
||||
auto pathsMultiString = BuildMultiStringPath(paths);
|
||||
BYTE* bPacket = (BYTE*)LocalAlloc(LPTR, pathsMultiString.size() + 1);
|
||||
if (bPacket) {
|
||||
memcpy(bPacket + 1, pathsMultiString.data(), pathsMultiString.size());
|
||||
@@ -2190,8 +2188,7 @@ void CFileManagerDlg::OnFilemangerCompress()
|
||||
GetCursorPos(&pt);
|
||||
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
|
||||
OnLocalCompress();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
OnRemoteCompress();
|
||||
}
|
||||
}
|
||||
@@ -2203,8 +2200,7 @@ void CFileManagerDlg::OnFilemangerUncompress()
|
||||
GetCursorPos(&pt);
|
||||
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
|
||||
OnLocalUnCompress();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
OnRemoteUnCompress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
#define ClientContext CONTEXT_OBJECT
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSizeHigh;
|
||||
DWORD dwSizeLow;
|
||||
} FILESIZE;
|
||||
typedef struct {
|
||||
DWORD dwSizeHigh;
|
||||
DWORD dwSizeLow;
|
||||
} FILESIZE;
|
||||
|
||||
#define m_DeCompressionBuffer InDeCompressedBuffer
|
||||
|
||||
|
||||
@@ -10,37 +10,37 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFileTransferModeDlg dialog
|
||||
|
||||
class CFileTransferModeDlg : public CDialog
|
||||
{
|
||||
class CFileTransferModeDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CString m_strFileName;
|
||||
CFileTransferModeDlg(CWnd* pParent = NULL); // standard constructor
|
||||
public:
|
||||
CString m_strFileName;
|
||||
CFileTransferModeDlg(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CFileTransferModeDlg)
|
||||
enum { IDD = IDD_TRANSFERMODE_DLG };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
//{{AFX_DATA(CFileTransferModeDlg)
|
||||
enum { IDD = IDD_TRANSFERMODE_DLG };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CFileTransferModeDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CFileTransferModeDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CFileTransferModeDlg)
|
||||
afx_msg void OnEndDialog(UINT id);
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CFileTransferModeDlg)
|
||||
afx_msg void OnEndDialog(UINT id);
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
@@ -13,48 +13,48 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CKeyBoardDlg dialog
|
||||
|
||||
class CKeyBoardDlg : public DialogBase
|
||||
{
|
||||
class CKeyBoardDlg : public DialogBase
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
void OnReceiveComplete();
|
||||
CKeyBoardDlg(CWnd* pParent = NULL, Server* pIOCPServer = NULL, ClientContext *pContext = NULL); // standard constructor
|
||||
public:
|
||||
void OnReceiveComplete();
|
||||
CKeyBoardDlg(CWnd* pParent = NULL, Server* pIOCPServer = NULL, ClientContext *pContext = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CKeyBoardDlg)
|
||||
enum { IDD = IDD_DLG_KEYBOARD };
|
||||
CEdit m_edit;
|
||||
//}}AFX_DATA
|
||||
//{{AFX_DATA(CKeyBoardDlg)
|
||||
enum { IDD = IDD_DLG_KEYBOARD };
|
||||
CEdit m_edit;
|
||||
//}}AFX_DATA
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CKeyBoardDlg)
|
||||
public:
|
||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual void PostNcDestroy();
|
||||
//}}AFX_VIRTUAL
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CKeyBoardDlg)
|
||||
public:
|
||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual void PostNcDestroy();
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
bool m_bIsOfflineRecord;
|
||||
protected:
|
||||
bool m_bIsOfflineRecord;
|
||||
|
||||
void AddKeyBoardData();
|
||||
void UpdateTitle();
|
||||
void ResizeEdit();
|
||||
bool SaveRecord();
|
||||
void AddKeyBoardData();
|
||||
void UpdateTitle();
|
||||
void ResizeEdit();
|
||||
bool SaveRecord();
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CKeyBoardDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CKeyBoardDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
||||
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
@@ -232,8 +232,8 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
||||
CDialog::OnInitDialog();
|
||||
SetIcon(m_hIcon,FALSE);
|
||||
DragAcceptFiles(TRUE);
|
||||
ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
|
||||
ChangeWindowMessageFilter(0x0049, MSGFLT_ADD);
|
||||
ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
|
||||
ChangeWindowMessageFilter(0x0049, MSGFLT_ADD);
|
||||
|
||||
PrepareDrawing(m_BitmapInfor_Full);
|
||||
|
||||
@@ -258,16 +258,16 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
||||
SysMenu->AppendMenu(MF_STRING, IDM_SCREEN_1080P, "限制为1080P(&4)");
|
||||
SysMenu->AppendMenu(MF_SEPARATOR);
|
||||
|
||||
CMenu fpsMenu;
|
||||
if (fpsMenu.CreatePopupMenu()) {
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_15, "最大帧率FPS:15");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_20, "最大帧率FPS:20");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_25, "最大帧率FPS:25");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_30, "最大帧率FPS:30");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_UNLIMITED, "最大帧率无限制");
|
||||
SysMenu->AppendMenuA(MF_STRING | MF_POPUP, (UINT_PTR)fpsMenu.Detach(), _T("帧率设置"));
|
||||
}
|
||||
CMenu fpsMenu;
|
||||
if (fpsMenu.CreatePopupMenu()) {
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_15, "最大帧率FPS:15");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_20, "最大帧率FPS:20");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_25, "最大帧率FPS:25");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_30, "最大帧率FPS:30");
|
||||
fpsMenu.AppendMenu(MF_STRING, IDM_FPS_UNLIMITED, "最大帧率无限制");
|
||||
SysMenu->AppendMenuA(MF_STRING | MF_POPUP, (UINT_PTR)fpsMenu.Detach(), _T("帧率设置"));
|
||||
}
|
||||
|
||||
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen");
|
||||
SysMenu->EnableMenuItem(IDM_SWITCHSCREEN, all ? MF_ENABLED : MF_GRAYED);
|
||||
@@ -322,7 +322,8 @@ VOID CScreenSpyDlg::OnClose()
|
||||
DialogBase::OnClose();
|
||||
}
|
||||
|
||||
afx_msg LRESULT CScreenSpyDlg::OnDisconnect(WPARAM wParam, LPARAM lParam) {
|
||||
afx_msg LRESULT CScreenSpyDlg::OnDisconnect(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
m_bConnected = FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -685,18 +686,22 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_SCREEN_1080P: {
|
||||
const int strategy = 0;
|
||||
BYTE cmd[16] = { CMD_SCREEN_SIZE, (BYTE)strategy };
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
break;
|
||||
}
|
||||
case IDM_SCREEN_1080P: {
|
||||
const int strategy = 0;
|
||||
BYTE cmd[16] = { CMD_SCREEN_SIZE, (BYTE)strategy };
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_FPS_10: case IDM_FPS_15: case IDM_FPS_20:
|
||||
case IDM_FPS_25: case IDM_FPS_30: case IDM_FPS_UNLIMITED: {
|
||||
case IDM_FPS_10:
|
||||
case IDM_FPS_15:
|
||||
case IDM_FPS_20:
|
||||
case IDM_FPS_25:
|
||||
case IDM_FPS_30:
|
||||
case IDM_FPS_UNLIMITED: {
|
||||
int fps = 10 + (nID - IDM_FPS_10) * 5;
|
||||
BYTE bToken[2] = { CMD_FPS, nID == IDM_FPS_UNLIMITED ? 255 : fps };
|
||||
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
||||
BYTE bToken[2] = { CMD_FPS, nID == IDM_FPS_UNLIMITED ? 255 : fps };
|
||||
m_ContextObject->Send2Client(bToken, sizeof(bToken));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -750,9 +755,9 @@ void CScreenSpyDlg::OnTimer(UINT_PTR nIDEvent)
|
||||
SetTextColor(m_hFullDC, RGB(0xff, 0x00, 0x00));
|
||||
TextOut(m_hFullDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
|
||||
}
|
||||
if (nIDEvent == 1 && m_bFullScreen && m_pToolbar) {
|
||||
m_pToolbar->CheckMousePosition();
|
||||
}
|
||||
if (nIDEvent == 1 && m_bFullScreen && m_pToolbar) {
|
||||
m_pToolbar->CheckMousePosition();
|
||||
}
|
||||
CDialog::OnTimer(nIDEvent);
|
||||
}
|
||||
|
||||
@@ -778,21 +783,21 @@ BOOL CScreenSpyDlg::PreTranslateMessage(MSG* pMsg)
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
if (pMsg->message == WM_KEYDOWN && m_bFullScreen) {
|
||||
// Ctrl+Alt+Home 退出全屏(备用)
|
||||
if (pMsg->wParam == VK_HOME &&
|
||||
(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
(GetKeyState(VK_MENU) & 0x8000)) {
|
||||
LeaveFullScreen();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (pMsg->message == WM_KEYDOWN && m_bFullScreen) {
|
||||
// Ctrl+Alt+Home 退出全屏(备用)
|
||||
if (pMsg->wParam == VK_HOME &&
|
||||
(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
(GetKeyState(VK_MENU) & 0x8000)) {
|
||||
LeaveFullScreen();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (pMsg->wParam != VK_LWIN && pMsg->wParam != VK_RWIN) {
|
||||
SendScaledMouseMessage(pMsg, true);
|
||||
}
|
||||
if (pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_F4) {
|
||||
return TRUE; // 屏蔽 Alt + F4
|
||||
}
|
||||
if (pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_F4) {
|
||||
return TRUE; // 屏蔽 Alt + F4
|
||||
}
|
||||
if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
|
||||
return TRUE;// 屏蔽Enter和ESC关闭对话
|
||||
break;
|
||||
@@ -1032,13 +1037,13 @@ void CScreenSpyDlg::EnterFullScreen()
|
||||
SetWindowPos(&CWnd::wndTop, rcMonitor.left, rcMonitor.top, rcMonitor.right - rcMonitor.left,
|
||||
rcMonitor.bottom - rcMonitor.top, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
if (!m_pToolbar) {
|
||||
m_pToolbar = new CToolbarDlg(this);
|
||||
m_pToolbar->Create(IDD_TOOLBAR_DLG, this);
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
int cy = GetSystemMetrics(SM_CYSCREEN);
|
||||
m_pToolbar->SetWindowPos(&wndTopMost, 0, -40, cx, 40, SWP_HIDEWINDOW);
|
||||
}
|
||||
if (!m_pToolbar) {
|
||||
m_pToolbar = new CToolbarDlg(this);
|
||||
m_pToolbar->Create(IDD_TOOLBAR_DLG, this);
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
int cy = GetSystemMetrics(SM_CYSCREEN);
|
||||
m_pToolbar->SetWindowPos(&wndTopMost, 0, -40, cx, 40, SWP_HIDEWINDOW);
|
||||
}
|
||||
|
||||
// 7. 标记全屏模式
|
||||
m_bFullScreen = true;
|
||||
@@ -1052,11 +1057,11 @@ bool CScreenSpyDlg::LeaveFullScreen()
|
||||
{
|
||||
if (m_bFullScreen) {
|
||||
KillTimer(1);
|
||||
if (m_pToolbar) {
|
||||
m_pToolbar->DestroyWindow();
|
||||
delete m_pToolbar;
|
||||
m_pToolbar = nullptr;
|
||||
}
|
||||
if (m_pToolbar) {
|
||||
m_pToolbar->DestroyWindow();
|
||||
delete m_pToolbar;
|
||||
m_pToolbar = nullptr;
|
||||
}
|
||||
|
||||
// 1. 恢复窗口样式
|
||||
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
|
||||
@@ -1150,24 +1155,24 @@ void CScreenSpyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
|
||||
}
|
||||
}
|
||||
|
||||
void CScreenSpyDlg::UpdateCtrlStatus(BOOL ctrl) {
|
||||
m_bIsCtrl = ctrl;
|
||||
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
||||
void CScreenSpyDlg::UpdateCtrlStatus(BOOL ctrl)
|
||||
{
|
||||
m_bIsCtrl = ctrl;
|
||||
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, m_bIsCtrl ? (LONG_PTR)m_hRemoteCursor : (LONG_PTR)LoadCursor(NULL, IDC_NO));
|
||||
}
|
||||
|
||||
// 将多个路径组合成单\0分隔的char数组
|
||||
// 格式: "path1\0path2\0path3\0"
|
||||
std::vector<char> BuildMultiStringPath(const std::vector<std::string>& paths)
|
||||
{
|
||||
std::vector<char> result;
|
||||
std::vector<char> result;
|
||||
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
result.insert(result.end(), path.begin(), path.end());
|
||||
result.push_back('\0');
|
||||
}
|
||||
for (const auto& path : paths) {
|
||||
result.insert(result.end(), path.begin(), path.end());
|
||||
result.push_back('\0');
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void CScreenSpyDlg::OnDropFiles(HDROP hDropInfo)
|
||||
@@ -1175,8 +1180,7 @@ void CScreenSpyDlg::OnDropFiles(HDROP hDropInfo)
|
||||
if (m_bIsCtrl && m_bConnected) {
|
||||
UINT nFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
|
||||
std::vector<std::string> list;
|
||||
for (UINT i = 0; i < nFiles; i++)
|
||||
{
|
||||
for (UINT i = 0; i < nFiles; i++) {
|
||||
TCHAR szPath[MAX_PATH];
|
||||
DragQueryFile(hDropInfo, i, szPath, MAX_PATH);
|
||||
list.push_back(szPath);
|
||||
@@ -1198,7 +1202,7 @@ void CScreenSpyDlg::OnDropFiles(HDROP hDropInfo)
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
}
|
||||
|
||||
DragFinish(hDropInfo);
|
||||
DragFinish(hDropInfo);
|
||||
|
||||
CDialogBase::OnDropFiles(hDropInfo);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ extern "C"
|
||||
class CScreenSpyDlg : public DialogBase
|
||||
{
|
||||
DECLARE_DYNAMIC(CScreenSpyDlg)
|
||||
CToolbarDlg* m_pToolbar = nullptr;
|
||||
CToolbarDlg* m_pToolbar = nullptr;
|
||||
CMy2015RemoteDlg* m_pParent = nullptr;
|
||||
|
||||
public:
|
||||
@@ -127,9 +127,10 @@ public:
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
|
||||
afx_msg LRESULT OnDisconnect(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg void OnExitFullscreen() {
|
||||
afx_msg void OnExitFullscreen()
|
||||
{
|
||||
LeaveFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
||||
|
||||
@@ -112,8 +112,7 @@ protected:
|
||||
m_bShouldUnmask = TRUE;
|
||||
std::string clientIP = getXForwardedFor(str);
|
||||
if (!clientIP.empty()) peer = clientIP;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_bShouldUnmask = FALSE;
|
||||
}
|
||||
if (nullptr == m_Masker) {
|
||||
|
||||
@@ -15,7 +15,7 @@ static void WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
|
||||
static void WINAPI ServiceCtrlHandler(DWORD ctrlCode);
|
||||
|
||||
BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
|
||||
char* exePath, size_t exePathSize)
|
||||
char* exePath, size_t exePathSize)
|
||||
{
|
||||
*registered = FALSE;
|
||||
*running = FALSE;
|
||||
@@ -31,9 +31,9 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
|
||||
|
||||
// 打开服务
|
||||
SC_HANDLE hService = OpenServiceA(
|
||||
hSCM,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
|
||||
hSCM,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
|
||||
if (!hService) {
|
||||
CloseServiceHandle(hSCM);
|
||||
return FALSE; // 未注册
|
||||
@@ -46,11 +46,11 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
|
||||
DWORD bytesNeeded = 0;
|
||||
memset(&ssp, 0, sizeof(ssp));
|
||||
if (QueryServiceStatusEx(
|
||||
hService,
|
||||
SC_STATUS_PROCESS_INFO,
|
||||
(LPBYTE)&ssp,
|
||||
sizeof(SERVICE_STATUS_PROCESS),
|
||||
&bytesNeeded)) {
|
||||
hService,
|
||||
SC_STATUS_PROCESS_INFO,
|
||||
(LPBYTE)&ssp,
|
||||
sizeof(SERVICE_STATUS_PROCESS),
|
||||
&bytesNeeded)) {
|
||||
*running = (ssp.dwCurrentState == SERVICE_RUNNING);
|
||||
}
|
||||
|
||||
@@ -190,9 +190,9 @@ static void WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
|
||||
Mprintf("ServiceMain() called");
|
||||
|
||||
g_StatusHandle = RegisterServiceCtrlHandler(
|
||||
SERVER_SERVICE_NAME,
|
||||
ServiceCtrlHandler
|
||||
);
|
||||
SERVER_SERVICE_NAME,
|
||||
ServiceCtrlHandler
|
||||
);
|
||||
|
||||
if (g_StatusHandle == NULL) {
|
||||
Mprintf("RegisterServiceCtrlHandler failed");
|
||||
@@ -318,10 +318,10 @@ DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam)
|
||||
BOOL ServerService_Install(void)
|
||||
{
|
||||
SC_HANDLE schSCManager = OpenSCManager(
|
||||
NULL,
|
||||
NULL,
|
||||
SC_MANAGER_ALL_ACCESS
|
||||
);
|
||||
NULL,
|
||||
NULL,
|
||||
SC_MANAGER_ALL_ACCESS
|
||||
);
|
||||
|
||||
if (schSCManager == NULL) {
|
||||
Mprintf("ERROR: OpenSCManager failed (%d)\n", (int)GetLastError());
|
||||
@@ -345,16 +345,16 @@ BOOL ServerService_Install(void)
|
||||
Mprintf("Executable path: %s\n", szPathWithArg);
|
||||
|
||||
SC_HANDLE schService = CreateServiceA(
|
||||
schSCManager,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVER_SERVICE_DISPLAY,
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
szPathWithArg,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
);
|
||||
schSCManager,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVER_SERVICE_DISPLAY,
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
szPathWithArg,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
);
|
||||
|
||||
if (schService == NULL) {
|
||||
DWORD err = GetLastError();
|
||||
@@ -366,11 +366,9 @@ BOOL ServerService_Install(void)
|
||||
CloseServiceHandle(schService);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (err == ERROR_ACCESS_DENIED) {
|
||||
} else if (err == ERROR_ACCESS_DENIED) {
|
||||
Mprintf("ERROR: Access denied. Please run as Administrator\n");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("ERROR: CreateService failed (%d)\n", (int)err);
|
||||
}
|
||||
CloseServiceHandle(schSCManager);
|
||||
@@ -395,19 +393,16 @@ BOOL ServerService_Install(void)
|
||||
if (QueryServiceStatus(schService, &status)) {
|
||||
if (status.dwCurrentState == SERVICE_RUNNING) {
|
||||
Mprintf("SUCCESS: Service is running\n");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("WARNING: Service state: %d\n", (int)status.dwCurrentState);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
Mprintf("INFO: Service is already running\n");
|
||||
err = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("WARNING: StartService failed (%d)\n", (int)err);
|
||||
}
|
||||
}
|
||||
@@ -420,10 +415,10 @@ BOOL ServerService_Install(void)
|
||||
BOOL ServerService_Uninstall(void)
|
||||
{
|
||||
SC_HANDLE schSCManager = OpenSCManager(
|
||||
NULL,
|
||||
NULL,
|
||||
SC_MANAGER_ALL_ACCESS
|
||||
);
|
||||
NULL,
|
||||
NULL,
|
||||
SC_MANAGER_ALL_ACCESS
|
||||
);
|
||||
|
||||
if (schSCManager == NULL) {
|
||||
Mprintf("ERROR: OpenSCManager failed (%d)\n", (int)GetLastError());
|
||||
@@ -431,10 +426,10 @@ BOOL ServerService_Uninstall(void)
|
||||
}
|
||||
|
||||
SC_HANDLE schService = OpenServiceA(
|
||||
schSCManager,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS
|
||||
);
|
||||
schSCManager,
|
||||
SERVER_SERVICE_NAME,
|
||||
SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS
|
||||
);
|
||||
|
||||
if (schService == NULL) {
|
||||
Mprintf("ERROR: OpenService failed (%d)\n", (int)GetLastError());
|
||||
@@ -455,14 +450,12 @@ BOOL ServerService_Uninstall(void)
|
||||
Mprintf(".");
|
||||
Sleep(1000);
|
||||
waitCount++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Mprintf("\n");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_NOT_ACTIVE) {
|
||||
Mprintf("WARNING: Failed to stop service (%d)\n", (int)err);
|
||||
@@ -475,8 +468,7 @@ BOOL ServerService_Uninstall(void)
|
||||
if (DeleteService(schService)) {
|
||||
Mprintf("SUCCESS: Service uninstalled successfully\n");
|
||||
r = TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("ERROR: DeleteService failed (%d)\n", (int)GetLastError());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// 服务配置:服务端使用不同的服务名
|
||||
// 服务配置:服务端使用不同的服务名
|
||||
#define SERVER_SERVICE_NAME "YamaControlService"
|
||||
#define SERVER_SERVICE_DISPLAY "Yama Control Service"
|
||||
#define SERVER_SERVICE_DESC "Provides remote desktop control server functionality."
|
||||
@@ -33,29 +33,29 @@ sc query YamaControlService
|
||||
// exePath - 输出参数,服务可执行文件路径(可为NULL)
|
||||
// exePathSize - exePath缓冲区大小
|
||||
// 返回: 成功返回TRUE
|
||||
BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
|
||||
char* exePath, size_t exePathSize);
|
||||
BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
|
||||
char* exePath, size_t exePathSize);
|
||||
|
||||
// 简单启动服务
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_StartSimple(void);
|
||||
// 简单启动服务
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_StartSimple(void);
|
||||
|
||||
// 运行服务(作为服务主入口)
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_Run(void);
|
||||
// 运行服务(作为服务主入口)
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_Run(void);
|
||||
|
||||
// 停止服务
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_Stop(void);
|
||||
// 停止服务
|
||||
// 返回: ERROR_SUCCESS 或错误码
|
||||
int ServerService_Stop(void);
|
||||
|
||||
// 安装服务
|
||||
BOOL ServerService_Install(void);
|
||||
// 安装服务
|
||||
BOOL ServerService_Install(void);
|
||||
|
||||
// 卸载服务
|
||||
BOOL ServerService_Uninstall(void);
|
||||
// 卸载服务
|
||||
BOOL ServerService_Uninstall(void);
|
||||
|
||||
// 服务工作线程
|
||||
DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam);
|
||||
// 服务工作线程
|
||||
DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ static BOOL AgentArray_Add(ServerAgentProcessArray* arr, const ServerAgentProces
|
||||
if (arr->count >= arr->capacity) {
|
||||
size_t newCapacity = arr->capacity == 0 ? INITIAL_CAPACITY : arr->capacity * 2;
|
||||
ServerAgentProcessInfo* newItems = (ServerAgentProcessInfo*)realloc(
|
||||
arr->items, newCapacity * sizeof(ServerAgentProcessInfo));
|
||||
arr->items, newCapacity * sizeof(ServerAgentProcessInfo));
|
||||
if (!newItems) {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
|
||||
DWORD dwCount = 0;
|
||||
|
||||
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
|
||||
&pSessionInfo, &dwCount)) {
|
||||
&pSessionInfo, &dwCount)) {
|
||||
|
||||
BOOL foundActiveSession = FALSE;
|
||||
|
||||
@@ -187,8 +187,8 @@ static void MonitorLoop(ServerSessionMonitor* self)
|
||||
// 记录会话(每5次循环记录一次,避免日志过多)
|
||||
if (loopCount % 5 == 1) {
|
||||
sprintf_s(buf, sizeof(buf), "Active session found: ID=%d, Name=%s",
|
||||
(int)sessionId,
|
||||
pSessionInfo[i].pWinStationName);
|
||||
(int)sessionId,
|
||||
pSessionInfo[i].pWinStationName);
|
||||
Mprintf(buf);
|
||||
}
|
||||
|
||||
@@ -201,8 +201,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
|
||||
Mprintf("GUI launched successfully");
|
||||
// 给程序一些时间启动
|
||||
Sleep(2000);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("Failed to launch GUI");
|
||||
}
|
||||
}
|
||||
@@ -217,8 +216,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
|
||||
}
|
||||
|
||||
WTSFreeMemory(pSessionInfo);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (loopCount % 5 == 1) {
|
||||
Mprintf("WTSEnumerateSessions failed");
|
||||
}
|
||||
@@ -247,8 +245,7 @@ static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId)
|
||||
char* pFileName = strrchr(currentExeName, '\\');
|
||||
if (pFileName) {
|
||||
pFileName++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pFileName = currentExeName;
|
||||
}
|
||||
|
||||
@@ -306,7 +303,7 @@ static void TerminateAllGui(ServerSessionMonitor* self)
|
||||
ServerAgentProcessInfo* info = &self->agentProcesses.items[i];
|
||||
|
||||
sprintf_s(buf, sizeof(buf), "Terminating GUI PID=%d (Session %d)",
|
||||
(int)info->processId, (int)info->sessionId);
|
||||
(int)info->processId, (int)info->sessionId);
|
||||
Mprintf(buf);
|
||||
|
||||
// 检查进程是否还活着
|
||||
@@ -316,18 +313,16 @@ static void TerminateAllGui(ServerSessionMonitor* self)
|
||||
// 进程还在运行,终止它
|
||||
if (!TerminateProcess(info->hProcess, 0)) {
|
||||
sprintf_s(buf, sizeof(buf), "WARNING: Failed to terminate PID=%d, error=%d",
|
||||
(int)info->processId, (int)GetLastError());
|
||||
(int)info->processId, (int)GetLastError());
|
||||
Mprintf(buf);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Mprintf("GUI terminated successfully");
|
||||
// 等待进程完全退出
|
||||
WaitForSingleObject(info->hProcess, 5000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sprintf_s(buf, sizeof(buf), "GUI PID=%d already exited with code %d",
|
||||
(int)info->processId, (int)exitCode);
|
||||
(int)info->processId, (int)exitCode);
|
||||
Mprintf(buf);
|
||||
}
|
||||
}
|
||||
@@ -357,18 +352,17 @@ static void CleanupDeadProcesses(ServerSessionMonitor* self)
|
||||
if (exitCode != STILL_ACTIVE) {
|
||||
// 进程已退出
|
||||
sprintf_s(buf, sizeof(buf), "GUI PID=%d exited with code %d, cleaning up",
|
||||
(int)info->processId, (int)exitCode);
|
||||
(int)info->processId, (int)exitCode);
|
||||
Mprintf(buf);
|
||||
|
||||
SAFE_CLOSE_HANDLE(info->hProcess);
|
||||
AgentArray_RemoveAt(&self->agentProcesses, i);
|
||||
continue; // 不增加 i,因为删除了元素
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// 无法获取退出代码,可能进程已不存在
|
||||
sprintf_s(buf, sizeof(buf), "Cannot query GUI PID=%d, removing from list",
|
||||
(int)info->processId);
|
||||
(int)info->processId);
|
||||
Mprintf(buf);
|
||||
|
||||
SAFE_CLOSE_HANDLE(info->hProcess);
|
||||
@@ -408,7 +402,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
|
||||
// 复制为可用于创建进程的主令牌
|
||||
HANDLE hDupToken = NULL;
|
||||
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
|
||||
SecurityImpersonation, TokenPrimary, &hDupToken)) {
|
||||
SecurityImpersonation, TokenPrimary, &hDupToken)) {
|
||||
sprintf_s(buf, sizeof(buf), "DuplicateTokenEx failed: %d", (int)GetLastError());
|
||||
Mprintf(buf);
|
||||
SAFE_CLOSE_HANDLE(hToken);
|
||||
@@ -473,18 +467,18 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
|
||||
|
||||
// 在用户会话中创建进程(GUI程序,不隐藏窗口)
|
||||
BOOL result = CreateProcessAsUserA(
|
||||
hDupToken,
|
||||
NULL, // 应用程序名(在命令行中解析)
|
||||
cmdLine, // 命令行参数:Yama.exe -agent
|
||||
NULL, // 进程安全属性
|
||||
NULL, // 线程安全属性
|
||||
FALSE, // 不继承句柄
|
||||
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, // GUI程序不需要 CREATE_NO_WINDOW
|
||||
lpEnvironment, // 环境变量
|
||||
NULL, // 当前目录
|
||||
&si,
|
||||
&pi
|
||||
);
|
||||
hDupToken,
|
||||
NULL, // 应用程序名(在命令行中解析)
|
||||
cmdLine, // 命令行参数:Yama.exe -agent
|
||||
NULL, // 进程安全属性
|
||||
NULL, // 线程安全属性
|
||||
FALSE, // 不继承句柄
|
||||
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, // GUI程序不需要 CREATE_NO_WINDOW
|
||||
lpEnvironment, // 环境变量
|
||||
NULL, // 当前目录
|
||||
&si,
|
||||
&pi
|
||||
);
|
||||
|
||||
if (lpEnvironment) {
|
||||
DestroyEnvironmentBlock(lpEnvironment);
|
||||
@@ -504,8 +498,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
|
||||
LeaveCriticalSection(&self->csProcessList);
|
||||
|
||||
SAFE_CLOSE_HANDLE(pi.hThread); // 线程句柄可以关闭
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DWORD err = GetLastError();
|
||||
sprintf_s(buf, sizeof(buf), "CreateProcessAsUser failed: %d", (int)err);
|
||||
Mprintf(buf);
|
||||
@@ -513,11 +506,9 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
|
||||
// 提供更详细的错误信息
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
Mprintf("ERROR: Executable not found");
|
||||
}
|
||||
else if (err == ERROR_ACCESS_DENIED) {
|
||||
} else if (err == ERROR_ACCESS_DENIED) {
|
||||
Mprintf("ERROR: Access denied - service may not have sufficient privileges");
|
||||
}
|
||||
else if (err == 1314) {
|
||||
} else if (err == 1314) {
|
||||
Mprintf("ERROR: Service does not have SE_INCREASE_QUOTA privilege");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
IMPLEMENT_DYNAMIC(CToolbarDlg, CDialogEx)
|
||||
|
||||
CToolbarDlg::CToolbarDlg(CWnd* pParent)
|
||||
: CDialogEx(IDD_TOOLBAR_DLG, pParent)
|
||||
: CDialogEx(IDD_TOOLBAR_DLG, pParent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -16,145 +16,145 @@ CToolbarDlg::~CToolbarDlg()
|
||||
|
||||
void CToolbarDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialogEx::DoDataExchange(pDX);
|
||||
CDialogEx::DoDataExchange(pDX);
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CToolbarDlg, CDialogEx)
|
||||
ON_BN_CLICKED(IDC_BTN_EXIT_FULLSCREEN, &CToolbarDlg::OnBnClickedExitFullscreen)
|
||||
ON_BN_CLICKED(CONTROL_BTN_ID, &CToolbarDlg::OnBnClickedCtrl)
|
||||
ON_BN_CLICKED(IDC_BTN_MINIMIZE, &CToolbarDlg::OnBnClickedMinimize)
|
||||
ON_BN_CLICKED(IDC_BTN_CLOSE, &CToolbarDlg::OnBnClickedClose)
|
||||
ON_WM_ERASEBKGND()
|
||||
ON_BN_CLICKED(IDC_BTN_EXIT_FULLSCREEN, &CToolbarDlg::OnBnClickedExitFullscreen)
|
||||
ON_BN_CLICKED(CONTROL_BTN_ID, &CToolbarDlg::OnBnClickedCtrl)
|
||||
ON_BN_CLICKED(IDC_BTN_MINIMIZE, &CToolbarDlg::OnBnClickedMinimize)
|
||||
ON_BN_CLICKED(IDC_BTN_CLOSE, &CToolbarDlg::OnBnClickedClose)
|
||||
ON_WM_ERASEBKGND()
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
void CToolbarDlg::CheckMousePosition()
|
||||
{
|
||||
CPoint pt;
|
||||
GetCursorPos(&pt);
|
||||
CPoint pt;
|
||||
GetCursorPos(&pt);
|
||||
|
||||
int cxScreen = GetSystemMetrics(SM_CXSCREEN);
|
||||
int cxScreen = GetSystemMetrics(SM_CXSCREEN);
|
||||
|
||||
// 计算按钮群的总宽度 (4个按钮 + 间距)
|
||||
int totalWidth = 80 * 4 + 10 * 3;
|
||||
int leftBound = (cxScreen - totalWidth) / 2;
|
||||
int rightBound = (cxScreen + totalWidth) / 2;
|
||||
// 计算按钮群的总宽度 (4个按钮 + 间距)
|
||||
int totalWidth = 80 * 4 + 10 * 3;
|
||||
int leftBound = (cxScreen - totalWidth) / 2;
|
||||
int rightBound = (cxScreen + totalWidth) / 2;
|
||||
|
||||
// 只有在按钮对应的横向范围内从下往上扫到顶端才弹出
|
||||
if (pt.y <= 2 && pt.x >= leftBound && pt.x <= rightBound) {
|
||||
if (!m_bVisible) SlideIn();
|
||||
}
|
||||
// 鼠标离开工具栏范围(或者在工具栏左右两侧)时隐藏
|
||||
else if (pt.y > m_nHeight + 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) {
|
||||
if (m_bVisible) SlideOut();
|
||||
}
|
||||
// 只有在按钮对应的横向范围内从下往上扫到顶端才弹出
|
||||
if (pt.y <= 2 && pt.x >= leftBound && pt.x <= rightBound) {
|
||||
if (!m_bVisible) SlideIn();
|
||||
}
|
||||
// 鼠标离开工具栏范围(或者在工具栏左右两侧)时隐藏
|
||||
else if (pt.y > m_nHeight + 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) {
|
||||
if (m_bVisible) SlideOut();
|
||||
}
|
||||
}
|
||||
|
||||
void CToolbarDlg::SlideIn()
|
||||
{
|
||||
if (m_bVisible) return;
|
||||
m_bVisible = true;
|
||||
if (m_bVisible) return;
|
||||
m_bVisible = true;
|
||||
|
||||
// 获取屏幕宽度,确保位置正确
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
// 获取屏幕宽度,确保位置正确
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
|
||||
// 动画:从 -m_nHeight 移动到 0
|
||||
// 步进加大(10像素),等待时间极短(10-15ms)
|
||||
for (int i = -m_nHeight; i <= 0; i += 10) {
|
||||
// 使用 SWP_NOACTIVATE 极其重要,防止夺取焦点导致的界面闪烁
|
||||
SetWindowPos(&wndTopMost, 0, i, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||||
// 动画:从 -m_nHeight 移动到 0
|
||||
// 步进加大(10像素),等待时间极短(10-15ms)
|
||||
for (int i = -m_nHeight; i <= 0; i += 10) {
|
||||
// 使用 SWP_NOACTIVATE 极其重要,防止夺取焦点导致的界面闪烁
|
||||
SetWindowPos(&wndTopMost, 0, i, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||||
|
||||
// 强制窗口立即重绘按钮,否则背景会是一片漆黑直到动画结束
|
||||
UpdateWindow();
|
||||
// 强制窗口立即重绘按钮,否则背景会是一片漆黑直到动画结束
|
||||
UpdateWindow();
|
||||
|
||||
Sleep(10); // 10ms 是人眼感知的流畅极限
|
||||
}
|
||||
Sleep(10); // 10ms 是人眼感知的流畅极限
|
||||
}
|
||||
|
||||
// 确保最终位置精准在 0
|
||||
SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE);
|
||||
// 确保最终位置精准在 0
|
||||
SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
void CToolbarDlg::SlideOut()
|
||||
{
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
for (int y = 0; y >= -m_nHeight; y -= 8) {
|
||||
SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE);
|
||||
Sleep(50);
|
||||
}
|
||||
ShowWindow(SW_HIDE);
|
||||
m_bVisible = false;
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
for (int y = 0; y >= -m_nHeight; y -= 8) {
|
||||
SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE);
|
||||
Sleep(50);
|
||||
}
|
||||
ShowWindow(SW_HIDE);
|
||||
m_bVisible = false;
|
||||
}
|
||||
|
||||
void CToolbarDlg::OnBnClickedExitFullscreen()
|
||||
{
|
||||
// 通知父窗口退出全屏
|
||||
GetParent()->PostMessage(WM_COMMAND, ID_EXIT_FULLSCREEN, 0);
|
||||
// 通知父窗口退出全屏
|
||||
GetParent()->PostMessage(WM_COMMAND, ID_EXIT_FULLSCREEN, 0);
|
||||
}
|
||||
|
||||
void CToolbarDlg::OnBnClickedCtrl()
|
||||
{
|
||||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||||
pParent->m_bIsCtrl = !pParent->m_bIsCtrl;
|
||||
pParent->UpdateCtrlStatus(pParent->m_bIsCtrl);
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕");
|
||||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||||
pParent->m_bIsCtrl = !pParent->m_bIsCtrl;
|
||||
pParent->UpdateCtrlStatus(pParent->m_bIsCtrl);
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕");
|
||||
}
|
||||
|
||||
void CToolbarDlg::OnBnClickedClose()
|
||||
{
|
||||
GetParent()->PostMessage(WM_CLOSE);
|
||||
GetParent()->PostMessage(WM_CLOSE);
|
||||
}
|
||||
|
||||
BOOL CToolbarDlg::OnInitDialog()
|
||||
{
|
||||
CDialogEx::OnInitDialog();
|
||||
CDialogEx::OnInitDialog();
|
||||
|
||||
// 1. 设置分层窗口样式
|
||||
ModifyStyleEx(0, WS_EX_LAYERED);
|
||||
// 1. 设置分层窗口样式
|
||||
ModifyStyleEx(0, WS_EX_LAYERED);
|
||||
|
||||
// 2. 关键设置:使用 LWA_COLORKEY 和 LWA_ALPHA 混合
|
||||
// RGB(255, 0, 255) 是品红色,我们将它定义为“透明色”
|
||||
// 255 代表按钮部分完全不透明(如果你想要按钮也半透明,可以改成 150-200)
|
||||
SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY | LWA_ALPHA);
|
||||
// 2. 关键设置:使用 LWA_COLORKEY 和 LWA_ALPHA 混合
|
||||
// RGB(255, 0, 255) 是品红色,我们将它定义为“透明色”
|
||||
// 255 代表按钮部分完全不透明(如果你想要按钮也半透明,可以改成 150-200)
|
||||
SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY | LWA_ALPHA);
|
||||
|
||||
// --- 按钮布局代码 (保持不变) ---
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
int btnWidth = 80;
|
||||
int btnHeight = 28;
|
||||
int btnSpacing = 10;
|
||||
int totalWidth = btnWidth * 4 + btnSpacing * 3;
|
||||
int startX = (cx - totalWidth) / 2;
|
||||
int y = (m_nHeight - btnHeight) / 2;
|
||||
// --- 按钮布局代码 (保持不变) ---
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
int btnWidth = 80;
|
||||
int btnHeight = 28;
|
||||
int btnSpacing = 10;
|
||||
int totalWidth = btnWidth * 4 + btnSpacing * 3;
|
||||
int startX = (cx - totalWidth) / 2;
|
||||
int y = (m_nHeight - btnHeight) / 2;
|
||||
|
||||
GetDlgItem(IDC_BTN_EXIT_FULLSCREEN)->SetWindowPos(NULL, startX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
GetDlgItem(IDC_BTN_EXIT_FULLSCREEN)->SetWindowPos(NULL, startX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
|
||||
int nextX = startX + btnWidth + btnSpacing;
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
int nextX = startX + btnWidth + btnSpacing;
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
|
||||
nextX += btnWidth + btnSpacing;
|
||||
GetDlgItem(IDC_BTN_MINIMIZE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); // 放置最小化按钮
|
||||
nextX += btnWidth + btnSpacing;
|
||||
GetDlgItem(IDC_BTN_MINIMIZE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); // 放置最小化按钮
|
||||
|
||||
nextX += btnWidth + btnSpacing;
|
||||
GetDlgItem(IDC_BTN_CLOSE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
nextX += btnWidth + btnSpacing;
|
||||
GetDlgItem(IDC_BTN_CLOSE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER);
|
||||
|
||||
// 设置控制按钮文本
|
||||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕");
|
||||
// 设置控制按钮文本
|
||||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||||
GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕");
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CToolbarDlg::OnBnClickedMinimize()
|
||||
{
|
||||
// 隐藏工具栏自身并最小化父窗口
|
||||
ShowWindow(SW_HIDE);
|
||||
m_bVisible = false;
|
||||
GetParent()->ShowWindow(SW_MINIMIZE);
|
||||
// 隐藏工具栏自身并最小化父窗口
|
||||
ShowWindow(SW_HIDE);
|
||||
m_bVisible = false;
|
||||
GetParent()->ShowWindow(SW_MINIMIZE);
|
||||
}
|
||||
|
||||
BOOL CToolbarDlg::OnEraseBkgnd(CDC* pDC)
|
||||
{
|
||||
CRect rect;
|
||||
GetClientRect(&rect);
|
||||
// 使用我们在 SetLayeredWindowAttributes 中定义的颜色填充背景
|
||||
pDC->FillSolidRect(rect, RGB(255, 0, 255));
|
||||
return TRUE;
|
||||
CRect rect;
|
||||
GetClientRect(&rect);
|
||||
// 使用我们在 SetLayeredWindowAttributes 中定义的颜色填充背景
|
||||
pDC->FillSolidRect(rect, RGB(255, 0, 255));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3,32 +3,32 @@
|
||||
|
||||
class CToolbarDlg : public CDialogEx
|
||||
{
|
||||
DECLARE_DYNAMIC(CToolbarDlg)
|
||||
DECLARE_DYNAMIC(CToolbarDlg)
|
||||
private:
|
||||
int m_lastY = 0; // 记录上一次的 Y 坐标
|
||||
int m_lastY = 0; // 记录上一次的 Y 坐标
|
||||
|
||||
public:
|
||||
CToolbarDlg(CWnd* pParent = nullptr);
|
||||
virtual ~CToolbarDlg();
|
||||
CToolbarDlg(CWnd* pParent = nullptr);
|
||||
virtual ~CToolbarDlg();
|
||||
|
||||
enum { IDD = IDD_TOOLBAR_DLG };
|
||||
enum { IDD = IDD_TOOLBAR_DLG };
|
||||
|
||||
int m_nHeight = 40;
|
||||
bool m_bVisible = false;
|
||||
int m_nHeight = 40;
|
||||
bool m_bVisible = false;
|
||||
|
||||
void SlideIn();
|
||||
void SlideOut();
|
||||
void CheckMousePosition();
|
||||
void SlideIn();
|
||||
void SlideOut();
|
||||
void CheckMousePosition();
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX);
|
||||
DECLARE_MESSAGE_MAP()
|
||||
virtual void DoDataExchange(CDataExchange* pDX);
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
afx_msg void OnBnClickedExitFullscreen();
|
||||
afx_msg void OnBnClickedCtrl();
|
||||
afx_msg void OnBnClickedMinimize();
|
||||
afx_msg void OnBnClickedClose();
|
||||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnBnClickedExitFullscreen();
|
||||
afx_msg void OnBnClickedCtrl();
|
||||
afx_msg void OnBnClickedMinimize();
|
||||
afx_msg void OnBnClickedClose();
|
||||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||||
virtual BOOL OnInitDialog();
|
||||
};
|
||||
|
||||
@@ -427,9 +427,13 @@
|
||||
#define IDC_STATIC_PAYLOAD 2211
|
||||
#define IDC_SLIDER_CLIENT_SIZE 2212
|
||||
#define IDC_STATIC_CURRENT_FILE 2213
|
||||
#define IDC_STATIC_PAYLOAD2 2213
|
||||
#define IDC_PROGRESS_FILESEND 2214
|
||||
#define IDC_STATIC_PAYLOAD3 2214
|
||||
#define IDC_STATIC_CURRENTINDEX 2215
|
||||
#define IDC_STATIC_CURRENTPERCENT 2216
|
||||
#define IDC_EDIT_INSTALL_DIR 2216
|
||||
#define IDC_EDIT_INSTALL_NAME 2217
|
||||
#define ID_ONLINE_UPDATE 32772
|
||||
#define ID_ONLINE_MESSAGE 32773
|
||||
#define ID_ONLINE_DELETE 32775
|
||||
@@ -606,15 +610,17 @@
|
||||
#define ID_FILEMANGER_COMPRESS 32990
|
||||
#define ID_FILEMANGER_32991 32991
|
||||
#define ID_FILEMANGER_UNCOMPRESS 32992
|
||||
#define ID_32993 32993
|
||||
#define ID_RANDOM_NAME 32994
|
||||
#define ID_EXIT_FULLSCREEN 40001
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 322
|
||||
#define _APS_NEXT_COMMAND_VALUE 32993
|
||||
#define _APS_NEXT_CONTROL_VALUE 2216
|
||||
#define _APS_NEXT_COMMAND_VALUE 32995
|
||||
#define _APS_NEXT_CONTROL_VALUE 2218
|
||||
#define _APS_NEXT_SYMED_VALUE 105
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user