Fix: TestRun run as windows service can't unlock screen

This commit is contained in:
shaun
2025-12-29 17:54:47 +01:00
committed by yuanyuanxiang
parent 4ae97abcc6
commit 2b4f061f82
13 changed files with 92 additions and 26 deletions

View File

@@ -198,7 +198,7 @@ int main(int argc, const char *argv[])
}
}
if (!SetSelfStart(argv[0], REG_NAME)) {
if (!SetSelfStart(argv[0], REG_NAME, Logf)) {
Mprintf("设置开机自启动失败,请用管理员权限运行.\n");
}

View File

@@ -273,11 +273,12 @@ private:
BYTE* pData = (BYTE*)mapped.pData;
int rowSize = m_ulFullWidth * 4; // ÿ<>е<EFBFBD><D0B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>RGBA<42><41>
BYTE* dest = buffer + reservedBytes + (m_ulFullHeight - 1) * rowSize;
BYTE* src = pData;
for (int y = 0; y < m_ulFullHeight; y++) {
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EABBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ã<EFBFBD><C3A3>ӵײ<D3B5><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int destIndex = reservedBytes + (m_ulFullHeight - 1 - y) * rowSize;
int srcIndex = y * mapped.RowPitch; // Direct3D <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>
memcpy(buffer + destIndex, pData + srcIndex, rowSize);
memcpy(dest, src, rowSize);
dest -= rowSize;
src += mapped.RowPitch;
}
// 7. <20><><EFBFBD><EFBFBD>

View File

@@ -276,6 +276,40 @@ void CScreenManager::InitScreenSpy()
}
}
BOOL IsRunningAsSystem() {
HANDLE hToken;
PTOKEN_USER pTokenUser = NULL;
DWORD dwSize = 0;
BOOL isSystem = FALSE;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
return FALSE;
}
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
pTokenUser = (PTOKEN_USER)malloc(dwSize);
if (pTokenUser && GetTokenInformation(hToken, TokenUser, pTokenUser,
dwSize, &dwSize)) {
// 使用 WellKnownSid 创建 SYSTEM SID
BYTE systemSid[SECURITY_MAX_SID_SIZE];
DWORD sidSize = sizeof(systemSid);
if (CreateWellKnownSid(WinLocalSystemSid, NULL, systemSid, &sidSize)) {
isSystem = EqualSid(pTokenUser->User.Sid, systemSid);
if (isSystem){
Mprintf("当前进程以 SYSTEM 身份运行。\n");
} else {
Mprintf("当前进程未以 SYSTEM 身份运行。\n");
}
}
}
free(pTokenUser);
CloseHandle(hToken);
return isSystem;
}
BOOL CScreenManager::OnReconnect()
{
m_SendFirst = FALSE;
@@ -320,19 +354,16 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
This->SendFirstScreen();
}
// 降低桌面检查频率避免频繁的DC重置导致闪屏
if (This->m_isGDI && This->IsRunAsService() && !This->m_virtual) {
if (This->IsRunAsService() && !This->m_virtual) {
auto now = clock();
if (now - last_check > 500) {
last_check = now;
// 使用公共函数检查并切换桌面(无需写权限)
if (SwitchToDesktopIfChanged(This->g_hDesk, 0)) {
if (SwitchToDesktopIfChanged(This->g_hDesk, 0) && This->m_isGDI) {
// 桌面变化时重置屏幕捕获的DC
if (This->m_ScreenSpyObject) {
CScreenSpy* spy = dynamic_cast<CScreenSpy*>(This->m_ScreenSpyObject);
if (spy) {
spy->ResetDesktopDC();
}
CScreenSpy* spy = (CScreenSpy*)(This->m_ScreenSpyObject);
if (spy) {
spy->ResetDesktopDC();
}
}
}
@@ -884,13 +915,7 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
return;
}
if (IsRunAsService()) {
// 获取当前活动桌面(带写权限,用于锁屏等安全桌面)
// 使用独立的静态变量避免与WorkThreadProc的g_hDesk并发冲突
static HDESK s_inputDesk = NULL;
static clock_t s_lastCheck = 0;
static DWORD s_lastThreadId = 0;
const int CHECK_INTERVAL = 100; // 桌面检测间隔ms快速响应锁屏/UAC切换
// 首次调用或定期检测桌面是否变化(降低频率,避免每次输入都检测)
auto now = clock();
if (!s_inputDesk || now - s_lastCheck > CHECK_INTERVAL) {

View File

@@ -17,6 +17,8 @@ bool LaunchApplication(TCHAR* pszApplicationFilePath, TCHAR* pszDesktopName);
bool IsWindows8orHigher();
BOOL IsRunningAsSystem();
class IOCPClient;
struct UserParam;
@@ -58,8 +60,17 @@ public:
}
bool IsRunAsService() const
{
return m_conn ? m_conn->iStartup == Startup_GhostMsc : false;
if (m_conn && (m_conn->iStartup == Startup_GhostMsc || m_conn->iStartup == Startup_TestRunMsc))
return true;
static BOOL is_run_as_system = IsRunningAsSystem();
return is_run_as_system;
}
// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><EFBFBD><EEB6AF><EFBFBD><EFBFBD><E6A3A8>дȨ<D0B4>ޣ<EFBFBD><DEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȱ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>
// ʹ<>ö<EFBFBD><C3B6><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>WorkThreadProc<6F><63>g_hDesk<73><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ
HDESK s_inputDesk = NULL;
clock_t s_lastCheck = 0;
DWORD s_lastThreadId = 0;
bool SwitchScreen();
virtual BOOL OnReconnect();
uint64_t m_DlgID = 0;

View File

@@ -45,6 +45,8 @@ inline int DebugPrivilege()
return 0;
}
typedef void (*StartupLogFunc)(const char* file, int line, const char* format, ...);
/**
* @brief <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] *sPath ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
@@ -54,26 +56,42 @@ inline int DebugPrivilege()
* HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
* @note <20>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Թ<EFBFBD><D4B9><EFBFBD>ԱȨ<D4B1><C8A8><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EBBFAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline BOOL SetSelfStart(const char* sPath, const char* sNmae)
inline BOOL SetSelfStart(const char* sPath, const char* sNmae, StartupLogFunc Log)
{
DebugPrivilege();
#define _Mprintf(format, ...) if (Log) Log(__FILE__, __LINE__, format, __VA_ARGS__)
int n = DebugPrivilege();
if (n != 0) {
_Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룺%d\n", n);
return FALSE;
}
// д<><D0B4><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"
#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
// <20><>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
HKEY hKey = NULL;
LONG lRet = RegOpenKeyExA(HKEY_CURRENT_USER, REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey);
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>
if (lRet != ERROR_SUCCESS)
if (lRet != ERROR_SUCCESS) {
_Mprintf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룺%d\n", lRet);
return FALSE;
}
lRet = RegSetValueExA(hKey, sNmae, 0, REG_SZ, (const BYTE*)sPath, strlen(sPath) + 1);
if (lRet != ERROR_SUCCESS) {
_Mprintf("д<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룺%d\n", lRet);
} else {
_Mprintf("д<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD>%s -> %s\n", sNmae, sPath);
}
// <20>ر<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>
RegCloseKey(hKey);
#undef _Mprintf
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>
return lRet == ERROR_SUCCESS;
}

View File

@@ -231,7 +231,7 @@ int main(int argc, const char *argv[])
}
}
BOOL ok = SetSelfStart(argv[0], REG_NAME);
BOOL ok = SetSelfStart(argv[0], REG_NAME, Logf);
if(!ok) {
Mprintf("设置开机自启动失败,请用管理员权限运行.\n");
}