WTSQuerySessionInformation 返回空字符串
我编写了一个程序,该程序应该查询终端服务 API 并打印出有关在终端服务盒上运行的会话的一些状态信息。我正在使用 WTSQuerySessionInformation 函数来执行此操作,它返回一些数据,但大多数数据似乎丢失...有人知道为什么吗?
这是我的程序:
void WTSGetString( HANDLE serverHandle, DWORD sessionid, WTS_INFO_CLASS command, wchar_t* commandStr)
{
DWORD bytesReturned = 0;
LPTSTR pData = NULL;
if (WTSQuerySessionInformation(serverHandle, sessionid, command, &pData, &bytesReturned))
{
wprintf(L"\tWTSQuerySessionInformationW - session %d - %s returned \"%s\"\n", sessionid, commandStr, pData);
}
else
{
wprintf(L"\tWTSQuerySessionInformationW - session %d - %s failed - error=%d - ", sessionid, commandStr, GetLastError());
printLastError(NULL, GetLastError());
}
WTSFreeMemory(pData);
}
void ExtractFromWTS( HANDLE serverHandle, DWORD sessionid )
{
WTSGetString(serverHandle, sessionid, WTSInitialProgram, L"WTSInitialProgram");
WTSGetString(serverHandle, sessionid, WTSApplicationName, L"WTSApplicationName");
WTSGetString(serverHandle, sessionid, WTSWorkingDirectory, L"WTSWorkingDirectory");
WTSGetString(serverHandle, sessionid, WTSOEMId, L"WTSOEMId");
WTSGetString(serverHandle, sessionid, WTSSessionId, L"WTSSessionId");
WTSGetString(serverHandle, sessionid, WTSUserName, L"WTSUserName");
WTSGetString(serverHandle, sessionid, WTSWinStationName, L"WTSWinStationName");
WTSGetString(serverHandle, sessionid, WTSDomainName, L"WTSDomainName");
WTSGetString(serverHandle, sessionid, WTSConnectState, L"WTSConnectState");
WTSGetString(serverHandle, sessionid, WTSClientBuildNumber, L"WTSClientBuildNumber");
WTSGetString(serverHandle, sessionid, WTSClientName, L"WTSClientName");
WTSGetString(serverHandle, sessionid, WTSClientDirectory, L"WTSClientDirectory");
WTSGetString(serverHandle, sessionid, WTSClientProductId, L"WTSClientProductId");
WTSGetString(serverHandle, sessionid, WTSClientHardwareId, L"WTSClientHardwareId");
WTSGetString(serverHandle, sessionid, WTSClientAddress, L"WTSClientAddress");
WTSGetString(serverHandle, sessionid, WTSClientDisplay, L"WTSClientDisplay");
WTSGetString(serverHandle, sessionid, WTSClientProtocolType, L"WTSClientProtocolType");
}
int _tmain(int argc, _TCHAR* argv[])
{
PWTS_SESSION_INFOW ppSessionInfo = 0;
DWORD pCount;
if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
{
printLastError(L"WTSEnumerateSessions", GetLastError());
return 1;
}
wprintf(L"%d WTS sessions found on host\n", pCount);
for (unsigned int i=0; i<pCount; i++)
{
wprintf(L"> session=%d, stationName = %s\n", ppSessionInfo[i].SessionId, ppSessionInfo[i].pWinStationName);
ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, ppSessionInfo[i].SessionId);
LPWSTR sessionstr = new wchar_t[200];
wsprintf(sessionstr, L"%d", ppSessionInfo[i].SessionId);
}
return 0;
}
这是输出:
C:\Users\Administrator\Desktop>ObtainWTSStartShell.exe empserver1
4 WTS sessions found on host
> session=0, stationName = Services
WTSQuerySessionInformationW - session 0 - WTSInitialProgram failed - error=87 - The paramete
r is incorrect.
WTSQuerySessionInformationW - session 0 - WTSApplicationName failed - error=87 - The paramet
er is incorrect.
WTSQuerySessionInformationW - session 0 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 0 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 0 - WTSSessionId returned ""
WTSQuerySessionInformationW - session 0 - WTSUserName returned ""
WTSQuerySessionInformationW - session 0 - WTSWinStationName returned "Services"
WTSQuerySessionInformationW - session 0 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 0 - WTSConnectState returned "♦"
WTSQuerySessionInformationW - session 0 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 0 - WTSClientName returned ""
WTSQuerySessionInformationW - session 0 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 0 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 0 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 0 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 0 - WTSClientDisplay returned ""
WTSQuerySessionInformationW - session 0 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=1, stationName = Console
WTSQuerySessionInformationW - session 1 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 1 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 1 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 1 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 1 - WTSSessionId returned "☺"
WTSQuerySessionInformationW - session 1 - WTSUserName returned ""
WTSQuerySessionInformationW - session 1 - WTSWinStationName returned "Console"
WTSQuerySessionInformationW - session 1 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 1 - WTSConnectState returned "☺"
WTSQuerySessionInformationW - session 1 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 1 - WTSClientName returned ""
WTSQuerySessionInformationW - session 1 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 1 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 1 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 1 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 1 - WTSClientDisplay returned "?"
WTSQuerySessionInformationW - session 1 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=3, stationName = RDP-Tcp#0
WTSQuerySessionInformationW - session 3 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 3 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 3 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 3 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 3 - WTSSessionId returned "♥"
WTSQuerySessionInformationW - session 3 - WTSUserName returned "Administrator"
WTSQuerySessionInformationW - session 3 - WTSWinStationName returned "RDP-Tcp#0"
WTSQuerySessionInformationW - session 3 - WTSDomainName returned "EMPSERVER1"
WTSQuerySessionInformationW - session 3 - WTSConnectState returned ""
WTSQuerySessionInformationW - session 3 - WTSClientBuildNumber returned "?"
WTSQuerySessionInformationW - session 3 - WTSClientName returned "APWADEV03"
WTSQuerySessionInformationW - session 3 - WTSClientDirectory returned "C:\Windows\System32\m
stscax.dll"
WTSQuerySessionInformationW - session 3 - WTSClientProductId returned "☺"
WTSQuerySessionInformationW - session 3 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 3 - WTSClientAddress returned "☻"
WTSQuerySessionInformationW - session 3 - WTSClientDisplay returned "?"
WTSQuerySessionInformationW - session 3 - WTSClientProtocolType returned "☻"
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=65536, stationName = RDP-Tcp
WTSQuerySessionInformationW - session 65536 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 65536 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 65536 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 65536 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 65536 - WTSSessionId returned ""
WTSQuerySessionInformationW - session 65536 - WTSUserName returned ""
WTSQuerySessionInformationW - session 65536 - WTSWinStationName returned "RDP-Tcp"
WTSQuerySessionInformationW - session 65536 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 65536 - WTSConnectState returned "♠"
WTSQuerySessionInformationW - session 65536 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientName returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientDisplay returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
如您所见,一些数据看起来有效,但并非全部......
I've written a program which should query the Terminal Services API and print out some state information about the sessions running on a terminal services box. I'm using the WTSQuerySessionInformation function to do this and it's returning some data but most of the data seems to be missing... Does anyone know why?
Here's my program:
void WTSGetString( HANDLE serverHandle, DWORD sessionid, WTS_INFO_CLASS command, wchar_t* commandStr)
{
DWORD bytesReturned = 0;
LPTSTR pData = NULL;
if (WTSQuerySessionInformation(serverHandle, sessionid, command, &pData, &bytesReturned))
{
wprintf(L"\tWTSQuerySessionInformationW - session %d - %s returned \"%s\"\n", sessionid, commandStr, pData);
}
else
{
wprintf(L"\tWTSQuerySessionInformationW - session %d - %s failed - error=%d - ", sessionid, commandStr, GetLastError());
printLastError(NULL, GetLastError());
}
WTSFreeMemory(pData);
}
void ExtractFromWTS( HANDLE serverHandle, DWORD sessionid )
{
WTSGetString(serverHandle, sessionid, WTSInitialProgram, L"WTSInitialProgram");
WTSGetString(serverHandle, sessionid, WTSApplicationName, L"WTSApplicationName");
WTSGetString(serverHandle, sessionid, WTSWorkingDirectory, L"WTSWorkingDirectory");
WTSGetString(serverHandle, sessionid, WTSOEMId, L"WTSOEMId");
WTSGetString(serverHandle, sessionid, WTSSessionId, L"WTSSessionId");
WTSGetString(serverHandle, sessionid, WTSUserName, L"WTSUserName");
WTSGetString(serverHandle, sessionid, WTSWinStationName, L"WTSWinStationName");
WTSGetString(serverHandle, sessionid, WTSDomainName, L"WTSDomainName");
WTSGetString(serverHandle, sessionid, WTSConnectState, L"WTSConnectState");
WTSGetString(serverHandle, sessionid, WTSClientBuildNumber, L"WTSClientBuildNumber");
WTSGetString(serverHandle, sessionid, WTSClientName, L"WTSClientName");
WTSGetString(serverHandle, sessionid, WTSClientDirectory, L"WTSClientDirectory");
WTSGetString(serverHandle, sessionid, WTSClientProductId, L"WTSClientProductId");
WTSGetString(serverHandle, sessionid, WTSClientHardwareId, L"WTSClientHardwareId");
WTSGetString(serverHandle, sessionid, WTSClientAddress, L"WTSClientAddress");
WTSGetString(serverHandle, sessionid, WTSClientDisplay, L"WTSClientDisplay");
WTSGetString(serverHandle, sessionid, WTSClientProtocolType, L"WTSClientProtocolType");
}
int _tmain(int argc, _TCHAR* argv[])
{
PWTS_SESSION_INFOW ppSessionInfo = 0;
DWORD pCount;
if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
{
printLastError(L"WTSEnumerateSessions", GetLastError());
return 1;
}
wprintf(L"%d WTS sessions found on host\n", pCount);
for (unsigned int i=0; i<pCount; i++)
{
wprintf(L"> session=%d, stationName = %s\n", ppSessionInfo[i].SessionId, ppSessionInfo[i].pWinStationName);
ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, ppSessionInfo[i].SessionId);
LPWSTR sessionstr = new wchar_t[200];
wsprintf(sessionstr, L"%d", ppSessionInfo[i].SessionId);
}
return 0;
}
And here's the output:
C:\Users\Administrator\Desktop>ObtainWTSStartShell.exe empserver1
4 WTS sessions found on host
> session=0, stationName = Services
WTSQuerySessionInformationW - session 0 - WTSInitialProgram failed - error=87 - The paramete
r is incorrect.
WTSQuerySessionInformationW - session 0 - WTSApplicationName failed - error=87 - The paramet
er is incorrect.
WTSQuerySessionInformationW - session 0 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 0 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 0 - WTSSessionId returned ""
WTSQuerySessionInformationW - session 0 - WTSUserName returned ""
WTSQuerySessionInformationW - session 0 - WTSWinStationName returned "Services"
WTSQuerySessionInformationW - session 0 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 0 - WTSConnectState returned "♦"
WTSQuerySessionInformationW - session 0 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 0 - WTSClientName returned ""
WTSQuerySessionInformationW - session 0 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 0 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 0 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 0 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 0 - WTSClientDisplay returned ""
WTSQuerySessionInformationW - session 0 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=1, stationName = Console
WTSQuerySessionInformationW - session 1 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 1 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 1 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 1 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 1 - WTSSessionId returned "☺"
WTSQuerySessionInformationW - session 1 - WTSUserName returned ""
WTSQuerySessionInformationW - session 1 - WTSWinStationName returned "Console"
WTSQuerySessionInformationW - session 1 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 1 - WTSConnectState returned "☺"
WTSQuerySessionInformationW - session 1 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 1 - WTSClientName returned ""
WTSQuerySessionInformationW - session 1 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 1 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 1 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 1 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 1 - WTSClientDisplay returned "?"
WTSQuerySessionInformationW - session 1 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=3, stationName = RDP-Tcp#0
WTSQuerySessionInformationW - session 3 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 3 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 3 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 3 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 3 - WTSSessionId returned "♥"
WTSQuerySessionInformationW - session 3 - WTSUserName returned "Administrator"
WTSQuerySessionInformationW - session 3 - WTSWinStationName returned "RDP-Tcp#0"
WTSQuerySessionInformationW - session 3 - WTSDomainName returned "EMPSERVER1"
WTSQuerySessionInformationW - session 3 - WTSConnectState returned ""
WTSQuerySessionInformationW - session 3 - WTSClientBuildNumber returned "?"
WTSQuerySessionInformationW - session 3 - WTSClientName returned "APWADEV03"
WTSQuerySessionInformationW - session 3 - WTSClientDirectory returned "C:\Windows\System32\m
stscax.dll"
WTSQuerySessionInformationW - session 3 - WTSClientProductId returned "☺"
WTSQuerySessionInformationW - session 3 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 3 - WTSClientAddress returned "☻"
WTSQuerySessionInformationW - session 3 - WTSClientDisplay returned "?"
WTSQuerySessionInformationW - session 3 - WTSClientProtocolType returned "☻"
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
> session=65536, stationName = RDP-Tcp
WTSQuerySessionInformationW - session 65536 - WTSInitialProgram returned ""
WTSQuerySessionInformationW - session 65536 - WTSApplicationName returned ""
WTSQuerySessionInformationW - session 65536 - WTSWorkingDirectory returned ""
WTSQuerySessionInformationW - session 65536 - WTSOEMId returned ""
WTSQuerySessionInformationW - session 65536 - WTSSessionId returned ""
WTSQuerySessionInformationW - session 65536 - WTSUserName returned ""
WTSQuerySessionInformationW - session 65536 - WTSWinStationName returned "RDP-Tcp"
WTSQuerySessionInformationW - session 65536 - WTSDomainName returned ""
WTSQuerySessionInformationW - session 65536 - WTSConnectState returned "♠"
WTSQuerySessionInformationW - session 65536 - WTSClientBuildNumber returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientName returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientDirectory returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientProductId returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientHardwareId returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientAddress returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientDisplay returned ""
WTSQuerySessionInformationW - session 65536 - WTSClientProtocolType returned ""
GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
GetShellProcessName succeseded - explorer.exe
As you can see, some of the data looks valid, but not all....
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尽管 WTSQuerySessionInformation 采用 LPTSTR 来保存返回的数据,但该数据并不总是字符串。在大多数情况下,尝试打印非字符串的内容不会很好地工作。事实上,您看到空/垃圾字符串意味着有时 LPTSTR 指向的缓冲区以 '\0' 开头(如果作为字符串读取), printf 将打印为空字符串。
相反,请尝试以十六进制表示形式打印字符串的每个字符。迭代字符串中的每个字符(0 到 bytesReturned-1)并将其打印为十六进制。这将使您更好地了解 LPTSTR 缓冲区中的内容。
Even though WTSQuerySessionInformation takes a LPTSTR to hold the data returned, the data isn't always a string. Trying to printf something that isn't a string won't work very well in most cases. The fact that you're seeing empty/garbage strings means that sometimes the buffer pointed to by the LPTSTR starts with a '\0' if read as a string, which printf will print as the empty string.
Instead try printing out each character of the string in HEX representation. Iterate through each character in the string (0 through bytesReturned-1) and print it as hex. That will give you a better idea of what's in the LPTSTR buffer.
除了当前会话的内容之外,我什么也得不到。
I've never been able to get anything but the current session stuff.
我们找到的一种解决方案是这样的。基于注册表信息:
您在 HKLM\Software\Citrx\Ica\Session 下的远程注册表中查询所有注册表项(即会话 ID)。然后,您从每个子键 Connection 中读取它们的值 PublishedName。之后,将 WTSQuerySessionInformation 中的会话 ID 与注册表项名称进行匹配,就完成了。
一些 PowerShell PoC 代码如下所示:
One solution we found is this. Base on registry information:
You query the remote registry under HKLM\Software\Citrx\Ica\Session for all registry keys (which are the session id's). Then you read they value PublishedName from each sub key Connection. After that you match the session id from WTSQuerySessionInformation against the registry key name and you are done.
Some PowerShell PoC code would look like this:
嗯,答案似乎是,在终端服务/RDP 会话中这些字段为空是相当正常的。该 API 最初是 Citrix API,并且有一个 WF 相当于大多数 WTS 功能。在 Citrix/IDA 服务器上运行时,您似乎从我的程序中获得了更多数据,该服务器似乎更全面地实现了此会话 API。话虽如此,我在使用 MS Remote App 时也看到了更多的字段被填写。然而,基本上我的程序正在运行......
Hmm, the answer appears to be that it's fairly normal for these fields to be empty on a terminal services/RDP session. This API was originally a Citrix API and there's a WF equivalent to most of these WTS function. You seem to get much more data from my program when running on a Citrix/IDA server which appears to implement this session API much more fully. Having said that, I also saw more of the fields being filled in when using MS Remote App. However, essentially my program was working...