Re: [Qemu-devel] [PATCH v4 1/1] qga: Add 'guest-get-users' command
> On Apr 14, 2017, at 12:09 AM, Michael Roth wrote: > > Quoting Vinzenz 'evilissimo' Feenstra (2017-04-13 05:41:17) >> From: Vinzenz Feenstra >> >> 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 >> --- >> configure | 2 +- >> include/glib-compat.h | 5 +++ >> qga/commands-posix.c | 52 ++ >> qga/commands-win32.c | 89 >> +++ >> qga/qapi-schema.json | 24 ++ >> 5 files changed, 171 insertions(+), 1 deletion(-) >> >> diff --git a/configure b/configure >> index be4d326..55e6654 100755 >> --- a/configure >> +++ b/configure >> @@ -742,7 +742,7 @@ if test "$mingw32" = "yes" ; then >> sysconfdir="\${prefix}" >> local_statedir= >> confsuffix="" >> - libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga" >> + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 >> $libs_qga" >> fi >> >> werror="" >> diff --git a/include/glib-compat.h b/include/glib-compat.h >> index 863c8cf..f8ee9dc 100644 >> --- a/include/glib-compat.h >> +++ b/include/glib-compat.h >> @@ -217,6 +217,11 @@ static inline void g_hash_table_add(GHashTable >> *hash_table, gpointer key) >> { >> g_hash_table_replace(hash_table, key, key); >> } >> + >> +static gboolean g_hash_table_contains(GHashTable *hash_table, gpointer key) >> +{ >> +return g_hash_table_lookup_extended(hash_table, key, NULL, NULL); >> +} >> #endif >> >> #ifndef g_assert_true >> diff --git a/qga/commands-posix.c b/qga/commands-posix.c >> index 915df9e..4a59988 100644 >> --- a/qga/commands-posix.c >> +++ b/qga/commands-posix.c >> @@ -15,6 +15,7 @@ >> #include >> #include >> #include >> +#include >> #include "qga/guest-agent-core.h" >> #include "qga-qmp-commands.h" >> #include "qapi/qmp/qerror.h" >> @@ -2517,3 +2518,54 @@ void ga_command_state_init(GAState *s, GACommandState >> *cs) >> ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); >> #endif >> } >> + >> +#define QGA_MICRO_SECOND_TO_SECOND 100 >> + >> +static double ga_get_login_time(struct utmpx *user_info) >> +{ >> +double seconds = (double)user_info->ut_tv.tv_sec; >> +double useconds = (double)user_info->ut_tv.tv_usec; >> +useconds /= QGA_MICRO_SECOND_TO_SECOND; >> +return seconds + useconds; >> +} >> + >> +GuestUserList *qmp_guest_get_users(Error **err) >> +{ >> +GHashTable *cache = g_hash_table_new(g_str_hash, g_str_equal); >> +GuestUserList *head = NULL, *cur_item = NULL; >> +setutxent(); >> +for (;;) { >> +struct utmpx *user_info = getutxent(); >> +if (user_info == NULL) { >> +break; >> +} else if (user_info->ut_type != USER_PROCESS) { >> +continue; >> +} else if (g_hash_table_contains(cache, user_info->ut_user)) { >> +gpointer value = g_hash_table_lookup(cache, user_info->ut_user); >> +GuestUser *user = (GuestUser *)value; >> +double login_time = ga_get_login_time(user_info); >> +/* We're ensuring the earliest login time to be sent */ >> +if (login_time < user->login_time) { >> +user->login_time = login_time; >> +} >> +continue; >> +} >> + >> +GuestUserList *item = g_new0(GuestUserList, 1); >> +item->value = g_new0(GuestUser, 1); >> +item->value->user = g_strdup(user_info->ut_user); >> +item->value->login_time = ga_get_login_time(user_info); >> + >> +g_hash_table_insert(cache, item->value->user, item->value); >> + >> +if (!cur_item) { >> +head = cur_item = item; >> +} else { >> +cur_item->next = item; >> +cur_item = item; >> +} >> +} >> +endutxent(); >> +g_hash_table_destroy(cache); >> +return head; >> +} >> diff --git a/qga/commands-win32.c b/qga/commands-win32.c >> index 19d72b2..8b84a90 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 >> #include >> @@ -25,6 +28,7 @@ >> #include >> #endif >> #include >> +#include >> >> #include "qga/guest-agent-core.h" >> #include "qga/vss-win32.h" >> @@ -1536,3 +1540,88 @@ void ga_command_state_init(GAState *s, GACommandState >> *cs) >> ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); >> } >> } >> + >> +/* MINGW is missing two fields: IncomingFrames & Outg
Re: [Qemu-devel] [PATCH v4 1/1] qga: Add 'guest-get-users' command
Quoting Vinzenz 'evilissimo' Feenstra (2017-04-13 05:41:17) > From: Vinzenz Feenstra > > 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 > --- > configure | 2 +- > include/glib-compat.h | 5 +++ > qga/commands-posix.c | 52 ++ > qga/commands-win32.c | 89 > +++ > qga/qapi-schema.json | 24 ++ > 5 files changed, 171 insertions(+), 1 deletion(-) > > diff --git a/configure b/configure > index be4d326..55e6654 100755 > --- a/configure > +++ b/configure > @@ -742,7 +742,7 @@ if test "$mingw32" = "yes" ; then >sysconfdir="\${prefix}" >local_statedir= >confsuffix="" > - libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga" > + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 > $libs_qga" > fi > > werror="" > diff --git a/include/glib-compat.h b/include/glib-compat.h > index 863c8cf..f8ee9dc 100644 > --- a/include/glib-compat.h > +++ b/include/glib-compat.h > @@ -217,6 +217,11 @@ static inline void g_hash_table_add(GHashTable > *hash_table, gpointer key) > { > g_hash_table_replace(hash_table, key, key); > } > + > +static gboolean g_hash_table_contains(GHashTable *hash_table, gpointer key) > +{ > +return g_hash_table_lookup_extended(hash_table, key, NULL, NULL); > +} > #endif > > #ifndef g_assert_true > diff --git a/qga/commands-posix.c b/qga/commands-posix.c > index 915df9e..4a59988 100644 > --- a/qga/commands-posix.c > +++ b/qga/commands-posix.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > #include "qga/guest-agent-core.h" > #include "qga-qmp-commands.h" > #include "qapi/qmp/qerror.h" > @@ -2517,3 +2518,54 @@ void ga_command_state_init(GAState *s, GACommandState > *cs) > ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); > #endif > } > + > +#define QGA_MICRO_SECOND_TO_SECOND 100 > + > +static double ga_get_login_time(struct utmpx *user_info) > +{ > +double seconds = (double)user_info->ut_tv.tv_sec; > +double useconds = (double)user_info->ut_tv.tv_usec; > +useconds /= QGA_MICRO_SECOND_TO_SECOND; > +return seconds + useconds; > +} > + > +GuestUserList *qmp_guest_get_users(Error **err) > +{ > +GHashTable *cache = g_hash_table_new(g_str_hash, g_str_equal); > +GuestUserList *head = NULL, *cur_item = NULL; > +setutxent(); > +for (;;) { > +struct utmpx *user_info = getutxent(); > +if (user_info == NULL) { > +break; > +} else if (user_info->ut_type != USER_PROCESS) { > +continue; > +} else if (g_hash_table_contains(cache, user_info->ut_user)) { > +gpointer value = g_hash_table_lookup(cache, user_info->ut_user); > +GuestUser *user = (GuestUser *)value; > +double login_time = ga_get_login_time(user_info); > +/* We're ensuring the earliest login time to be sent */ > +if (login_time < user->login_time) { > +user->login_time = login_time; > +} > +continue; > +} > + > +GuestUserList *item = g_new0(GuestUserList, 1); > +item->value = g_new0(GuestUser, 1); > +item->value->user = g_strdup(user_info->ut_user); > +item->value->login_time = ga_get_login_time(user_info); > + > +g_hash_table_insert(cache, item->value->user, item->value); > + > +if (!cur_item) { > +head = cur_item = item; > +} else { > +cur_item->next = item; > +cur_item = item; > +} > +} > +endutxent(); > +g_hash_table_destroy(cache); > +return head; > +} > diff --git a/qga/commands-win32.c b/qga/commands-win32.c > index 19d72b2..8b84a90 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 > #include > @@ -25,6 +28,7 @@ > #include > #endif > #include > +#include > > #include "qga/guest-agent-core.h" > #include "qga/vss-win32.h" > @@ -1536,3 +1540,88 @@ 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; > +DW
Re: [Qemu-devel] [PATCH v4 1/1] qga: Add 'guest-get-users' command
Quoting Michael Roth (2017-04-13 15:30:06) > Quoting Vinzenz 'evilissimo' Feenstra (2017-04-13 05:41:17) > > From: Vinzenz Feenstra > > > > 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 > > Thanks, applied to qga tree with some minor whitespace fix-ups: > > https://github.com/mdroth/qemu/commits/qga Er, whoops, replied to the wrong patch sorry. > > > --- > > configure | 2 +- > > include/glib-compat.h | 5 +++ > > qga/commands-posix.c | 52 ++ > > qga/commands-win32.c | 89 > > +++ > > qga/qapi-schema.json | 24 ++ > > 5 files changed, 171 insertions(+), 1 deletion(-) > > > > diff --git a/configure b/configure > > index be4d326..55e6654 100755 > > --- a/configure > > +++ b/configure > > @@ -742,7 +742,7 @@ if test "$mingw32" = "yes" ; then > >sysconfdir="\${prefix}" > >local_statedir= > >confsuffix="" > > - libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga" > > + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 > > $libs_qga" > > fi > > > > werror="" > > diff --git a/include/glib-compat.h b/include/glib-compat.h > > index 863c8cf..f8ee9dc 100644 > > --- a/include/glib-compat.h > > +++ b/include/glib-compat.h > > @@ -217,6 +217,11 @@ static inline void g_hash_table_add(GHashTable > > *hash_table, gpointer key) > > { > > g_hash_table_replace(hash_table, key, key); > > } > > + > > +static gboolean g_hash_table_contains(GHashTable *hash_table, gpointer key) > > +{ > > +return g_hash_table_lookup_extended(hash_table, key, NULL, NULL); > > +} > > #endif > > > > #ifndef g_assert_true > > diff --git a/qga/commands-posix.c b/qga/commands-posix.c > > index 915df9e..4a59988 100644 > > --- a/qga/commands-posix.c > > +++ b/qga/commands-posix.c > > @@ -15,6 +15,7 @@ > > #include > > #include > > #include > > +#include > > #include "qga/guest-agent-core.h" > > #include "qga-qmp-commands.h" > > #include "qapi/qmp/qerror.h" > > @@ -2517,3 +2518,54 @@ void ga_command_state_init(GAState *s, > > GACommandState *cs) > > ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); > > #endif > > } > > + > > +#define QGA_MICRO_SECOND_TO_SECOND 100 > > + > > +static double ga_get_login_time(struct utmpx *user_info) > > +{ > > +double seconds = (double)user_info->ut_tv.tv_sec; > > +double useconds = (double)user_info->ut_tv.tv_usec; > > +useconds /= QGA_MICRO_SECOND_TO_SECOND; > > +return seconds + useconds; > > +} > > + > > +GuestUserList *qmp_guest_get_users(Error **err) > > +{ > > +GHashTable *cache = g_hash_table_new(g_str_hash, g_str_equal); > > +GuestUserList *head = NULL, *cur_item = NULL; > > +setutxent(); > > +for (;;) { > > +struct utmpx *user_info = getutxent(); > > +if (user_info == NULL) { > > +break; > > +} else if (user_info->ut_type != USER_PROCESS) { > > +continue; > > +} else if (g_hash_table_contains(cache, user_info->ut_user)) { > > +gpointer value = g_hash_table_lookup(cache, > > user_info->ut_user); > > +GuestUser *user = (GuestUser *)value; > > +double login_time = ga_get_login_time(user_info); > > +/* We're ensuring the earliest login time to be sent */ > > +if (login_time < user->login_time) { > > +user->login_time = login_time; > > +} > > +continue; > > +} > > + > > +GuestUserList *item = g_new0(GuestUserList, 1); > > +item->value = g_new0(GuestUser, 1); > > +item->value->user = g_strdup(user_info->ut_user); > > +item->value->login_time = ga_get_login_time(user_info); > > + > > +g_hash_table_insert(cache, item->value->user, item->value); > > + > > +if (!cur_item) { > > +head = cur_item = item; > > +} else { > > +cur_item->next = item; > > +cur_item = item; > > +} > > +} > > +endutxent(); > > +g_hash_table_destroy(cache); > > +return head; > > +} > > diff --git a/qga/commands-win32.c b/qga/commands-win32.c > > index 19d72b2..8b84a90 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 > > #include > > @@ -25,6 +28,7 @@ > > #include > > #end
Re: [Qemu-devel] [PATCH v4 1/1] qga: Add 'guest-get-users' command
Quoting Vinzenz 'evilissimo' Feenstra (2017-04-13 05:41:17) > From: Vinzenz Feenstra > > 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 Thanks, applied to qga tree with some minor whitespace fix-ups: https://github.com/mdroth/qemu/commits/qga > --- > configure | 2 +- > include/glib-compat.h | 5 +++ > qga/commands-posix.c | 52 ++ > qga/commands-win32.c | 89 > +++ > qga/qapi-schema.json | 24 ++ > 5 files changed, 171 insertions(+), 1 deletion(-) > > diff --git a/configure b/configure > index be4d326..55e6654 100755 > --- a/configure > +++ b/configure > @@ -742,7 +742,7 @@ if test "$mingw32" = "yes" ; then >sysconfdir="\${prefix}" >local_statedir= >confsuffix="" > - libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga" > + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 > $libs_qga" > fi > > werror="" > diff --git a/include/glib-compat.h b/include/glib-compat.h > index 863c8cf..f8ee9dc 100644 > --- a/include/glib-compat.h > +++ b/include/glib-compat.h > @@ -217,6 +217,11 @@ static inline void g_hash_table_add(GHashTable > *hash_table, gpointer key) > { > g_hash_table_replace(hash_table, key, key); > } > + > +static gboolean g_hash_table_contains(GHashTable *hash_table, gpointer key) > +{ > +return g_hash_table_lookup_extended(hash_table, key, NULL, NULL); > +} > #endif > > #ifndef g_assert_true > diff --git a/qga/commands-posix.c b/qga/commands-posix.c > index 915df9e..4a59988 100644 > --- a/qga/commands-posix.c > +++ b/qga/commands-posix.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > #include "qga/guest-agent-core.h" > #include "qga-qmp-commands.h" > #include "qapi/qmp/qerror.h" > @@ -2517,3 +2518,54 @@ void ga_command_state_init(GAState *s, GACommandState > *cs) > ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); > #endif > } > + > +#define QGA_MICRO_SECOND_TO_SECOND 100 > + > +static double ga_get_login_time(struct utmpx *user_info) > +{ > +double seconds = (double)user_info->ut_tv.tv_sec; > +double useconds = (double)user_info->ut_tv.tv_usec; > +useconds /= QGA_MICRO_SECOND_TO_SECOND; > +return seconds + useconds; > +} > + > +GuestUserList *qmp_guest_get_users(Error **err) > +{ > +GHashTable *cache = g_hash_table_new(g_str_hash, g_str_equal); > +GuestUserList *head = NULL, *cur_item = NULL; > +setutxent(); > +for (;;) { > +struct utmpx *user_info = getutxent(); > +if (user_info == NULL) { > +break; > +} else if (user_info->ut_type != USER_PROCESS) { > +continue; > +} else if (g_hash_table_contains(cache, user_info->ut_user)) { > +gpointer value = g_hash_table_lookup(cache, user_info->ut_user); > +GuestUser *user = (GuestUser *)value; > +double login_time = ga_get_login_time(user_info); > +/* We're ensuring the earliest login time to be sent */ > +if (login_time < user->login_time) { > +user->login_time = login_time; > +} > +continue; > +} > + > +GuestUserList *item = g_new0(GuestUserList, 1); > +item->value = g_new0(GuestUser, 1); > +item->value->user = g_strdup(user_info->ut_user); > +item->value->login_time = ga_get_login_time(user_info); > + > +g_hash_table_insert(cache, item->value->user, item->value); > + > +if (!cur_item) { > +head = cur_item = item; > +} else { > +cur_item->next = item; > +cur_item = item; > +} > +} > +endutxent(); > +g_hash_table_destroy(cache); > +return head; > +} > diff --git a/qga/commands-win32.c b/qga/commands-win32.c > index 19d72b2..8b84a90 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 > #include > @@ -25,6 +28,7 @@ > #include > #endif > #include > +#include > > #include "qga/guest-agent-core.h" > #include "qga/vss-win32.h" > @@ -1536,3 +1540,88 @@ 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_CON
[Qemu-devel] [PATCH v4 1/1] qga: Add 'guest-get-users' command
From: Vinzenz Feenstra 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 --- configure | 2 +- include/glib-compat.h | 5 +++ qga/commands-posix.c | 52 ++ qga/commands-win32.c | 89 +++ qga/qapi-schema.json | 24 ++ 5 files changed, 171 insertions(+), 1 deletion(-) diff --git a/configure b/configure index be4d326..55e6654 100755 --- a/configure +++ b/configure @@ -742,7 +742,7 @@ if test "$mingw32" = "yes" ; then sysconfdir="\${prefix}" local_statedir= confsuffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi -lnetapi32 $libs_qga" + libs_qga="-lws2_32 -lwinmm -lpowrprof -lwtsapi32 -liphlpapi -lnetapi32 $libs_qga" fi werror="" diff --git a/include/glib-compat.h b/include/glib-compat.h index 863c8cf..f8ee9dc 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -217,6 +217,11 @@ static inline void g_hash_table_add(GHashTable *hash_table, gpointer key) { g_hash_table_replace(hash_table, key, key); } + +static gboolean g_hash_table_contains(GHashTable *hash_table, gpointer key) +{ +return g_hash_table_lookup_extended(hash_table, key, NULL, NULL); +} #endif #ifndef g_assert_true diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 915df9e..4a59988 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -2517,3 +2518,54 @@ void ga_command_state_init(GAState *s, GACommandState *cs) ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); #endif } + +#define QGA_MICRO_SECOND_TO_SECOND 100 + +static double ga_get_login_time(struct utmpx *user_info) +{ +double seconds = (double)user_info->ut_tv.tv_sec; +double useconds = (double)user_info->ut_tv.tv_usec; +useconds /= QGA_MICRO_SECOND_TO_SECOND; +return seconds + useconds; +} + +GuestUserList *qmp_guest_get_users(Error **err) +{ +GHashTable *cache = g_hash_table_new(g_str_hash, g_str_equal); +GuestUserList *head = NULL, *cur_item = NULL; +setutxent(); +for (;;) { +struct utmpx *user_info = getutxent(); +if (user_info == NULL) { +break; +} else if (user_info->ut_type != USER_PROCESS) { +continue; +} else if (g_hash_table_contains(cache, user_info->ut_user)) { +gpointer value = g_hash_table_lookup(cache, user_info->ut_user); +GuestUser *user = (GuestUser *)value; +double login_time = ga_get_login_time(user_info); +/* We're ensuring the earliest login time to be sent */ +if (login_time < user->login_time) { +user->login_time = login_time; +} +continue; +} + +GuestUserList *item = g_new0(GuestUserList, 1); +item->value = g_new0(GuestUser, 1); +item->value->user = g_strdup(user_info->ut_user); +item->value->login_time = ga_get_login_time(user_info); + +g_hash_table_insert(cache, item->value->user, item->value); + +if (!cur_item) { +head = cur_item = item; +} else { +cur_item->next = item; +cur_item = item; +} +} +endutxent(); +g_hash_table_destroy(cache); +return head; +} diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 19d72b2..8b84a90 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 #include @@ -25,6 +28,7 @@ #include #endif #include +#include #include "qga/guest-agent-core.h" #include "qga/vss-win32.h" @@ -1536,3 +1540,88 @@ 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; +