diff options
author | Vinzenz Feenstra <vfeenstr@redhat.com> | 2017-04-19 11:26:15 +0200 |
---|---|---|
committer | Michael Roth <mdroth@linux.vnet.ibm.com> | 2017-04-26 23:57:45 -0500 |
commit | 161a56a9065feb6fa2f69cec6237a5c4e714b9d3 (patch) | |
tree | e1c26dd740444144d8d0f92f2e7726b51b4d8777 /qga/commands-win32.c | |
parent | 1dbfbc17fe783e34644daf4abbb8f4e17344abcd (diff) |
qga: Add 'guest-get-users' command
A command that will list all currently logged in users, and the time
since when they are logged in.
Examples:
virsh # qemu-agent-command F25 '{ "execute": "guest-get-users" }'
{"return":[{"login-time":1490622289.903835,"user":"root"}]}
virsh # qemu-agent-command Win2k12r2 '{ "execute": "guest-get-users" }'
{"return":[{"login-time":1490351044.670552,"domain":"LADIDA",
"user":"Administrator"}]}
Signed-off-by: Vinzenz Feenstra <vfeenstr@redhat.com>
* make g_hash_table_contains compat func inline to avoid
unused warnings
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Diffstat (limited to 'qga/commands-win32.c')
-rw-r--r-- | qga/commands-win32.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 9fec1fb638..439d229225 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -11,6 +11,9 @@ * See the COPYING file in the top-level directory. */ +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +#endif #include "qemu/osdep.h" #include <wtypes.h> #include <powrprof.h> @@ -25,6 +28,7 @@ #include <initguid.h> #endif #include <lm.h> +#include <wtsapi32.h> #include "qga/guest-agent-core.h" #include "qga/vss-win32.h" @@ -1536,3 +1540,102 @@ void ga_command_state_init(GAState *s, GACommandState *cs) ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); } } + +/* MINGW is missing two fields: IncomingFrames & OutgoingFrames */ +typedef struct _GA_WTSINFOA { + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBy; + 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; + +} GA_WTSINFOA; + +GuestUserList *qmp_guest_get_users(Error **err) +{ +#if (_WIN32_WINNT >= 0x0600) +#define QGA_NANOSECONDS 10000000 + + GHashTable *cache = NULL; + GuestUserList *head = NULL, *cur_item = NULL; + + DWORD buffer_size = 0, count = 0, i = 0; + GA_WTSINFOA *info = NULL; + WTS_SESSION_INFOA *entries = NULL; + GuestUserList *item = NULL; + GuestUser *user = NULL; + gpointer value = NULL; + INT64 login = 0; + double login_time = 0; + + cache = g_hash_table_new(g_str_hash, g_str_equal); + + if (WTSEnumerateSessionsA(NULL, 0, 1, &entries, &count)) { + for (i = 0; i < count; ++i) { + buffer_size = 0; + info = NULL; + if (WTSQuerySessionInformationA( + NULL, + entries[i].SessionId, + WTSSessionInfo, + (LPSTR *)&info, + &buffer_size + )) { + + if (strlen(info->UserName) == 0) { + WTSFreeMemory(info); + continue; + } + + login = info->LogonTime.QuadPart; + login -= W32_FT_OFFSET; + login_time = ((double)login) / QGA_NANOSECONDS; + + if (g_hash_table_contains(cache, info->UserName)) { + value = g_hash_table_lookup(cache, info->UserName); + user = (GuestUser *)value; + if (user->login_time > login_time) { + user->login_time = login_time; + } + } else { + item = g_new0(GuestUserList, 1); + item->value = g_new0(GuestUser, 1); + + item->value->user = g_strdup(info->UserName); + item->value->domain = g_strdup(info->Domain); + item->value->has_domain = true; + + item->value->login_time = login_time; + + g_hash_table_add(cache, item->value->user); + + if (!cur_item) { + head = cur_item = item; + } else { + cur_item->next = item; + cur_item = item; + } + } + } + WTSFreeMemory(info); + } + WTSFreeMemory(entries); + } + g_hash_table_destroy(cache); + return head; +#else + error_setg(err, QERR_UNSUPPORTED); + return NULL; +#endif +} |