#include "users.h" #include "common/windows/unicode.h" #include "common/time.h" #include #include #include const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) { WTS_SESSION_INFO_1W* sessionInfo; DWORD sessionCount; DWORD level = 1; if (!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) { return "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed"; } for (DWORD i = 0; i < sessionCount; i++) { WTS_SESSION_INFO_1W* session = &sessionInfo[i]; if (session->State != WTSActive) { continue; } FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreateWS(session->pUserName); if (options->myselfOnly && !ffStrbufEqual(&instance.state.platform.userName, &userName)) { continue; } FFUserResult* user = FF_LIST_ADD(FFUserResult, *users); ffStrbufInitMove(&user->name, &userName); ffStrbufInitWS(&user->hostName, session->pHostName); ffStrbufInitWS(&user->sessionName, session->pSessionName); ffStrbufInit(&user->clientIp); user->loginTime = 0; DWORD bytes = 0; PWTS_CLIENT_ADDRESS address = NULL; if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientAddress, (LPWSTR*) &address, &bytes)) { if (address->AddressFamily == AF_INET) { ffStrbufSetF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); } else if (address->AddressFamily == AF_INET6) { char ipStr[INET6_ADDRSTRLEN]; const char* end = RtlIpv6AddressToStringA((const IN6_ADDR*) address->Address, ipStr); ffStrbufSetNS(&user->clientIp, (uint32_t) (end - ipStr), ipStr); } WTSFreeMemory(address); } bytes = 0; PWTSINFOW wtsInfo = NULL; if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSSessionInfo, (LPWSTR*) &wtsInfo, &bytes)) { user->loginTime = ffFileTimeToUnixMs((uint64_t) wtsInfo->LogonTime.QuadPart); WTSFreeMemory(wtsInfo); } } WTSFreeMemoryExW(WTSTypeSessionInfoLevel1, sessionInfo, 1); return NULL; }