我目前正在编写一个 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);
}
...
}
根据 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);
...
}