WTSIsRemoteSession 始终返回 TRUE

Wil*_* K. 1 windows service winapi

我目前正在编写一个 Windows 服务,它也会在用户登录时执行一些操作。有人的想法是,如果登录来自远程计算机(例如远程桌面),则不执行任何操作,并试图找到一种方法来消除这种情况。但以下不起作用 - 它总是返回 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);
    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

根据文档WTSIsRemoteSession

\n
\n

WTSI远程会话

\n

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

\n

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

\n

Windows Server\xc2\xa02008 和 Windows\xc2\xa0Vista:\xc2\xa0\xc2\xa0 不支持此值。

\n
\n

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

\n
VOID SessionChangeHandler(DWORD reason, DWORD sessionId)\n{\n    LPWSTR *pSessionInfo = nullptr;\n    DWORD dataLen = 0;\n\n    bool isRDP = WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, &pSessionInfo, &dataLen);\n    if ((!isRDP) && (GetLastError() != 0))\n    {\n        // Do some error handling...\n        return;\n    }\n\n    if (pSessionInfo)\n        WTSFreeMemory(pSessionInfo);\n\n    // use isRDP as needed...\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果您发现isRDP在这种情况下总是如此,则说明文档具有误导性,您应该检查缓冲区的内容pSessionInfoisRDP您正在根据是否设置变量WTSQuerySessionInformation()变量,而不是查看数据中实际包含的内容。

\n

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

\n
VOID SessionChangeHandler(DWORD reason, DWORD sessionId)\n{\n    LPWSTR *pSessionInfo = nullptr;\n    DWORD dataLen = 0;\n\n    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, &pSessionInfo, &dataLen))\n    {\n        // Do some error handling...\n        return;\n    }\n\n    bool isRDP = * (BOOL*) pSessionInfo;\n    WTSFreeMemory(pSessionInfo);\n\n    // use isRDP as needed...\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或者:

\n
VOID SessionChangeHandler(DWORD reason, DWORD sessionId)\n{\n    BOOL *isRDP = nullptr;\n    DWORD dataLen = 0;\n\n    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, (LPWSTR*)&isRDP, &dataLen))\n    {\n        // Do some error handling...\n        return;\n    }\n\n    // use *isRDP as needed...\n\n    WTSFreeMemory(isRDP);\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

更新:

\n

另一方面,如果dataLen将其设置为sizeof(UCHAR)输出,则将pSessionInfo指针转换为UCHAR*指针并取消引用它,例如:

\n
VOID SessionChangeHandler(DWORD reason, DWORD sessionId)\n{\n    LPWSTR *pSessionInfo = nullptr;\n    DWORD dataLen = 0;\n\n    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, &pSessionInfo, &dataLen))\n    {\n        // Do some error handling...\n        return;\n    }\n\n    bool isRDP = * (UCHAR*) pSessionInfo;\n    WTSFreeMemory(pSessionInfo);\n\n    // use isRDP as needed...\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或者:

\n
VOID SessionChangeHandler(DWORD reason, DWORD sessionId)\n{\n    UCHAR *isRDP = nullptr;\n    DWORD dataLen = 0;\n\n    if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, (LPWSTR*)&isRDP, &dataLen))\n    {\n        // Do some error handling...\n        return;\n    }\n\n    // use *isRDP as needed...\n\n    WTSFreeMemory(isRDP);\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n