问题
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);
}
...
}
回答1:
Per the documentation for WTSIsRemoteSession
:
WTSIsRemoteSession
Determines whether the current session is a remote session.
The
WTSQuerySessionInformation
function returns a value ofTRUE
to indicate that the current session is a remote session, andFALSE
to indicate that the current session is a local session. This value can only be used for the local machine, so thehServer
parameter of theWTSQuerySessionInformation
function must containWTS_CURRENT_SERVER_HANDLE
.Windows Server 2008 and Windows Vista: This value is not supported.
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...
...
}
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.
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...
...
}
Alternatively:
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);
...
}
来源:https://stackoverflow.com/questions/56990844/wtsisremotesession-always-returns-true