VBoxServiceVMInfo.cpp revision f65e6cba3e74ffd3dc9e6053828dcc82b367e8de
/* $Id$ */
/** @file
* VBoxVMInfo - Virtual machine (guest) information for the host.
*/
/*
* Copyright (C) 2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#ifdef RT_OS_WINDOWS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <Ntsecapi.h>
#else
# define __STDC_LIMIT_MACROS
# include <errno.h>
# include <unistd.h>
# include <utmp.h>
# ifdef RT_OS_SOLARIS
# endif
#endif
#include <iprt/semaphore.h>
#include <VBox/VBoxGuestLib.h>
#include "VBoxServiceInternal.h"
#include "VBoxServiceUtils.h"
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** The vminfo interval (millseconds). */
uint32_t g_VMInfoInterval = 0;
/** The semaphore we're blocking on. */
/** The guest property service client ID. */
static uint32_t g_VMInfoGuestPropSvcClientID = 0;
/** Number of logged in users in OS. */
#ifdef RT_OS_WINDOWS
/** Function prototypes for dynamic loading. */
/** External functions. */
#endif
/** @copydoc VBOXSERVICE::pfnPreInit */
static DECLCALLBACK(int) VBoxServiceVMInfoPreInit(void)
{
return VINF_SUCCESS;
}
/** @copydoc VBOXSERVICE::pfnOption */
static DECLCALLBACK(int) VBoxServiceVMInfoOption(const char **ppszShort, int argc, char **argv, int *pi)
{
int rc = -1;
if (ppszShort)
/* no short options */;
return rc;
}
/** @copydoc VBOXSERVICE::pfnInit */
static DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
{
/*
* If not specified, find the right interval default.
* Then create the event sem to block on.
*/
if (!g_VMInfoInterval)
if (!g_VMInfoInterval)
#ifdef RT_OS_WINDOWS
/* Get function pointers. */
{
g_pfnWTSGetActiveConsoleSessionId = (fnWTSGetActiveConsoleSessionId)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");
}
#endif
if (RT_SUCCESS(rc))
else
{
}
return rc;
}
/** @copydoc VBOXSERVICE::pfnWorker */
{
int rc = VINF_SUCCESS;
/*
* Tell the control thread that it can continue
* spawning services.
*/
#ifdef RT_OS_WINDOWS
/* Required for network information (must be called per thread). */
}
#endif /* !RT_OS_WINDOWS */
/* First get information that won't change while the OS is running. */
char szInfo[256] = {0};
/* Retrieve version information about Guest Additions and installed files (components). */
#ifdef RT_OS_WINDOWS
#else
/* VboxServiceGetAddsVersion !RT_OS_WINDOWS */
char szRevision[32];
#endif
/* Now enter the loop retrieving runtime data continuously. */
unsigned cErrors = 0;
for (;;)
{
/* Enumerate logged in users. */
uint32_t uiUserCount = 0;
char szUserList[4096] = {0};
#ifdef RT_OS_WINDOWS
#ifndef TARGET_NT4
NTSTATUS r = 0;
/* This function can report stale or orphaned interactive logon sessions of already logged
off users (especially in Windows 2000). */
if (r != STATUS_SUCCESS)
{
return 1;
}
for (int i = 0; i<(int)ulCount; i++)
{
{
if (uiUserCount > 0)
uiUserCount++;
}
}
#endif /* TARGET_NT4 */
#elif defined(RT_OS_FREEBSD)
/* TODO: Port me */
#else
if (rc != 0)
{
}
setutent();
{
/* Make sure we don't add user names which are not
* part of type USER_PROCESS and don't add same users twice. */
{
/** @todo Do we really want to filter out double user names? (Same user logged in twice) */
if (uiUserCount > 0)
uiUserCount++;
}
}
endutent();
#endif /* !RT_OS_WINDOWS */
VboxServiceWriteProp(g_VMInfoGuestPropSvcClientID, "GuestInfo/OS/LoggedInUsersList", (uiUserCount > 0) ? szUserList : NULL);
{
/* Update this property ONLY if there is a real change from no users to
* users or vice versa. The only exception is that the initialization
* forces an update, but only once. This ensures consistent property
* settings even if the VM aborted previously. */
if (uiUserCount == 0)
else if (g_VMInfoLoggedInUsers == 0)
}
/* Get network configuration. */
int nNumInterfaces = 0;
#ifdef RT_OS_WINDOWS
{
return -1;
}
unsigned long nBytesReturned = 0;
0,
0,
sizeof(InterfaceList),
0,
0) == SOCKET_ERROR)
{
return -1;
}
#else
if (sd < 0) /* Socket invalid. */
{
return -1;
}
char buffer[1024] = {0};
{
return -1;
}
#endif
char szPropPath [FILENAME_MAX] = {0};
char szTemp [FILENAME_MAX] = {0};
int iCurIface = 0;
VboxServiceWritePropInt(g_VMInfoGuestPropSvcClientID, szPropPath, (nNumInterfaces > 1 ? nNumInterfaces-1 : 0));
/** @todo Use GetAdaptersInfo() and GetAdapterAddresses (IPv4 + IPv6) for more information. */
for (int i = 0; i < nNumInterfaces; ++i)
{
#ifdef RT_OS_WINDOWS
continue;
#else
{
return -1;
}
continue;
#endif
#ifdef RT_OS_WINDOWS
#else
{
return -1;
}
#endif
#ifdef RT_OS_WINDOWS
#else
{
return -1;
}
#if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
#else
#endif
#endif
else
iCurIface++;
}
#ifdef RT_OS_WINDOWS
#else
#endif /* !RT_OS_WINDOWS */
/*
* Block for a while.
*
* The event semaphore takes care of ignoring interruptions and it
* allows us to implement service wakeup later.
*/
if (*pfShutdown)
break;
if (*pfShutdown)
break;
{
break;
}
}
#ifdef RT_OS_WINDOWS
WSACleanup();
#endif /* !RT_OS_WINDOWS */
return rc;
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceVMInfoStop(void)
{
}
/** @copydoc VBOXSERVICE::pfnTerm */
static DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
{
int rc;
if (g_VMInfoEvent != NIL_RTSEMEVENTMULTI)
{
/** @todo temporary solution: Zap all values which are not valid
* be replaced with "temporary properties" later.
*
* @todo r=bird: This code isn't called on non-Windows systems. We need
* a more formal way of shutting down the service for that to work.
*/
if (g_VMInfoLoggedInUsers > 0)
/* Disconnect from guest properties service. */
if (RT_FAILURE(rc))
}
}
/**
* The 'vminfo' service description.
*/
{
/* pszName. */
"vminfo",
/* pszDescription. */
"Virtual Machine Information",
/* pszUsage. */
"[--vminfo-interval <ms>]"
,
/* pszOptions. */
" --vminfo-interval Specifies the interval at which to retrieve the\n"
" VM information. The default is 10000 ms.\n"
,
/* methods */
};