From 2d54b0f63d0b8755d12874df5e665e9d84032006 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Mon, 7 Apr 2025 14:07:25 +0800 Subject: [PATCH 1/3] fix: #74 The remote desktop window closes randomly --- server/2015Remote/IOCPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/2015Remote/IOCPServer.cpp b/server/2015Remote/IOCPServer.cpp index fc96873..ecc9085 100644 --- a/server/2015Remote/IOCPServer.cpp +++ b/server/2015Remote/IOCPServer.cpp @@ -638,7 +638,7 @@ BOOL IOCPServer::OnClientPostSending(CONTEXT_OBJECT* ContextObject,ULONG ulCompl ContextObject->wsaOutBuffer.buf = (char*)ContextObject->OutCompressedBuffer.GetBuffer(0); ContextObject->wsaOutBuffer.len = ContextObject->OutCompressedBuffer.GetBufferLength(); int iOk = WSASend(ContextObject->sClientSocket, &ContextObject->wsaOutBuffer,1, - &ContextObject->wsaOutBuffer.len, ulFlags,&OverlappedPlus->m_ol, NULL); + NULL, ulFlags,&OverlappedPlus->m_ol, NULL); if ( iOk == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) { int a = GetLastError(); From db76967a37ec2f27172dc73553ec94cb866497db Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Mon, 7 Apr 2025 14:21:42 +0800 Subject: [PATCH 2/3] fix: #75 GDXI screenshot crashes when screen is off --- client/ScreenCapturerDXGI.h | 108 ++++++++++++++++++++---------------- client/ScreenManager.cpp | 17 +++++- 2 files changed, 76 insertions(+), 49 deletions(-) diff --git a/client/ScreenCapturerDXGI.h b/client/ScreenCapturerDXGI.h index 5f18a80..e7095ad 100644 --- a/client/ScreenCapturerDXGI.h +++ b/client/ScreenCapturerDXGI.h @@ -40,64 +40,76 @@ public: // 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 适配器 + IDXGIDevice * dxgiDevice = nullptr; 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); + do { + // 2. 获取 DXGI 设备 + d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + if(!dxgiDevice)break; - // 7. 获取屏幕大小 - DXGI_OUTDUPL_DESC duplDesc; - deskDupl->GetDesc(&duplDesc); - m_ulFullWidth = duplDesc.ModeDesc.Width; - m_ulFullHeight = duplDesc.ModeDesc.Height; + // 3. 获取 DXGI 适配器 + dxgiDevice->GetAdapter(&dxgiAdapter); + if (!dxgiAdapter)break; - // 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); + // 4. 获取 DXGI 输出(屏幕) + dxgiAdapter->EnumOutputs(0, &dxgiOutput); + if (!dxgiOutput)break; - // 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; + // 5. 获取 DXGI 输出 1 + dxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), (void**)&dxgiOutput1); + if (!dxgiOutput1)break; - // 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]; + // 6. 创建 Desktop Duplication + dxgiOutput1->DuplicateOutput(d3dDevice, &deskDupl); + if (!deskDupl)break; + + // 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]; + } while (false); // 释放 DXGI 资源 - dxgiOutput1->Release(); - dxgiOutput->Release(); - dxgiAdapter->Release(); - dxgiDevice->Release(); + if (dxgiOutput1) dxgiOutput1->Release(); + if (dxgiOutput) dxgiOutput->Release(); + if (dxgiAdapter) dxgiAdapter->Release(); + if (dxgiDevice) dxgiDevice->Release(); + } + + bool IsInitSucceed() const { + return cpuTexture; } void CleanupDXGI() { diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 9c0f71e..fc69407 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -57,7 +57,22 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan 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); + if ((DXGI && IsWindows8orHigher())) + { + auto s = new ScreenCapturerDXGI(algo); + if (s->IsInitSucceed()) { + m_ScreenSpyObject = s; + } + else { + SAFE_DELETE(s); + m_ScreenSpyObject = new CScreenSpy(32, algo); + Mprintf("CScreenManager: DXGI SPY init failed!!! Using GDI instead.\n"); + } + } + else + { + m_ScreenSpyObject = new CScreenSpy(32, algo); + } m_hWorkThread = CreateThread(NULL,0, WorkThreadProc,this,0,NULL); } From 29a324404fa8f41b8d318bb69b60b66268c46b7e Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Mon, 7 Apr 2025 21:12:55 +0800 Subject: [PATCH 3/3] fix: #62 Text length limit for `CEdit` is 30000 --- server/2015Remote/ShellDlg.cpp | 47 +++++++++++++++++++++++++++++++--- server/2015Remote/ShellDlg.h | 2 +- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/server/2015Remote/ShellDlg.cpp b/server/2015Remote/ShellDlg.cpp index 9b1eb15..78d35a9 100644 --- a/server/2015Remote/ShellDlg.cpp +++ b/server/2015Remote/ShellDlg.cpp @@ -6,6 +6,8 @@ #include "ShellDlg.h" #include "afxdialogex.h" +#define EDIT_MAXLENGTH 30000 + BEGIN_MESSAGE_MAP(CAutoEndEdit, CEdit) ON_WM_CHAR() END_MESSAGE_MAP() @@ -77,6 +79,7 @@ BOOL CShellDlg::OnInitDialog() m_nReceiveLength = m_nCurSel; m_Edit.SetSel((int)m_nCurSel, (int)m_nCurSel); m_Edit.PostMessage(EM_SETSEL, m_nCurSel, m_nCurSel); + m_Edit.SetLimitText(EDIT_MAXLENGTH); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE @@ -115,6 +118,17 @@ VOID CShellDlg::AddKeyBoardData(void) //替换掉原来的换行符 可能cmd 的换行同w32下的编辑控件的换行符不一致 所有的回车换行 strResult.Replace("\n", "\r\n"); + if (strResult.GetLength() + m_Edit.GetWindowTextLength() >= EDIT_MAXLENGTH) + { + CString text; + m_Edit.GetWindowTextA(text); + auto n = EDIT_MAXLENGTH - strResult.GetLength() - 5; // 留5个字符输入clear清屏 + if (n < 0) { + strResult = strResult.Right(strResult.GetLength() + n); + } + m_Edit.SetWindowTextA(text.Right(max(n, 0))); + } + //得到当前窗口的字符个数 int iLength = m_Edit.GetWindowTextLength(); //kdfjdjfdir //hello @@ -151,6 +165,24 @@ void CShellDlg::OnClose() } +CString ExtractAfterLastNewline(const CString& str) +{ + int nPos = str.ReverseFind(_T('\n')); + if (nPos != -1) + { + return str.Mid(nPos + 1); + } + + nPos = str.ReverseFind(_T('\r')); + if (nPos != -1) + { + return str.Mid(nPos + 1); + } + + return str; +} + + BOOL CShellDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) @@ -174,13 +206,20 @@ BOOL CShellDlg::PreTranslateMessage(MSG* pMsg) #ifdef _DEBUG TRACE("[Shell]=> %s", (char*)pSrc); #endif + if (0 == strcmp((char*)pSrc, "exit\r\n")) { // 退出终端 + return PostMessage(WM_CLOSE); + } + else if (0 == strcmp((char*)pSrc, "clear\r\n")) { // 清理终端 + str = ExtractAfterLastNewline(str.Left(str.GetLength() - 7)); + m_Edit.SetWindowTextA(str); + m_nCurSel = m_Edit.GetWindowTextLength(); + m_nReceiveLength = m_nCurSel; + m_Edit.SetSel(m_nCurSel, m_nCurSel); + return TRUE; + } int length = str.GetLength() - m_nCurSel; m_iocpServer->OnClientPreSending(m_ContextObject, pSrc, length); m_nCurSel = m_Edit.GetWindowTextLength(); - if (0 == strcmp((char*)pSrc, "exit\r\n")) - { - return PostMessage(WM_CLOSE); - } } // 限制VK_BACK if (pMsg->wParam == VK_BACK && pMsg->hwnd == m_Edit.m_hWnd) diff --git a/server/2015Remote/ShellDlg.h b/server/2015Remote/ShellDlg.h index 5a2348d..2198b7e 100644 --- a/server/2015Remote/ShellDlg.h +++ b/server/2015Remote/ShellDlg.h @@ -25,7 +25,7 @@ public: HICON m_hIcon; UINT m_nReceiveLength; VOID AddKeyBoardData(void); - UINT m_nCurSel; //获得当前数据所在位置; + int m_nCurSel; //获得当前数据所在位置; // 对话框数据 enum { IDD = IDD_DIALOG_SHELL };