如何使用C ++从Windows服务中获取登录用户的令牌?

时间:2015-10-11 19:20:34

标签: windows winapi visual-c++

在windows vista&以上,

目前,我正在枚举所有的Windows会话,然后一旦找到活动会话,就会调用WTSQueryUserToken(),它会给我当前用户的标记。

此令牌用于在桌面内以他的权限启动进程。

我面临的问题是,没有可靠的方法来获取活动会话/交互式会话。我必须等待(每隔几毫秒检查一次),直到explorer.exe产生。

我不喜欢用户登录的SENS(系统通知服务)等通知。

修改

收到SERVICE_CONTROL_SESSIONCHANGE / logon事件后,我调用WTSGetActiveConsoleSessionId()来获取当前会话,然后使用此会话ID和WTSQueryUserToken()来获取令牌。

WTSGetActiveConsoleSessionId()有时会返回会话0.因此,当我需要来自当前登录用户的会话的令牌时,我最终得到会话0的令牌。

这取决于WTSGetActiveConsoleSessionId()调用的时间。

通过实验我想出了等待explorer.exe的想法,并且只有在它出现之后调用WTSGetActiveConsoleSessionId(),这似乎保证我总是得到会话1或更高版本,从而相应的令牌。

寻求更清洁的方法。

2 个答案:

答案 0 :(得分:2)

  

收到SERVICE_CONTROL_SESSIONCHANGE / logon事件后,我调用WTSGetActiveConsoleSessionId()来获取当前会话,然后使用此会话ID和WTSQueryUserToken()来获取令牌。

您应该使用SERVICE_CONTROL_SESSIONCHANGE本身报告的会话ID。 lpEventData参数将是指向WTSSESSION_NOTIFICATION结构的指针,其中包含dwSessionId字段。

  

WTSGetActiveConsoleSessionId()有时会返回会话0。

WTSGetActiveConsoleSessionId()返回连接到本地计算机的物理控制台(鼠标/键盘/监视器)的会话。它永远不会在Vista及更高版本中报告会话0(由于会话0隔离),但它可以在XP中(登录的第一个交互式用户使用会话0)。但是,即使它可以报告会话0,也不能保证与登录用户关联的正确会话。还有其他方式登录到计算机而不是通过其物理控制台。例如,远程桌面。

  

因此,当我需要来自当前登录用户的会话的令牌时,我最终得到会话0的令牌。

您需要查询用户实际登录的会话。 SERVICE_CONTROL_SESSIONCHANGE告诉您实际的会话ID,在Vista及更高版本中永远不会为0(由于会话0隔离)。

  

通过实验我想出了等待explorer.exe的想法,并且只有在它出现之后调用WTSGetActiveConsoleSessionId(),这似乎保证我总是得到会话1或更高版本,从而相应的令牌。

但这不能保证该活动控制台会话是要查询的正确会话。

  

寻求更清洁的方法。

使用通知明确告诉您的会话ID。不要去追捕它。

答案 1 :(得分:0)

我知道这是一个老问题,但仅供将来参考,以澄清人头马的答案...

如果我们假设您的服务控制处理程序称为ServiceControlHandler,那么您要执行以下操作:

DWORD ServiceControlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
    DWORD retval = ERROR_CALL_NOT_IMPLEMENTED; 

    switch (dwControl)
    {
        case SERVICE_CONTROL_INTERROGATE: // All services should handle this message
            retval = NO_ERROR;
            break;

        case SERVICE_CONTROL_SESSIONCHANGE: // Assumes you registered for these when you created the service
        {
            auto data = reinterpret_cast<WTSSESSION_NOTIFICATION*>(lpEventData);
            if (data)
            {
                DWORD sessionId = data->dwSessionId; // Now you have the actual session ID

                retval = NO_ERROR; // indicates we handled the message.

                switch (dwEventType)
                {
                    case WTS_CONSOLE_CONNECT:
                        // TODO: Do what you wish
                        break;
                    case WTS_CONSOLE_DISCONNECT:
                        // TODO: Do what you wish
                        break;
                    case WTS_REMOTE_CONNECT:
                        // TODO: Do what you wish
                        break;
                    case WTS_REMOTE_DISCONNECT:
                        // TODO: Do what you wish
                        break;
                    case WTS_SESSION_LOGON:
                        // TODO: Do what you wish
                        break;
                    case WTS_SESSION_LOGOFF:
                        // TODO: Do what you wish
                        break;
                    case WTS_SESSION_LOCK:
                        // TODO: Do what you wish
                        break;
                    case WTS_SESSION_UNLOCK:
                        // TODO: Do what you wish
                        break;
                    case WTS_SESSION_REMOTE_CONTROL:
                        // TODO: Do what you wish
                        break;

                    case WTS_SESSION_CREATE:    // (0xA) Reserved for future use.
                    case WTS_SESSION_TERMINATE: // (0xB) Reserved for future use.
                    default:
                        break; // do nothing
                }
            }
            else
            {
                // NOTE: should never happen
            }
        }
        break;

        // TODO: Handle other control types here

        default:
            retval = ERROR_CALL_NOT_IMPLEMENTED; // must always return this if not handled
            break;

    };

    return retval;
}

正如雷米(Remy)所说,通过这种方式,您可以使用通知明确告知您的会话ID,而不是去寻找错误的会话ID。

相关问题