标签: wtsapi32

是什么让SwitchDesktop在用户解锁会话后无法正常工作?

我有一个程序可以切换桌面并在其上启动一个新进程.进程退出时,父进程将还原原始桌面.

出于测试目的,我在一个触发切换的普通win32应用程序中放了一个按钮.它工作,并关闭启动的进程(记事本),我回到原来的桌面.

在同一个程序中,我调用了WTSRegisterSessionNotification以在会话解锁时接收通知(WTS_SESSION_UNLOCK).我收到了

但是当我尝试在WTS_SESSION_UNLOCK消息处理程序中切换桌面时,SwitchDesktop失败并且GetLastError为0.文档说最后一个错误通常不是由SwitchDesktop设置的.

有趣的是,如果我在for循环中调用切换桌面,它将在第5次迭代时工作.

简而言之,这不起作用:

    case WM_WTSSESSION_CHANGE:
      if(wParam == WTS_SESSION_UNLOCK)          
      {
          SwitchDesktop(a_valid_desktop_handle);
      }
    break;
Run Code Online (Sandbox Code Playgroud)

但这个丑陋的黑客有效:

    case WM_WTSSESSION_CHANGE:
      if(wParam == WTS_SESSION_UNLOCK)          
      {
         for(int i=0; i<10; ++i)
         {
            if(SwitchDesktop(a_valid_desktop_handle))
            {
                //This will work when i == 5, maybe 6.
                break;
            }
         }
      }
    break;
Run Code Online (Sandbox Code Playgroud)

设置一个计时器(退出消息循环)也有效,但对于这个问题,它只是一个更复杂的循环形式.SwitchDesktop将在完成一系列WM_TIMER消息后继续工作.看起来像是不变的时间,虽然我没有测量它.

SwitchDesktop的MSDN文档提到我将使用自定义Userinit进程失败.但是在切换之前获取当前桌面的名称:

wchar_t name[512];
GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()), UOI_NAME, name, sizeof(name)/sizeof(*name), 0);
OutputDebugString(name);
Run Code Online (Sandbox Code Playgroud)

给我default所有的时间.并且因为GetLastError是0 而不是5(访问被拒绝)我非常确定在收到WTS_SESSION_UNLOCK通知之前安全桌面已经消失.

我知道在屏幕被锁定时我无法切换桌面,但桌面解锁后是否有"宽限期",我无法调用SwitchDesktop?

windows winapi wtsapi32

6
推荐指数
1
解决办法
1755
查看次数

如何获取物理会话的当前用户令牌?

我有一些代码,我正在尝试获取当前会话用户令牌:

#include <Wtsapi32.h>

DWORD activeSessionId = WTSGetActiveConsoleSessionId();

HANDLE currentToken;
BOOL queryRet = WTSQueryUserToken(activeSessionId, &currentToken);

if (!queryRet) {
    DWORD err = GetLastError();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误的价值是1314.

更新1

到目前为止没有运气,试图授予当前进程SE_TCB_NAME - 但仍然从WTSQueryUserToken(1314)获得相同的错误.

HANDLE process = GetCurrentProcess();

HANDLE processToken;
BOOL openTokenRet = OpenProcessToken(
    process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);

if (!openTokenRet)
{
    DWORD err = GetLastError();
    return 0;
}

TOKEN_PRIVILEGES tokenPrivs;
BOOL lookupRet = LookupPrivilegeValue(
    NULL, SE_TCB_NAME, &tokenPrivs.Privileges[0].Luid);

if (!lookupRet)
{
    DWORD err = GetLastError();
    return 0;
}

tokenPrivs.PrivilegeCount = 1;
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

BOOL …
Run Code Online (Sandbox Code Playgroud)

winapi wtsapi32

5
推荐指数
1
解决办法
1万
查看次数

标签 统计

winapi ×2

wtsapi32 ×2

windows ×1