From: Pétur Runólfsson petur@keystrike.com
--- dlls/wtsapi32/tests/wtsapi.c | 79 ++++++++++++++++++++++++++++++++++- dlls/wtsapi32/wtsapi32.c | 81 +++++++++++++++++++++++++++++++++++- include/wtsapi32.h | 58 ++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 3 deletions(-)
diff --git a/dlls/wtsapi32/tests/wtsapi.c b/dlls/wtsapi32/tests/wtsapi.c index d45d5776f39..e9391164c4a 100644 --- a/dlls/wtsapi32/tests/wtsapi.c +++ b/dlls/wtsapi32/tests/wtsapi.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <windef.h> #include <winbase.h> +#include <winuser.h> #include <winternl.h> #include <lmcons.h> #include <wtsapi32.h> @@ -188,13 +189,29 @@ static void test_WTSEnumerateProcessesW(void) pWTSFreeMemoryExW(WTSTypeProcessInfoLevel0, info, count); }
+static LONGLONG get_system_time_as_longlong(void) +{ + LARGE_INTEGER li; + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + li.u.LowPart = ft.dwLowDateTime; + li.u.HighPart = ft.dwHighDateTime; + return li.QuadPart; +} + +#define JAN_1970 (116444736000000000LL) + static void test_WTSQuerySessionInformation(void) { WCHAR *buf1, usernameW[UNLEN + 1], computernameW[MAX_COMPUTERNAME_LENGTH + 1]; char *buf2, username[UNLEN + 1], computername[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD count, tempsize, sessionId; WTS_CONNECTSTATE_CLASS *state; - DWORD count, tempsize; + WTSINFOW *wtsinfoW; + WTSINFOA *wtsinfoA; USHORT *protocol; + LONGLONG t1, t2; BOOL ret;
count = 0; @@ -309,6 +326,66 @@ static void test_WTSQuerySessionInformation(void) ok(protocol != NULL, "protocol not set\n"); ok(count == sizeof(*protocol), "got %lu\n", count); WTSFreeMemory(protocol); + + ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + + count = 0; + wtsinfoW = NULL; + t1 = get_system_time_as_longlong(); + ret = WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionInfo, + (WCHAR **)&wtsinfoW, &count); + ok(ret, "got %lu\n", GetLastError()); + t2 = get_system_time_as_longlong(); + ok(count == sizeof(*wtsinfoW), "got %lu\n", count); + ok(wtsinfoW->State == WTSActive, "got %d.\n", wtsinfoW->State); + ok(wtsinfoW->SessionId == sessionId, "expected %lu, got %lu\n", sessionId, wtsinfoW->SessionId); + ok(wtsinfoW->IncomingBytes == 0, "got %lu\n", wtsinfoW->IncomingBytes); + ok(wtsinfoW->OutgoingBytes == 0, "got %lu\n", wtsinfoW->OutgoingBytes); + ok(wtsinfoW->IncomingFrames == 0, "got %lu\n", wtsinfoW->IncomingFrames); + ok(wtsinfoW->OutgoingFrames == 0, "got %lu\n", wtsinfoW->OutgoingFrames); + ok(wtsinfoW->IncomingCompressedBytes == 0, "got %lu\n", wtsinfoW->IncomingCompressedBytes); + ok(wtsinfoW->OutgoingCompressedBytes == 0, "got %lu\n", wtsinfoW->OutgoingCompressedBytes); + ok(!wcscmp(wtsinfoW->WinStationName, L"Console"), "got %s\n", wine_dbgstr_w(wtsinfoW->WinStationName)); + ok(!wcsicmp(wtsinfoW->Domain, computernameW), + "expected %s, got %s\n", + wine_dbgstr_w(computernameW), wine_dbgstr_w(wtsinfoW->Domain)); + ok(!wcsicmp(wtsinfoW->UserName, usernameW), + "expected %s, got %s\n", + wine_dbgstr_w(usernameW), wine_dbgstr_w(wtsinfoW->UserName)); + ok(t1 <= wtsinfoW->CurrentTime.QuadPart, + "out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(wtsinfoW->CurrentTime.QuadPart)); + ok(wtsinfoW->CurrentTime.QuadPart <= t2, + "out of order %s %s\n", + wine_dbgstr_longlong(wtsinfoW->CurrentTime.QuadPart), wine_dbgstr_longlong(t2)); + WTSFreeMemory(wtsinfoW); + + count = 0; + wtsinfoA = NULL; + t1 = get_system_time_as_longlong(); + ret = WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionInfo, + (char **)&wtsinfoA, &count); + ok(ret, "got %lu\n", GetLastError()); + t2 = get_system_time_as_longlong(); + ok(count == sizeof(*wtsinfoA), "got %lu\n", count); + ok(wtsinfoA->State == WTSActive, "got %d.\n", wtsinfoA->State); + ok(wtsinfoA->SessionId == sessionId, "expected %lu, got %lu\n", sessionId, wtsinfoA->SessionId); + ok(wtsinfoA->IncomingBytes == 0, "got %lu\n", wtsinfoA->IncomingBytes); + ok(wtsinfoA->OutgoingBytes == 0, "got %lu\n", wtsinfoA->OutgoingBytes); + ok(wtsinfoA->IncomingFrames == 0, "got %lu\n", wtsinfoA->IncomingFrames); + ok(wtsinfoA->OutgoingFrames == 0, "got %lu\n", wtsinfoA->OutgoingFrames); + ok(wtsinfoA->IncomingCompressedBytes == 0, "got %lu\n", wtsinfoA->IncomingCompressedBytes); + ok(wtsinfoA->OutgoingCompressedBytes == 0, "got %lu\n", wtsinfoA->OutgoingCompressedBytes); + ok(!strcmp(wtsinfoA->WinStationName, "Console"), "got %s\n", wtsinfoA->WinStationName); + ok(!stricmp(wtsinfoA->Domain, computername), "expected %s, got %s\n", computername, wtsinfoA->Domain); + ok(!stricmp(wtsinfoA->UserName, username), "expected %s, got %s\n", username, wtsinfoA->UserName); + ok(t1 <= wtsinfoA->CurrentTime.QuadPart, + "out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(wtsinfoA->CurrentTime.QuadPart)); + ok(wtsinfoA->CurrentTime.QuadPart <= t2, + "out of order %s %s\n", + wine_dbgstr_longlong(wtsinfoA->CurrentTime.QuadPart), wine_dbgstr_longlong(t2)); + WTSFreeMemory(wtsinfoA); }
static void test_WTSQueryUserToken(void) diff --git a/dlls/wtsapi32/wtsapi32.c b/dlls/wtsapi32/wtsapi32.c index 785082d12a3..d2cdb3a930f 100644 --- a/dlls/wtsapi32/wtsapi32.c +++ b/dlls/wtsapi32/wtsapi32.c @@ -30,6 +30,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(wtsapi);
+/*********************************************************************** + * static string constants + */ +static const WCHAR session_name[] = L"Console"; + /************************************************************ * WTSCloseServer (WTSAPI32.@) */ @@ -348,8 +353,6 @@ BOOL WINAPI WTSEnumerateSessionsA(HANDLE server, DWORD reserved, DWORD version, BOOL WINAPI WTSEnumerateSessionsW(HANDLE server, DWORD reserved, DWORD version, PWTS_SESSION_INFOW *session_info, DWORD *count) { - static const WCHAR session_name[] = L"Console"; - FIXME("%p 0x%08lx 0x%08lx %p %p semi-stub.\n", server, reserved, version, session_info, count);
if (!session_info || !count) return FALSE; @@ -470,6 +473,51 @@ BOOL WINAPI WTSQuerySessionInformationA(HANDLE server, DWORD session_id, WTS_INF if (class == WTSClientProtocolType || class == WTSConnectState) return WTSQuerySessionInformationW(server, session_id, class, (WCHAR **)buffer, count);
+ if (class == WTSSessionInfo) + { + DWORD size; + WTSINFOA *info; + WTSINFOW *infoW; + + if (!WTSQuerySessionInformationW(server, session_id, class, (WCHAR **)&infoW, &size)) + return FALSE; + + if (!(info = malloc(sizeof(*info)))) + { + WTSFreeMemory(infoW); + return FALSE; + } + memset(info, 0, sizeof(*info)); + info->State = infoW->State; + info->SessionId = infoW->SessionId; + size = sizeof(info->WinStationName); + if (!WideCharToMultiByte(CP_ACP, 0, infoW->WinStationName, -1, info->WinStationName, size, NULL, NULL)) + { + WTSFreeMemory(infoW); + free(info); + return FALSE; + } + size = sizeof(info->Domain); + if (!WideCharToMultiByte(CP_ACP, 0, infoW->Domain, -1, info->Domain, size, NULL, NULL)) + { + WTSFreeMemory(infoW); + free(info); + return FALSE; + } + size = sizeof(info->UserName); + if (!WideCharToMultiByte(CP_ACP, 0, infoW->UserName, -1, info->UserName, size, NULL, NULL)) + { + WTSFreeMemory(infoW); + free(info); + return FALSE; + } + info->CurrentTime = infoW->CurrentTime; + WTSFreeMemory(infoW); + *buffer = (char *)info; + *count = sizeof(*info); + return TRUE; + } + if (!WTSQuerySessionInformationW(server, session_id, class, &bufferW, count)) return FALSE;
@@ -559,6 +607,35 @@ BOOL WINAPI WTSQuerySessionInformationW(HANDLE server, DWORD session_id, WTS_INF return TRUE; }
+ if (class == WTSSessionInfo) + { + WTSINFOW *info; + FILETIME ft; + DWORD size; + + if (!(info = malloc(sizeof(*info)))) return FALSE; + FIXME("returning partial WTSINFO\n"); + memset(info, 0, sizeof(*info)); + info->State = WTSActive; + if (!ProcessIdToSessionId(GetCurrentProcessId(), &info->SessionId)) + { + free(info); + return FALSE; + } + memcpy(info->WinStationName, session_name, sizeof(session_name)); + size = sizeof(info->Domain) / sizeof(WCHAR); + GetComputerNameW(info->Domain, &size); + size = sizeof(info->UserName) / sizeof(WCHAR); + GetUserNameW(info->UserName, &size); + GetSystemTimeAsFileTime(&ft); + info->CurrentTime.LowPart = ft.dwLowDateTime; + info->CurrentTime.HighPart = ft.dwHighDateTime; + /* TODO: fill remaining timestamps with real data */ + *buffer = (WCHAR *)info; + *count = sizeof(*info); + return TRUE; + } + FIXME("Unimplemented class %d\n", class);
*buffer = NULL; diff --git a/include/wtsapi32.h b/include/wtsapi32.h index 1bd5b6cd791..55ed6f96ae4 100644 --- a/include/wtsapi32.h +++ b/include/wtsapi32.h @@ -49,6 +49,19 @@ typedef enum tagWTS_INFO_CLASS WTSClientAddress, WTSClientDisplay, WTSClientProtocolType, + WTSIdleTime, + WTSLogonTime, + WTSIncomingBytes, + WTSOutgoingBytes, + WTSIncomingFrames, + WTSOutgoingFrames, + WTSClientInfo, + WTSSessionInfo, + WTSSessionInfoEx, + WTSConfigInfo, + WTSValidationInfo, + WTSSessionAddressV4, + WTSIsRemoteSession } WTS_INFO_CLASS;
typedef enum _WTS_CONNECTSTATE_CLASS @@ -169,6 +182,51 @@ typedef struct _WTS_SERVER_INFOW DECL_WINELIB_TYPE_AW(WTS_SERVER_INFO) DECL_WINELIB_TYPE_AW(PWTS_SERVER_INFO)
+#define WINSTATIONNAME_LENGTH 32 +#define USERNAME_LENGTH 20 +#define DOMAIN_LENGTH 17 + +typedef struct _WTSINFOA { + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBytes; + CHAR WinStationName[WINSTATIONNAME_LENGTH]; + CHAR Domain[DOMAIN_LENGTH]; + CHAR UserName[USERNAME_LENGTH + 1]; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER LogonTime; + LARGE_INTEGER CurrentTime; +} WTSINFOA, *PWTSINFOA; + +typedef struct _WTSINFOW { + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBytes; + WCHAR WinStationName[WINSTATIONNAME_LENGTH]; + WCHAR Domain[DOMAIN_LENGTH]; + WCHAR UserName[USERNAME_LENGTH + 1]; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER LogonTime; + LARGE_INTEGER CurrentTime; +} WTSINFOW, *PWTSINFOW; + +DECL_WINELIB_TYPE_AW(WTSINFO) +DECL_WINELIB_TYPE_AW(PWTSINFO) + #define WTS_CURRENT_SERVER_HANDLE ((HANDLE)NULL) #define WTS_CURRENT_SESSION (~0u) #define WTS_ANY_SESSION ((DWORD)-2)