WTSQuerySessionInformation, возвращающая пустые строки - PullRequest
3 голосов
/ 13 мая 2010

Я написал программу, которая должна запрашивать 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

Как видите, некоторые данные выглядят достоверными, но не все ....

Ответы [ 5 ]

3 голосов
/ 20 апреля 2011

Несмотря на то, что WTSQuerySessionInformation использует LPTSTR для хранения возвращаемых данных, данные не всегда являются строкой. Попытка напечатать что-то, что не является строкой, в большинстве случаев не будет работать очень хорошо. Тот факт, что вы видите пустые / мусорные строки, означает, что иногда буфер, на который указывает LPTSTR, начинается с '\ 0', если читается как строка, которую printf будет печатать как пустую строку.

Вместо этого попробуйте распечатать каждый символ строки в шестнадцатеричном представлении. Перебирайте каждый символ в строке (от 0 до bytesReturned-1) и печатайте его как шестнадцатеричный. Это даст вам лучшее представление о том, что находится в буфере LPTSTR.

2 голосов
/ 13 мая 2010

Хм, ответ, по-видимому, состоит в том, что эти поля являются вполне нормальными пустыми в сеансе служб терминалов / RDP. Этот API изначально был API-интерфейсом Citrix, и существует WF-эквивалент для большинства этих функций WTS. Похоже, вы получаете гораздо больше данных из моей программы при работе на сервере Citrix / IDA, который, по-видимому, реализует этот сеансовый API гораздо более полно. Сказав это, я также увидел больше полей, заполняемых при использовании MS Remote App. Однако, по сути, моя программа работала ...

0 голосов
/ 02 февраля 2017

Одно решение, которое мы нашли, это. База данных реестра:

enter image description here

Вы запрашиваете в удаленном реестре в HKLM \ Software \ Citrx \ Ica \ Session все ключи реестра (которые являются идентификаторами сеансов). Затем вы читаете, что они имеют значение «Имя_узла» для каждого подключа. После этого вы сопоставляете идентификатор сеанса из WTSQuerySessionInformation с именем раздела реестра, и все готово.

Некоторый код PowerShell PoC будет выглядеть следующим образом:

$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', 'YOURSERVER')
$RegKey = $Reg.OpenSubKey("SOFTWARE\\Citrix\\ICA\\Session")
foreach ($sessionId in $RegKey.GetSubKeyNames())
{
    $sessionKey = $RegKey.OpenSubKey($sessionId + "\\Connection")
    if ($sessionKey -ne $null)
    {
        $sessionKey.GetValue("PublishedName")
        $sessionKey.Close()
    }
}    
$RegKey.Close()
$Reg.Close()
0 голосов
/ 11 июня 2014

Мне никогда не удавалось получить ничего, кроме материала текущего сеанса.

    int _tmain(int argc, _TCHAR* argv[])
    {

        //  if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
        //  {
        ////The stuff coming back from WTSEnumerateSessions in ppSessionInfo doesn't seem to be useful. 

        if (GetSystemMetrics(SM_REMOTESESSION) == 0)
        {
            //it ain't remote.  give up.
            return 1;
        }

        DWORD bytesReturned = 0;
        LPTSTR pData = NULL;
        WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionId, &pData, &bytesReturned);
        DWORD sessionId = pData[0]; /*for lookin' at in the debugger*/
        wprintf(L"%d WTS session where you will see stuff.  CURRENT_SESSION\n", pData[0]);

        ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, pData[0]); 
        LPWSTR sessionstr = new wchar_t[200];
        wsprintf(sessionstr, L"%d", pData[0]);    

        getchar();
        return 0;
    }
0 голосов
/ 13 мая 2010

Я думаю, что WTSQuerySessionInformation нуждается в вас, чтобы сначала получить привилегии для правильного возврата всех данных?

...