WTSIsRemoteSession 始终返回 TRUE

问题描述 投票:0回答:1

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

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);
    }

    ...

}
windows winapi service
1个回答
4
投票

根据 WTSIsRemoteSession

文档

WTSI 是远程会话

判断当前会话是否为远程会话。

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

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

这意味着 WTSQuerySessionInformation()

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

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
。您根据
isRDP
是否分配任何内存来设置
WTSQuerySessionInformation()
变量,您没有查看数据中实际包含的内容。

例如,假设

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

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);
    ...
}

更新:

另一方面,如果

dataLen
在输出上设置为
sizeof(UCHAR)
,则将
pSessionInfo
指针转换为
UCHAR*
指针并取消引用它,例如:

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 = * (UCHAR*) pSessionInfo;
    WTSFreeMemory(pSessionInfo);

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

或者:

VOID SessionChangeHandler(DWORD reason, DWORD sessionId)
{
    UCHAR *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);
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.