WTSIsRemoteSession 总是返回 TRUE

问题描述:

我目前正在编写一个 Windows 服务,它也会在用户登录时执行一些操作.如果登录来自远程计算机(例如远程桌面),则有一个想法是什么都不做,并试图找到一种方法来破坏它.但是以下不起作用 - 它总是返回true(Windows 10 64位V1809) - 我在这里做错了什么吗?

I'm currently writing a Windows service, which also does something when a user logs on. There was the idea to do nothing if the logon comes from a remote computer (e.g. Remote desktop), and tried to find a way to dermine this. But following does not work - it always returns true (Windows 10 64 bit V1809) - is there something I doing wrong here?

DWORD SvcHandlerEx(DWORD controlCode, DWORD eventType, ... )
{
    ...

    switch(controlCode)
    {
        case SERVICE_CONTROL_SESSIONCHANGE:
        {
            WTSSESSION_NOTIFICATION *pSessInfo = (WTSSESSION_NOTIFICATION *)pEvtData;
            // invoke SessionChangeHandler(eventId, pSessInfo->dwSessionId)
        }

        ...
    }

    ...
}

...

VOID SessionChangeHandler(DWORD reason, DWORD sessionId)
{
    LPWSTR *pSessionInfo = nullptr;
    DWORD dataLen = 0;
    BOOL isRDP = false;

    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, 
                                     WTSIsRemoteSession, &pSessionInfo, &dataLen))
    {
        // Do some error handling...
        return;
    }

    if (dataLen)
    {
        if (dataLen)
        {
            isRDP = (bool)pSessionInfo;    // Always 1 (TRUE) !!!
        }

        WTSFreeMemory(pSessionInfo);
    }

    ...

}

根据 文档 WTSIsRemoteSession:

WTSIsRemoteSession

WTSIsRemoteSession

确定当前会话是否为远程会话.

Determines whether the current session is a remote session.

WTSQuerySessionInformation 函数返回值 TRUE 表示当前会话是远程会话,FALSE 表示当前会话是本地会话.此值只能用于本地机器,因此WTSQuerySessionInformation 函数的hServer 参数必须包含WTS_CURRENT_SERVER_HANDLE.

The WTSQuerySessionInformation function returns a value of TRUE to indicate that the current session is a remote session, and FALSE to indicate that the current session is a local session. This value can only be used for the local machine, so the hServer parameter of the WTSQuerySessionInformation function must contain WTS_CURRENT_SERVER_HANDLE.

Windows Server 2008 和 Windows Vista:不支持此值.

Windows Server 2008 and Windows Vista:  This value is not supported.

这意味着 WTSQuerySessionInformation()返回值保存了您正在寻找的值,并且该函数可能分配的任何内存(如果有)都是次要的,应该查询WTSIsRemoteSession时被忽略,例如:

This implies that the return value of WTSQuerySessionInformation() holds the value you are looking for, and whatever memory the function may allocate, if any, is secondary and should be ignored when querying WTSIsRemoteSession, eg:

VOID SessionChangeHandler(DWORD reason, DWORD sessionId)
{
    LPWSTR *pSessionInfo = nullptr;
    DWORD dataLen = 0;

    bool isRDP = WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, &pSessionInfo, &dataLen);
    if ((!isRDP) && (GetLastError() != 0))
    {
        // Do some error handling...
        return;
    }

    if (pSessionInfo)
        WTSFreeMemory(pSessionInfo);

    // use isRDP as needed...
    ...
}

但是,如果您发现在这种情况下 isRDP 始终为真,那么文档具有误导性,您应该检查 pSessionInfo 的 contents代码>缓冲区代替.您正在根据 WTSQuerySessionInformation() 是否分配任何内存来设置您的 isRDP 变量,而不是查看数据中的实际内容.

However, if you find that isRDP is always true in this case, then the documentation is misleading and you should check the contents of the pSessionInfo buffer instead. You are setting your isRDP variable based on whether WTSQuerySessionInformation() allocates any memory at all, you are not looking at what is actually inside the data.

例如,假设 dataLen 在输出时被设置为 sizeof(BOOL) 然后将您的 pSessionInfo 指针转换为 BOOL* 指针并取消引用它,例如:

For instance, assuming dataLen is being set to sizeof(BOOL) on output then cast your pSessionInfo pointer to a BOOL* pointer and dereference it, eg:

VOID SessionChangeHandler(DWORD reason, DWORD sessionId)
{
    LPWSTR *pSessionInfo = nullptr;
    DWORD dataLen = 0;

    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, &pSessionInfo, &dataLen))
    {
        // Do some error handling...
        return;
    }

    bool isRDP = * (BOOL*) pSessionInfo;
    WTSFreeMemory(pSessionInfo);

    // use isRDP as needed...
    ...
}

或者:

VOID SessionChangeHandler(DWORD reason, DWORD sessionId)
{
    BOOL *isRDP = nullptr;
    DWORD dataLen = 0;

    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, (LPWSTR*)&isRDP, &dataLen))
    {
        // Do some error handling...
        return;
    }

    // use isRDP as needed...

    WTSFreeMemory(isRDP);
    ...
}