VBoxServiceVMInfo-win.cpp revision 1222ff94540f6426532c1f1714f0717fdcf92e46
/* $Id$ */
/** @file
* VBoxVMInfo-win - 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 *
*******************************************************************************/
#include <windows.h>
#include <Ntsecapi.h>
#include <wtsapi32.h> /* For WTS* calls. */
#include <psapi.h> /* EnumProcesses. */
#include <iprt/semaphore.h>
#include <VBox/VBoxGuestLib.h>
#include "VBoxServiceInternal.h"
#include "VBoxServiceUtils.h"
/*******************************************************************************
* Global Variables *
*******************************************************************************/
#ifndef TARGET_NT4
/** Function prototypes for dynamic loading. */
/** The vminfo interval (millseconds). */
#endif
#ifndef TARGET_NT4
/* Function GetLUIDsFromProcesses() written by Stefan Kuhr. */
{
if (!ppLuid)
{
return 0L;
}
/* Call the PSAPI function EnumProcesses to get all of the
ProcID's currently in the system.
NOTE: In the documentation, the third parameter of
EnumProcesses is named cbNeeded, which implies that you
can call the function once to find out how much space to
allocate for a buffer and again to fill the buffer.
This is not the case. The cbNeeded parameter returns
the number of PIDs returned, so if your buffer size is
zero cbNeeded returns zero.
NOTE: The "HeapAlloc" loop here ensures that we
actually allocate a buffer large enough for all the
PIDs in the system. */
do
{
if (lpdwPIDs)
{
dwSize2 *= 2;
}
return 0L; // Last error will be that of HeapAlloc
{
return 0L;
}
}
/* At this point we have an array of the PIDs at the
time of the last EnumProcesses invocation. We will
allocate an array of LUIDs passed back via the out
param ppLuid of exactly the number of PIDs. We will
only fill the first n values of this array, with n
being the number of unique LUIDs found in these PIDs. */
/* How many ProcIDs did we get? */
dwSize2 = 0L; /* Our return value of found luids. */
if (!(*ppLuid))
{
dwLastError = GetLastError();
goto CLEANUP;
}
{
/* Open the process (if we can... security does not
permit every process in the system). */
{
{
{
if (!bFound)
}
}
}
/* We don't really care if OpenProcess or OpenProcessToken fail or succeed, because
there are quite a number of system processes we cannot open anyway, not even as SYSTEM. */
}
if (lpdwPIDs)
if (ERROR_SUCCESS !=dwLastError)
return dwSize2;
}
{
NTSTATUS r = 0;
int iLength = 0;
if (!a_pSession)
return FALSE;
if (r != STATUS_SUCCESS)
{
if (sessionData)
return FALSE;
}
if (!sessionData)
{
VBoxServiceError("Invalid logon session data.\n");
return FALSE;
}
(sessionData->UserName).Buffer, (sessionData->UserName).Length, (sessionData->Sid != NULL) ? "1" : "0", sessionData->LogonId.HighPart, sessionData->LogonId.LowPart);
{
/* Get the user name. */
if (iLength > sizeof(a_pUserInfo->szUser) - sizeof(TCHAR)) /* -sizeof(TCHAR) because we have to add the terminating null char at the end later. */
{
VBoxServiceVerbose(0, "User name too long (%d bytes) for buffer! Name will be truncated.\n", iLength);
}
/* Get authentication package. */
if (iLength > sizeof(a_pUserInfo->szAuthenticationPackage) - sizeof(TCHAR)) /* -sizeof(TCHAR) because we have to add the terminating null char at the end later. */
{
VBoxServiceVerbose(0, "Authentication pkg name too long (%d bytes) for buffer! Name will be truncated.\n", iLength);
}
/* Get logon domain. */
if (iLength > sizeof(a_pUserInfo->szLogonDomain) - sizeof(TCHAR)) /* -sizeof(TCHAR) because we have to add the terminating null char at the end later. */
{
VBoxServiceVerbose(0, "Logon domain name too long (%d bytes) for buffer! Name will be truncated.\n", iLength);
}
/* Only handle users which can login interactively or logged in remotely over native RDP. */
{
if (LookupAccountSid(NULL,
&ownerType))
{
a_pUserInfo->szUser, sessionData->Session, sessionData->LogonId.HighPart, sessionData->LogonId.LowPart, a_pUserInfo->szAuthenticationPackage, a_pUserInfo->szLogonDomain);
/* The session ID increments/decrements on Vista often! So don't compare
the session data SID with the current SID here. */
DWORD dwActiveSession = 0;
/*VBoxServiceVerbose(3, ("Users: Current active session ID: %ld\n", dwActiveSession));*/
if (SidTypeUser == ownerType)
{
DWORD dwBytesRet = 0;
int iState = 0;
if (WTSQuerySessionInformation( /* Detect RDP sessions as well. */
&pBuffer,
&dwBytesRet))
{
/*VBoxServiceVerbose(3, ("Users: WTSQuerySessionInformation returned %ld bytes, p=%p, state=%d\n", dwBytesRet, pBuffer, pBuffer != NULL ? (INT)*pBuffer : -1));*/
if(dwBytesRet)
{
/** @todo On Vista and W2K, always "old" user name are still
* there. Filter out the old one! */
VBoxServiceVerbose(3, "Users: Account User=%ls is logged in via TCS/RDP. State=%d\n", a_pUserInfo->szUser, iState);
bFoundUser = TRUE;
}
}
else
{
/* Terminal services don't run (for example in W2K, nothing to worry about ...). */
/* ... or is on Vista fast user switching page! */
bFoundUser = TRUE;
}
if (pBuffer)
{
{
break;
}
}
}
}
}
}
return bLoggedIn;
}
#endif /* TARGET_NT4 */
{
long rc = 0;
/* Check the new path first. */
rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Sun\\VirtualBox Guest Additions", 0, KEY_READ, &hKey);
if (rc != ERROR_SUCCESS)
{
/* New path does not exist, check the old one ... */
rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Sun\\xVM VirtualBox Guest Additions", 0, KEY_READ, &hKey);
if (rc != ERROR_SUCCESS)
{
/* Nothing seems to exist, print some warning. */
return 1;
}
}
/* Installation directory. */
{
RegCloseKey (hKey);
return 1;
}
/* Flip slashes. */
if (*pszTmp == '\\')
*pszTmp = '/';
/* Revision. */
{
RegCloseKey (hKey);
return 1;
}
/* Version. */
{
RegCloseKey (hKey);
return 1;
}
/* Write information to host. */
RegCloseKey (hKey);
return VINF_SUCCESS;
}
{
int rc;
char szPropPath[_MAX_PATH] = {0};
/* The file information table. */
#ifndef TARGET_NT4
{
{
}
};
#else /* File lookup for NT4. */
{
{
}
};
#endif
while (pTable->pszFileName)
{
rc = VboxServiceGetFileVersionString(pTable->pszFilePath, pTable->pszFileName, szVer, sizeof(szVer));
pTable++;
}
return VINF_SUCCESS;
}