summaryrefslogtreecommitdiff
path: root/src/VBox/Additions
diff options
context:
space:
mode:
authorMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
committerMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
commite13debb062071c46f2707d0d0e59c57675b49360 (patch)
tree922f54068563b5cf3274bae8ba8122ce4b4ede1d /src/VBox/Additions
parentabd0051802e55207e88435a185ff8d6e6b8d17d5 (diff)
downloadvirtualbox-upstream/3.2.2-dfsg.tar.gz
Imported Upstream version 3.2.2-dfsgupstream/3.2.2-dfsg
Diffstat (limited to 'src/VBox/Additions')
-rw-r--r--src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp6
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxService-win.cpp443
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxService.cpp203
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp57
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h97
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp293
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp26
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServicePropCache.h1
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp254
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp280
-rw-r--r--src/VBox/Additions/common/crOpenGL/Makefile.kmk8
-rw-r--r--src/VBox/Additions/common/crOpenGL/defs64.py479
-rwxr-xr-xsrc/VBox/Additions/linux/export_modules42
-rw-r--r--src/VBox/Additions/linux/sharedfolders/regops.c4
-rw-r--r--src/VBox/Additions/solaris/Installer/postinstall.sh14
-rw-r--r--src/VBox/Additions/x11/vboxmouse/xorg71/mouse.c3
16 files changed, 1573 insertions, 637 deletions
diff --git a/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp b/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
index 69bbf7beb..8e5ecbc91 100644
--- a/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
+++ b/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
@@ -1,4 +1,4 @@
-/* $Revision: 28800 $ */
+/* $Revision: 29680 $ */
/** @file
* VBoxGuestLib - Host-Guest Communication Manager internal functions, implemented by VBoxGuest
*/
@@ -45,7 +45,7 @@
* Defined Constants And Macros *
*******************************************************************************/
/** The max parameter buffer size for a user request. */
-#define VBGLR0_MAX_HGCM_USER_PARM (16*_1M)
+#define VBGLR0_MAX_HGCM_USER_PARM (24*_1M)
/** The max parameter buffer size for a kernel request. */
#define VBGLR0_MAX_HGCM_KERNEL_PARM (16*_1M)
#ifdef RT_OS_LINUX
@@ -770,7 +770,7 @@ static int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VM
/*
* Copy back parameters.
*/
- for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++)
+ for (iParm = 0; iParm < cParms; iParm++, pSrcParm++, pDstParm++)
{
switch (pDstParm->type)
{
diff --git a/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp b/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
index 3fc1eb3b2..5e13afece 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
@@ -1,10 +1,10 @@
-/* $Id: VBoxService-win.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: VBoxService-win.cpp 29817 2010-05-26 13:54:41Z vboxsync $ */
/** @file
* VBoxService - Guest Additions Service Skeleton, Windows Specific Parts.
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -28,15 +28,25 @@
#include <process.h>
#include <aclapi.h>
-DWORD g_rcWinService = 0;
-SERVICE_STATUS_HANDLE g_hWinServiceStatus = NULL;
-void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv);
+/*******************************************************************************
+* Internal Functions *
+*******************************************************************************/
+static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv);
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+static DWORD g_dwWinServiceLastStatus = 0;
+SERVICE_STATUS_HANDLE g_hWinServiceStatus = NULL;
+/** The semaphore for the dummy Windows service. */
+static RTSEMEVENT g_WindowsEvent = NIL_RTSEMEVENT;
-static SERVICE_TABLE_ENTRY const g_aServiceTable[]=
+static SERVICE_TABLE_ENTRY const g_aServiceTable[] =
{
- {VBOXSERVICE_NAME, VBoxServiceWinMain},
- {NULL,NULL}
+ { VBOXSERVICE_NAME, vboxServiceWinMain },
+ { NULL, NULL}
};
@@ -45,13 +55,13 @@ static SERVICE_TABLE_ENTRY const g_aServiceTable[]=
* @todo Add full unicode support.
* @todo Add event log capabilities / check return values.
*/
-DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
- SE_OBJECT_TYPE ObjectType,
- LPTSTR pszTrustee,
- TRUSTEE_FORM TrusteeForm,
- DWORD dwAccessRights,
- ACCESS_MODE AccessMode,
- DWORD dwInheritance)
+static DWORD vboxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
+ SE_OBJECT_TYPE ObjectType,
+ LPTSTR pszTrustee,
+ TRUSTEE_FORM TrusteeForm,
+ DWORD dwAccessRights,
+ ACCESS_MODE AccessMode,
+ DWORD dwInheritance)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
@@ -71,7 +81,7 @@ DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
VBoxServiceError("AddAceToObjectsSecurityDescriptor: Object not found/installed: %s\n", pszObjName);
else
VBoxServiceError("AddAceToObjectsSecurityDescriptor: GetNamedSecurityInfo: Error %u\n", dwRes);
- goto Cleanup;
+ goto l_Cleanup;
}
/* Initialize an EXPLICIT_ACCESS structure for the new ACE. */
@@ -87,7 +97,7 @@ DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
if (ERROR_SUCCESS != dwRes)
{
VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetEntriesInAcl: Error %u\n", dwRes);
- goto Cleanup;
+ goto l_Cleanup;
}
/* Attach the new ACL as the object's DACL. */
@@ -97,11 +107,11 @@ DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
if (ERROR_SUCCESS != dwRes)
{
VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetNamedSecurityInfo: Error %u\n", dwRes);
- goto Cleanup;
+ goto l_Cleanup;
}
/** @todo get rid of that spaghetti jump ... */
-Cleanup:
+l_Cleanup:
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
@@ -113,17 +123,17 @@ Cleanup:
/** Reports our current status to the SCM. */
-BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
+static BOOL vboxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
{
- if (NULL == g_hWinServiceStatus) /* Program could be in testing mode, so no service environment available. */
+ if (g_hWinServiceStatus == NULL) /* Program could be in testing mode, so no service environment available. */
return FALSE;
VBoxServiceVerbose(2, "Setting service status to: %ld\n", dwStatus);
- g_rcWinService = dwStatus;
+ g_dwWinServiceLastStatus = dwStatus;
SERVICE_STATUS ss;
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ss.dwCurrentState = g_rcWinService;
+ ss.dwCurrentState = dwStatus;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ss.dwWin32ExitCode = NO_ERROR;
ss.dwServiceSpecificExitCode = 0; /* Not used */
@@ -134,157 +144,157 @@ BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
}
-int VBoxServiceWinSetDesc(SC_HANDLE hService)
+/**
+ * Reports SERVICE_STOP_PENDING to SCM.
+ *
+ * @param uCheckPoint Some number.
+ */
+void VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint)
{
+ vboxServiceWinSetStatus(SERVICE_STOP_PENDING, uCheckPoint);
+}
+
+
+static RTEXITCODE vboxServiceWinSetDesc(SC_HANDLE hService)
+{
+#ifndef TARGET_NT4
/* On W2K+ there's ChangeServiceConfig2() which lets us set some fields
like a longer service description. */
-#ifndef TARGET_NT4
- SERVICE_DESCRIPTION desc;
/** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */
- desc. lpDescription = VBOXSERVICE_DESCRIPTION;
- if (FALSE == ChangeServiceConfig2(hService,
- SERVICE_CONFIG_DESCRIPTION, /* Service info level */
- &desc))
+ SERVICE_DESCRIPTION desc;
+ desc.lpDescription = VBOXSERVICE_DESCRIPTION;
+ if (!ChangeServiceConfig2(hService,
+ SERVICE_CONFIG_DESCRIPTION, /* Service info level */
+ &desc))
{
VBoxServiceError("Cannot set the service description! Error: %ld\n", GetLastError());
- return 1;
+ return RTEXITCODE_FAILURE;
}
#endif
- return VINF_SUCCESS;
+ return RTEXITCODE_SUCCESS;
}
-/** Installs the service into the registry. */
-int VBoxServiceWinInstall(void)
+/**
+ * Installs the service.
+ */
+RTEXITCODE VBoxServiceWinInstall(void)
{
- SC_HANDLE hService, hSCManager;
- TCHAR imagePath[MAX_PATH] = { 0 };
-
- GetModuleFileName(NULL,imagePath,MAX_PATH);
VBoxServiceVerbose(1, "Installing service ...\n");
- hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ TCHAR imagePath[MAX_PATH] = { 0 };
+ GetModuleFileName(NULL, imagePath, sizeof(imagePath));
- if (NULL == hSCManager)
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSCManager == NULL)
{
VBoxServiceError("Could not open SCM! Error: %ld\n", GetLastError());
- return 1;
+ return RTEXITCODE_FAILURE;
}
- hService = ::CreateService (hSCManager,
- VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
- SERVICE_ALL_ACCESS,
- SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
- SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
- imagePath, NULL, NULL, NULL, NULL, NULL);
- int rc = VINF_SUCCESS;
- if (NULL == hService)
+ RTEXITCODE rc = RTEXITCODE_SUCCESS;
+ SC_HANDLE hService = CreateService(hSCManager,
+ VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
+ imagePath, NULL, NULL, NULL, NULL, NULL);
+ if (hService != NULL)
+ VBoxServiceVerbose(0, "Service successfully installed!\n");
+ else
{
DWORD dwErr = GetLastError();
switch (dwErr)
{
-
- case ERROR_SERVICE_EXISTS:
-
- VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n");
- hService = OpenService (hSCManager,
- VBOXSERVICE_NAME,
- SERVICE_ALL_ACCESS);
- if (NULL == hService)
- {
- VBoxServiceError("Could not open service! Error: %ld\n", GetLastError());
- rc = 1;
- }
- else
- {
- if (ChangeServiceConfig (hService,
- SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
- SERVICE_DEMAND_START,
- SERVICE_ERROR_NORMAL,
- imagePath,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- VBOXSERVICE_FRIENDLY_NAME))
+ case ERROR_SERVICE_EXISTS:
+ VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n");
+ hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS);
+ if (hService)
{
- VBoxServiceVerbose(1, "The service config has been successfully updated.\n");
+ if (ChangeServiceConfig (hService,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL,
+ imagePath,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ VBOXSERVICE_FRIENDLY_NAME))
+ VBoxServiceVerbose(1, "The service config has been successfully updated.\n");
+ else
+ rc = VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError());
}
else
- {
- VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError());
- rc = 1;
- }
- }
- break;
+ rc = VBoxServiceError("Could not open service! Error: %ld\n", GetLastError());
+ break;
- default:
-
- VBoxServiceError("Could not create service! Error: %ld\n", dwErr);
- rc = 1;
- break;
+ default:
+ rc = VBoxServiceError("Could not create service! Error: %ld\n", dwErr);
+ break;
}
}
- else
- {
- VBoxServiceVerbose(0, "Service successfully installed!\n");
- }
- if (RT_SUCCESS(rc))
- rc = VBoxServiceWinSetDesc(hService);
+ if (rc == RTEXITCODE_SUCCESS)
+ rc = vboxServiceWinSetDesc(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return rc;
}
-/** Uninstalls the service from the registry. */
-int VBoxServiceWinUninstall(void)
+/**
+ * Uninstalls the service.
+ */
+RTEXITCODE VBoxServiceWinUninstall(void)
{
- SC_HANDLE hService, hSCManager;
- hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
-
VBoxServiceVerbose(1, "Uninstalling service ...\n");
- if (NULL == hSCManager) {
+ SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
+ if (hSCManager == NULL)
+ {
VBoxServiceError("Could not open SCM! Error: %d\n", GetLastError());
- return 1;
- }
-
- hService = OpenService (hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
- if (NULL == hService) {
- VBoxServiceError("Could not open service! Error: %d\n", GetLastError());
- CloseServiceHandle (hSCManager);
- return 1;
+ return RTEXITCODE_FAILURE;
}
- if (FALSE == DeleteService (hService))
- {
- VBoxServiceError("Could not remove service! Error: %d\n", GetLastError());
- CloseServiceHandle (hService);
- CloseServiceHandle (hSCManager);
- return 1;
- }
- else
+ RTEXITCODE rcExit;
+ SC_HANDLE hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
+ if (hService != NULL)
{
- HKEY hKey = NULL;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
- RegDeleteKey(hKey, VBOXSERVICE_NAME);
- RegCloseKey(hKey);
- }
+ if (DeleteService(hService))
+ {
+ /*
+ * ???
+ */
+ HKEY hKey = NULL;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey)
+ == ERROR_SUCCESS)
+ {
+ RegDeleteKey(hKey, VBOXSERVICE_NAME);
+ RegCloseKey(hKey);
+ }
- VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
+ VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
+ rcExit = RTEXITCODE_SUCCESS;
+ }
+ else
+ rcExit = VBoxServiceError("Could not remove service! Error: %d\n", GetLastError());
+ CloseServiceHandle(hService);
}
-
- CloseServiceHandle(hService);
+ else
+ rcExit = VBoxServiceError("Could not open service! Error: %d\n", GetLastError());
CloseServiceHandle(hSCManager);
- return 0;
+ return rcExit;
}
-int VBoxServiceWinStart(void)
+static int vboxServiceWinStart(void)
{
int rc = VINF_SUCCESS;
@@ -293,52 +303,50 @@ int VBoxServiceWinStart(void)
PSID pBuiltinUsersSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY;
- if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
- SECURITY_LOCAL_RID,
- 0, 0, 0, 0, 0, 0, 0,
- &pBuiltinUsersSID))
+ if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
+ SECURITY_LOCAL_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &pBuiltinUsersSID))
{
+ /**@todo r=bird: rc = RTErrConvertFromWin32(GetLastError()); ?*/
VBoxServiceError("AllocateAndInitializeSid: Error %u\n", GetLastError());
}
else
{
- DWORD dwRes = VBoxServiceWinAddAceToObjectsSecurityDescriptor (TEXT("\\\\.\\VBoxMiniRdrDN"),
- SE_FILE_OBJECT,
- (LPTSTR)pBuiltinUsersSID,
- TRUSTEE_IS_SID,
- FILE_GENERIC_READ | FILE_GENERIC_WRITE,
- SET_ACCESS,
- NO_INHERITANCE);
+ DWORD dwRes = vboxServiceWinAddAceToObjectsSecurityDescriptor(TEXT("\\\\.\\VBoxMiniRdrDN"),
+ SE_FILE_OBJECT,
+ (LPTSTR)pBuiltinUsersSID,
+ TRUSTEE_IS_SID,
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+ SET_ACCESS,
+ NO_INHERITANCE);
if (dwRes != ERROR_SUCCESS)
{
if (dwRes == ERROR_FILE_NOT_FOUND)
{
/* If we don't find our "VBoxMiniRdrDN" (for Shared Folders) object above,
don't report an error; it just might be not installed. Otherwise this
- would cause the SCM to hang on starting up the service. */
+ would cause the SCM to hang on starting up the service. */
rc = VINF_SUCCESS;
}
- else rc = RTErrConvertFromWin32(dwRes);
+ else
+ rc = RTErrConvertFromWin32(dwRes);
}
}
#endif
if (RT_SUCCESS(rc))
{
- /* Notify SCM *before* we're starting the services, because the last services
- always starts in main thread (which causes the SCM to wait because of the non-responding
- service). */
- VBoxServiceWinSetStatus (SERVICE_RUNNING, 0);
-
- /*
- * Check that at least one service is enabled.
- */
- unsigned iMain = VBoxServiceGetStartedServices();
- rc = VBoxServiceStartServices(iMain); /* Start all the services. */
-
- if (RT_FAILURE(rc))
- VBoxServiceWinSetStatus (SERVICE_STOPPED, 0);
+ rc = VBoxServiceStartServices();
+ if (RT_SUCCESS(rc))
+ {
+ vboxServiceWinSetStatus(SERVICE_RUNNING, 0);
+ VBoxServiceMainWait();
+ }
+ else
+ vboxServiceWinSetStatus(SERVICE_STOPPED, 0);
}
+ /**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */
if (RT_FAILURE(rc))
VBoxServiceError("Service failed to start with rc=%Rrc!\n", rc);
@@ -347,103 +355,116 @@ int VBoxServiceWinStart(void)
}
+/**
+ * Call StartServiceCtrlDispatcher.
+ *
+ * The main() thread invokes this when not started in foreground mode. It
+ * won't return till the service is being shutdown (unless start up fails).
+ *
+ * @returns RTEXITCODE_SUCCESS on normal return after service shutdown.
+ * Something else on failure, error will have been reported.
+ */
+RTEXITCODE VBoxServiceWinEnterCtrlDispatcher(void)
+{
+ if (!StartServiceCtrlDispatcher(&g_aServiceTable[0]))
+ return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!",
+ GetLastError(), g_pszProgName);
+ return RTEXITCODE_SUCCESS;
+}
+
+
#ifdef TARGET_NT4
-VOID WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl)
+static VOID WINAPI vboxServiceWinCtrlHandler(DWORD dwControl)
#else
-DWORD WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl,
- DWORD dwEventType,
- LPVOID lpEventData,
- LPVOID lpContext)
+static DWORD WINAPI vboxServiceWinCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
#endif
{
- DWORD rc = NO_ERROR;
+ DWORD rcRet = NO_ERROR;
- VBoxServiceVerbose(2, "Control handler: Control=%ld\n", dwControl);
-#ifndef TARGET_NT4
- VBoxServiceVerbose(2, "Control handler: EventType=%ld\n", dwEventType);
+#ifdef TARGET_NT4
+ VBoxServiceVerbose(2, "Control handler: Control=%#x\n", dwControl);
+#else
+ VBoxServiceVerbose(2, "Control handler: Control=%#x EventType=%#x\n", dwControl, dwEventType);
#endif
switch (dwControl)
{
+ case SERVICE_CONTROL_INTERROGATE:
+ vboxServiceWinSetStatus(g_dwWinServiceLastStatus, 0);
+ break;
- case SERVICE_CONTROL_INTERROGATE:
- VBoxServiceWinSetStatus(g_rcWinService, 0);
- break;
-
- case SERVICE_CONTROL_STOP:
- case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN:
{
- VBoxServiceWinSetStatus(SERVICE_STOP_PENDING, 0);
+ vboxServiceWinSetStatus(SERVICE_STOP_PENDING, 0);
- rc = VBoxServiceStopServices();
+ int rc2 = VBoxServiceStopServices();
+ if (RT_FAILURE(rc2))
+ rcRet = ERROR_GEN_FAILURE;
- VBoxServiceWinSetStatus(SERVICE_STOPPED, 0);
+ vboxServiceWinSetStatus(SERVICE_STOPPED, 0);
+ break;
}
- break;
-
- case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
+ case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
#ifndef TARGET_NT4
- switch (dwEventType)
- {
- /*case WTS_SESSION_LOGON:
- VBoxServiceVerbose(2, "A user has logged on to the session.\n");
+# if 0
+ switch (dwEventType)
+ {
+ case WTS_SESSION_LOGON:
+ VBoxServiceVerbose(2, "A user has logged on to the session.\n");
+ break;
+
+ case WTS_SESSION_LOGOFF:
+ VBoxServiceVerbose(2, "A user has logged off from the session.\n");
+ break;
+ default:
+ break;
+ }
+# endif
+#endif /* !TARGET_NT4 */
break;
- case WTS_SESSION_LOGOFF:
- VBoxServiceVerbose(2, "A user has logged off from the session.\n");
- break;*/
default:
+ VBoxServiceVerbose(1, "Service control function not implemented: %#x\n", dwControl);
+ rcRet = ERROR_CALL_NOT_IMPLEMENTED;
break;
- }
-#endif /* TARGET_NT4 */
- break;
-
- default:
-
- VBoxServiceVerbose(1, "Service control function not implemented: %ld\n", dwControl);
- rc = ERROR_CALL_NOT_IMPLEMENTED;
- break;
}
#ifndef TARGET_NT4
- return rc;
+ return rcRet;
#endif
}
-void WINAPI VBoxServiceWinMain(DWORD argc, LPTSTR *argv)
+static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv)
{
- int rc = VINF_SUCCESS;
-
VBoxServiceVerbose(2, "Registering service control handler ...\n");
#ifdef TARGET_NT4
- g_hWinServiceStatus = RegisterServiceCtrlHandler (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler);
+ g_hWinServiceStatus = RegisterServiceCtrlHandler(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler);
#else
- g_hWinServiceStatus = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler, NULL);
+ g_hWinServiceStatus = RegisterServiceCtrlHandlerEx(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler, NULL);
#endif
-
- if (NULL == g_hWinServiceStatus)
+ if (g_hWinServiceStatus != NULL)
+ {
+ VBoxServiceVerbose(2, "Service control handler registered.\n");
+ vboxServiceWinStart();
+ }
+ else
{
DWORD dwErr = GetLastError();
-
switch (dwErr)
{
- case ERROR_INVALID_NAME:
- VBoxServiceError("Invalid service name!\n");
- break;
- case ERROR_SERVICE_DOES_NOT_EXIST:
- VBoxServiceError("Service does not exist!\n");
- break;
- default:
- VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
- break;
+ case ERROR_INVALID_NAME:
+ VBoxServiceError("Invalid service name!\n");
+ break;
+ case ERROR_SERVICE_DOES_NOT_EXIST:
+ VBoxServiceError("Service does not exist!\n");
+ break;
+ default:
+ VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
+ break;
}
}
- else
- {
- VBoxServiceVerbose(2, "Service control handler registered.\n");
-
- rc = VBoxServiceWinStart();
- }
}
+
diff --git a/src/VBox/Additions/common/VBoxService/VBoxService.cpp b/src/VBox/Additions/common/VBoxService/VBoxService.cpp
index cf696b2c8..4953d2736 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxService.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxService.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxService.cpp 29647 2010-05-18 15:59:51Z vboxsync $ */
+/* $Id: VBoxService.cpp 29817 2010-05-26 13:54:41Z vboxsync $ */
/** @file
* VBoxService - Guest Additions Service Skeleton.
*/
@@ -34,6 +34,7 @@
#include <iprt/buildconfig.h>
#include <iprt/initterm.h>
#include <iprt/path.h>
+#include <iprt/semaphore.h>
#include <iprt/string.h>
#include <iprt/stream.h>
#include <iprt/thread.h>
@@ -53,8 +54,12 @@ char *g_pszProgName = (char *)"";
int g_cVerbosity = 0;
/** The default service interval (the -i | --interval) option). */
uint32_t g_DefaultInterval = 0;
-/** Shutdown the main thread. (later, for signals.) */
-bool volatile g_fShutdown;
+#ifdef RT_OS_WINDOWS
+/** Signal shutdown to the Windows service thread. */
+static bool volatile g_fWindowsServiceShutdown;
+/** Event the Windows service thread waits for shutdown. */
+static RTSEMEVENT g_hEvtWindowsService;
+#endif
/**
* The details of the services that has been compiled in.
@@ -149,11 +154,11 @@ static int VBoxServiceUsage(void)
/**
* Displays a syntax error message.
*
- * @returns 1
+ * @returns RTEXITCODE_SYNTAX.
* @param pszFormat The message text.
* @param ... Format arguments.
*/
-int VBoxServiceSyntax(const char *pszFormat, ...)
+RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...)
{
RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgName);
@@ -162,18 +167,18 @@ int VBoxServiceSyntax(const char *pszFormat, ...)
RTStrmPrintfV(g_pStdErr, pszFormat, va);
va_end(va);
- return 1;
+ return RTEXITCODE_SYNTAX;
}
/**
* Displays an error message.
*
- * @returns 1
+ * @returns RTEXITCODE_FAILURE.
* @param pszFormat The message text.
* @param ... Format arguments.
*/
-int VBoxServiceError(const char *pszFormat, ...)
+RTEXITCODE VBoxServiceError(const char *pszFormat, ...)
{
RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgName);
@@ -186,7 +191,7 @@ int VBoxServiceError(const char *pszFormat, ...)
LogRel(("%s: Error: %N", g_pszProgName, pszFormat, &va));
va_end(va);
- return 1;
+ return RTEXITCODE_FAILURE;
}
@@ -275,17 +280,16 @@ static DECLCALLBACK(int) VBoxServiceThread(RTTHREAD ThreadSelf, void *pvUser)
}
-unsigned VBoxServiceGetStartedServices(void)
+/**
+ * Check if at least one service should be started.
+ */
+static bool VBoxServiceCheckStartedServices(void)
{
- unsigned iMain = ~0U;
for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
if (g_aServices[j].fEnabled)
- {
- iMain = j;
- break;
- }
+ return true;
- return iMain; /* Return the index of the main service (must always come last!). */
+ return false;
}
@@ -293,11 +297,8 @@ unsigned VBoxServiceGetStartedServices(void)
* Starts the service.
*
* @returns VBox status code, errors are fully bitched.
- *
- * @param iMain The index of the service that belongs to the main
- * thread. Pass ~0U if none does.
*/
-int VBoxServiceStartServices(unsigned iMain)
+int VBoxServiceStartServices(void)
{
int rc;
@@ -331,8 +332,7 @@ int VBoxServiceStartServices(unsigned iMain)
rc = VINF_SUCCESS;
for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
{
- if ( !g_aServices[j].fEnabled
- || j == iMain)
+ if (!g_aServices[j].fEnabled)
continue;
VBoxServiceVerbose(2, "Starting service '%s' ...\n", g_aServices[j].pDesc->pszName);
@@ -353,18 +353,7 @@ int VBoxServiceStartServices(unsigned iMain)
rc = VERR_GENERAL_FAILURE;
}
}
- if ( RT_SUCCESS(rc)
- && iMain != ~0U)
- {
- /* The final service runs in the main thread. */
- VBoxServiceVerbose(1, "Starting '%s' in the main thread\n", g_aServices[iMain].pDesc->pszName);
- rc = g_aServices[iMain].pDesc->pfnWorker(&g_fShutdown);
- if (RT_SUCCESS(rc))
- VBoxServiceVerbose(1, "Main service '%s' successfully stopped.\n", g_aServices[iMain].pDesc->pszName);
- else /* Only complain if service returned an error. Otherwise the service is a one-timer. */
- VBoxServiceError("Service '%s' stopped unexpected; rc=%Rrc\n", g_aServices[iMain].pDesc->pszName, rc);
- g_aServices[iMain].pDesc->pfnTerm();
- }
+
return rc;
}
@@ -378,58 +367,61 @@ int VBoxServiceStartServices(unsigned iMain)
int VBoxServiceStopServices(void)
{
int rc = VINF_SUCCESS;
- unsigned iMain = VBoxServiceGetStartedServices();
+ /*
+ * Signal all the services.
+ */
for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
- ASMAtomicXchgBool(&g_aServices[j].fShutdown, true);
+ ASMAtomicWriteBool(&g_aServices[j].fShutdown, true);
+
+ /*
+ * Do the pfnStop callback on all running services.
+ */
for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
if (g_aServices[j].fStarted)
{
VBoxServiceVerbose(3, "Calling stop function for service '%s' ...\n", g_aServices[j].pDesc->pszName);
g_aServices[j].pDesc->pfnStop();
}
- for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
- if ( !g_aServices[j].fEnabled /* Only stop services which were started before. */
- || j == iMain) /* Don't call the termination function for main service yet. */
- {
+ /*
+ * Wait for all the service threads to complete.
+ */
+ for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
+ {
+ if (!g_aServices[j].fEnabled) /* Only stop services which were started before. */
continue;
- }
- else
+ if (g_aServices[j].Thread != NIL_RTTHREAD)
{
- if (g_aServices[j].Thread != NIL_RTTHREAD)
+ VBoxServiceVerbose(2, "Waiting for service '%s' to stop ...\n", g_aServices[j].pDesc->pszName);
+ for (int i = 0; i < 30; i++) /* Wait 30 seconds in total */
{
- VBoxServiceVerbose(2, "Waiting for service '%s' to stop ...\n", g_aServices[j].pDesc->pszName);
- for (int i = 0; i < 30; i++) /* Wait 30 seconds in total */
- {
- rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);
- if (RT_SUCCESS(rc))
- break;
+ rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);
+ if (RT_SUCCESS(rc))
+ break;
#ifdef RT_OS_WINDOWS
- /* Notify SCM that it takes a bit longer ... */
- VBoxServiceWinSetStatus(SERVICE_STOP_PENDING, i);
+ /* Notify SCM that it takes a bit longer ... */
+ VBoxServiceWinSetStopPendingStatus(i + j*32);
#endif
- }
- if (RT_FAILURE(rc))
- VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc);
}
- VBoxServiceVerbose(3, "Terminating service '%s' (%d) ...\n", g_aServices[j].pDesc->pszName, j);
- g_aServices[j].pDesc->pfnTerm();
+ if (RT_FAILURE(rc))
+ VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc);
}
+ VBoxServiceVerbose(3, "Terminating service '%s' (%d) ...\n", g_aServices[j].pDesc->pszName, j);
+ g_aServices[j].pDesc->pfnTerm();
+ }
#ifdef RT_OS_WINDOWS
/*
- * As we're now done terminating all service threads,
- * we have to stop the main thread as well (if defined). Note that the termination
- * function will be called in a later context (when the main thread returns from the worker
- * function).
+ * Wake up and tell the main() thread that we're shutting down (it's
+ * sleeping in VBoxServiceMainWait).
*/
- if (iMain != ~0U)
+ if (g_hEvtWindowsService != NIL_RTSEMEVENT)
{
- VBoxServiceVerbose(3, "Stopping main service '%s' (%d) ...\n", g_aServices[iMain].pDesc->pszName, iMain);
-
- ASMAtomicXchgBool(&g_fShutdown, true);
- g_aServices[iMain].pDesc->pfnStop();
+ VBoxServiceVerbose(3, "Stopping the main thread...\n");
+ ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true);
+ rc = RTSemEventSignal(g_hEvtWindowsService);
+ AssertRC(rc);
}
#endif
@@ -438,14 +430,37 @@ int VBoxServiceStopServices(void)
}
-#ifndef RT_OS_WINDOWS
-/*
- * Block all important signals, then explicitly wait until one of these signal arrives.
+/**
+ * Block the main thread until the service shuts down.
*/
-static void VBoxServiceWaitSignal(void)
+void VBoxServiceMainWait(void)
{
+ int rc;
+
+#ifdef RT_OS_WINDOWS
+ /*
+ * Wait for the semaphore to be signalled.
+ */
+ VBoxServiceVerbose(1, "Waiting in main thread\n");
+ rc = RTSemEventCreate(&g_hEvtWindowsService);
+ AssertRC(rc);
+ while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown))
+ {
+ rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT);
+ AssertRC(rc);
+ }
+ RTSemEventDestroy(g_hEvtWindowsService);
+ g_hEvtWindowsService = NIL_RTSEMEVENT;
+
+#else
+ /*
+ * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking
+ * all important signals.
+ *
+ * The annoying EINTR/ERESTART loop is for the benefit of Solaris where
+ * sigwait returns when we receive a SIGCHLD. Kind of makes sense since
+ */
sigset_t signalMask;
- int iSignal;
sigemptyset(&signalMask);
sigaddset(&signalMask, SIGHUP);
sigaddset(&signalMask, SIGINT);
@@ -454,18 +469,21 @@ static void VBoxServiceWaitSignal(void)
sigaddset(&signalMask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
- int rc;
+ int iSignal;
do
{
iSignal = -1;
rc = sigwait(&signalMask, &iSignal);
}
while ( rc == EINTR
- || rc == ERESTART);
+# ifdef ERESTART
+ || rc == ERESTART
+# endif
+ );
- VBoxServiceVerbose(3, "VBoxServiceWaitSignal: Received signal %d (rc=%d)\n", iSignal, rc);
-}
+ VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc);
#endif /* !RT_OS_WINDOWS */
+}
int main(int argc, char **argv)
@@ -635,43 +653,21 @@ int main(int argc, char **argv)
/*
* Check that at least one service is enabled.
*/
- unsigned iMain = VBoxServiceGetStartedServices();
- if (iMain == ~0U)
+ if (!VBoxServiceCheckStartedServices())
return VBoxServiceSyntax("At least one service must be enabled.\n");
-#ifndef RT_OS_WINDOWS
- /*
- * POSIX: No main service thread.
- */
- iMain = ~0U;
-#endif
-
VBoxServiceVerbose(0, "%s r%s started. Verbose level = %d\n",
RTBldCfgVersion(), RTBldCfgRevisionStr(), g_cVerbosity);
/*
* Daemonize if requested.
*/
+ RTEXITCODE rcExit;
if (fDaemonize && !fDaemonized)
{
#ifdef RT_OS_WINDOWS
- /** @todo Should do something like VBoxSVC here, OR automatically re-register
- * the service and start it. Involving VbglR3Daemonize isn't an option
- * here.
- *
- * Also, the idea here, IIRC, was to map the sub service to windows
- * services. The todo below is for mimicking windows services on
- * non-windows systems. Not sure if this is doable or not, but in anycase
- * this code can be moved into -win.
- *
- * You should return when StartServiceCtrlDispatcher, btw., not
- * continue.
- */
VBoxServiceVerbose(2, "Starting service dispatcher ...\n");
- if (!StartServiceCtrlDispatcher(&g_aServiceTable[0]))
- return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!",
- GetLastError(), g_pszProgName);
- /* Service now lives in the control dispatcher registered above. */
+ rcExit = VBoxServiceWinEnterCtrlDispatcher();
#else
VBoxServiceVerbose(1, "Daemonizing...\n");
rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
@@ -692,11 +688,10 @@ int main(int argc, char **argv)
* POSIX: This is used for both daemons and console runs. Start all services
* and return immediately.
*/
- rc = VBoxServiceStartServices(iMain);
-#ifndef RT_OS_WINDOWS
+ rc = VBoxServiceStartServices();
+ rcExit = RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
if (RT_SUCCESS(rc))
- VBoxServiceWaitSignal();
-#endif
+ VBoxServiceMainWait();
VBoxServiceStopServices();
}
@@ -712,6 +707,6 @@ int main(int argc, char **argv)
#endif
VBoxServiceVerbose(0, "Ended.\n");
- return RT_SUCCESS(rc) ? 0 : 1;
+ return rcExit;
}
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
index 9e62421d1..1b0f68a51 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
@@ -1,5 +1,5 @@
-/* $Id: VBoxServiceControlExec.cpp 29627 2010-05-18 12:47:35Z vboxsync $ */
+/* $Id: VBoxServiceControlExec.cpp 29842 2010-05-27 10:53:19Z vboxsync $ */
/** @file
* VBoxServiceControlExec - Utility functions for process execution.
*/
@@ -252,9 +252,6 @@ static int VBoxServiceControlExecProcLoop(PVBOXSERVICECTRLTHREAD pThread,
bool fProcessAlive = true;
bool fProcessTimedOut = false;
uint64_t MsProcessKilled = UINT64_MAX;
- bool const fHavePipes = hStdInW != NIL_RTPIPE
- || hStdOutR != NIL_RTPIPE
- || hStdErrR != NIL_RTPIPE;
RTMSINTERVAL const cMsPollBase = hStdInW != NIL_RTPIPE
? 100 /* need to poll for input */
: 1000; /* need only poll for process exit and aborts */
@@ -749,6 +746,49 @@ void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pDat
}
}
+int VBoxServiceControlExecCreateProcess(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
+ PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
+ const char *pszPassword, PRTPROCESS phProcess)
+{
+ int rc = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+ /*
+ * If sysprep should be executed do this in the context of VBoxService, which
+ * (usually, if started by SCM) has administrator rights. Because of that a UI
+ * won't be shown (doesn't have a desktop).
+ */
+ if (stricmp(pszExec, "sysprep") == 0)
+ {
+ /* Get the predefined path of sysprep.exe (depending on Windows OS). */
+ char szSysprepCmd[RTPATH_MAX] = "C:\\sysprep\\sysprep.exe";
+ OSVERSIONINFOEX OSInfoEx;
+ RT_ZERO(OSInfoEx);
+ OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if ( GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
+ && OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && OSInfoEx.dwMajorVersion >= 6 /* Vista or later */)
+ {
+ rc = RTEnvGetEx(RTENV_DEFAULT, "windir", szSysprepCmd, sizeof(szSysprepCmd), NULL);
+ if (RT_SUCCESS(rc))
+ rc = RTPathAppend(szSysprepCmd, sizeof(szSysprepCmd), "system32\\sysprep\\sysprep.exe");
+ }
+ rc = RTProcCreateEx(szSysprepCmd, papszArgs, hEnv, 0 /* fFlags */,
+ phStdIn, phStdOut, phStdErr, NULL /* pszAsUser */,
+ NULL /* pszPassword */, phProcess);
+ }
+ else
+ {
+#endif
+ /* Do normal execution. */
+ rc = RTProcCreateEx(pszExec, papszArgs, hEnv, fFlags,
+ phStdIn, phStdOut, phStdErr, pszAsUser,
+ pszPassword, phProcess);
+#ifdef RT_OS_WINDOWS
+ }
+#endif
+ return rc;
+}
+
DECLCALLBACK(int) VBoxServiceControlExecProcessWorker(PVBOXSERVICECTRLTHREAD pThread)
{
AssertPtr(pThread);
@@ -823,11 +863,10 @@ DECLCALLBACK(int) VBoxServiceControlExecProcessWorker(PVBOXSERVICECTRLTHREAD pTh
if (RT_SUCCESS(rc))
{
RTPROCESS hProcess;
- rc = RTProcCreateEx(pData->pszCmd, pData->papszArgs, hEnv, RTPROC_FLAGS_SERVICE,
- phStdIn, phStdOut, phStdErr,
- strlen(pData->pszUser) ? pData->pszUser : NULL,
- strlen(pData->pszUser) && strlen(pData->pszPassword) ? pData->pszPassword : NULL,
- &hProcess);
+ rc = VBoxServiceControlExecCreateProcess(pData->pszCmd, pData->papszArgs, hEnv, RTPROC_FLAGS_SERVICE,
+ phStdIn, phStdOut, phStdErr,
+ pData->pszUser, pData->pszPassword,
+ &hProcess);
if (RT_SUCCESS(rc))
{
/*
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h b/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
index 4a4e686f2..7c6b3e116 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
@@ -1,4 +1,4 @@
-/* $Id: VBoxServiceInternal.h 29516 2010-05-17 09:55:17Z vboxsync $ */
+/* $Id: VBoxServiceInternal.h 29858 2010-05-28 12:54:03Z vboxsync $ */
/** @file
* VBoxService - Guest Additions Services.
*/
@@ -101,27 +101,6 @@ typedef VBOXSERVICE const *PCVBOXSERVICE;
# define VBOXSERVICE_DESCRIPTION "Manages VM runtime information, time synchronization, remote sysprep execution and miscellaneous utilities for guest operating systems."
/** The following constant may be defined by including NtStatus.h. */
# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-/** Structure for storing the looked up user information. */
-typedef struct
-{
- WCHAR wszUser[_MAX_PATH];
- WCHAR wszAuthenticationPackage[_MAX_PATH];
- WCHAR wszLogonDomain[_MAX_PATH];
-} VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER;
-/** Structure for the file information lookup. */
-typedef struct
-{
- char *pszFilePath;
- char *pszFileName;
-} VBOXSERVICEVMINFOFILE, *PVBOXSERVICEVMINFOFILE;
-/** Structure for process information lookup. */
-typedef struct
-{
- DWORD id;
- LUID luid;
-} VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC;
-/** Function prototypes for dynamic loading. */
-typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void);
#endif /* RT_OS_WINDOWS */
#ifdef VBOX_WITH_GUEST_CONTROL
@@ -252,58 +231,54 @@ typedef VBOXSERVICEVEPROPCACHEENTRY *PVBOXSERVICEVEPROPCACHEENTRY;
RT_C_DECLS_BEGIN
-extern char *g_pszProgName;
-extern int g_cVerbosity;
-extern uint32_t g_DefaultInterval;
-
-extern int VBoxServiceSyntax(const char *pszFormat, ...);
-extern int VBoxServiceError(const char *pszFormat, ...);
-extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
-extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max);
-extern unsigned VBoxServiceGetStartedServices(void);
-extern int VBoxServiceStartServices(unsigned iMain);
-extern int VBoxServiceStopServices(void);
-
-extern VBOXSERVICE g_TimeSync;
-extern VBOXSERVICE g_Clipboard;
-extern VBOXSERVICE g_Control;
-extern VBOXSERVICE g_VMInfo;
-extern VBOXSERVICE g_CpuHotPlug;
+extern char *g_pszProgName;
+extern int g_cVerbosity;
+extern uint32_t g_DefaultInterval;
+extern VBOXSERVICE g_TimeSync;
+extern VBOXSERVICE g_Clipboard;
+extern VBOXSERVICE g_Control;
+extern VBOXSERVICE g_VMInfo;
+extern VBOXSERVICE g_CpuHotPlug;
#ifdef VBOXSERVICE_MANAGEMENT
-extern VBOXSERVICE g_MemBalloon;
-extern VBOXSERVICE g_VMStatistics;
+extern VBOXSERVICE g_MemBalloon;
+extern VBOXSERVICE g_VMStatistics;
#endif
#ifdef VBOX_WITH_PAGE_SHARING
-extern VBOXSERVICE g_PageSharing;
+extern VBOXSERVICE g_PageSharing;
#endif
+extern RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...);
+extern RTEXITCODE VBoxServiceError(const char *pszFormat, ...);
+extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
+extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32,
+ uint32_t u32Min, uint32_t u32Max);
+extern int VBoxServiceStartServices(void);
+extern int VBoxServiceStopServices(void);
+extern void VBoxServiceMainWait(void);
#ifdef RT_OS_WINDOWS
-extern DWORD g_rcWinService;
-extern SERVICE_TABLE_ENTRY const g_aServiceTable[]; /** @todo generate on the fly, see comment in main() from the enabled sub services. */
-extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */
+extern RTEXITCODE VBoxServiceWinInstall(void);
+extern RTEXITCODE VBoxServiceWinUninstall(void);
+extern RTEXITCODE VBoxServiceWinEnterCtrlDispatcher(void);
+extern void VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint);
+#endif
-extern int VBoxServiceWinInstall(void);
-extern int VBoxServiceWinUninstall(void);
-extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint);
+#ifdef RT_OS_WINDOWS
# ifdef VBOX_WITH_GUEST_PROPS
-extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs);
-extern bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession);
-extern int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
-extern void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs);
-extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID);
+extern int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList);
+extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID);
# endif /* VBOX_WITH_GUEST_PROPS */
#endif /* RT_OS_WINDOWS */
#ifdef VBOX_WITH_GUEST_CONTROL
-extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,
- const char *pszArgs, uint32_t uNumArgs,
- const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
- const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
+extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,
+ const char *pszArgs, uint32_t uNumArgs,
+ const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
+ const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread);
-extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
- uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
-extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
- uint8_t *pbData, uint32_t cbData);
+extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+ uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
+extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+ uint8_t *pbData, uint32_t cbData);
#endif
#ifdef VBOXSERVICE_MANAGEMENT
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp b/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp
index d34b92320..ec1faebbc 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxServicePageSharing.cpp 29640 2010-05-18 14:30:50Z vboxsync $ */
+/* $Id: VBoxServicePageSharing.cpp 29996 2010-06-02 13:12:21Z vboxsync $ */
/** @file
* VBoxService - Guest page sharing.
*/
@@ -44,6 +44,7 @@ static RTSEMEVENTMULTI g_PageSharingEvent = NIL_RTSEMEVENTMULTI;
#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
#include <tlhelp32.h>
#include <psapi.h>
+#include <winternl.h>
typedef struct
{
@@ -53,15 +54,43 @@ typedef struct
MODULEENTRY32 Info;
} KNOWN_MODULE, *PKNOWN_MODULE;
+#define SystemModuleInformation 11
+
+typedef struct _RTL_PROCESS_MODULE_INFORMATION
+{
+ ULONG Section;
+ PVOID MappedBase;
+ PVOID ImageBase;
+ ULONG ImageSize;
+ ULONG Flags;
+ USHORT LoadOrderIndex;
+ USHORT InitOrderIndex;
+ USHORT LoadCount;
+ USHORT OffsetToFileName;
+ CHAR FullPathName[256];
+} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
+
+typedef struct _RTL_PROCESS_MODULES
+{
+ ULONG NumberOfModules;
+ RTL_PROCESS_MODULE_INFORMATION Modules[1];
+} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
+
+typedef NTSTATUS (WINAPI *PFNZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
+static PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
+static HMODULE hNtdll = 0;
+
+
static DECLCALLBACK(int) VBoxServicePageSharingEmptyTreeCallback(PAVLPVNODECORE pNode, void *);
static PAVLPVNODECORE pKnownModuleTree = NULL;
/**
* Registers a new module with the VMM
- * @param pModule Module ptr
+ * @param pModule Module ptr
+ * @param fValidateMemory Validate/touch memory pages or not
*/
-void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule)
+void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule, bool fValidateMemory)
{
VMMDEVSHAREDREGIONDESC aRegions[VMMDEVSHAREDREGIONDESC_MAX];
DWORD dwModuleSize = pModule->Info.modBaseSize;
@@ -127,71 +156,95 @@ void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule)
pModule->szFileVersion[RT_ELEMENTS(pModule->szFileVersion) - 1] = 0;
unsigned idxRegion = 0;
- do
- {
- MEMORY_BASIC_INFORMATION MemInfo;
- SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo));
- Assert(ret);
- if (!ret)
+ if (fValidateMemory)
+ {
+ do
{
- VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError());
- break;
- }
+ MEMORY_BASIC_INFORMATION MemInfo;
- if ( MemInfo.State == MEM_COMMIT
- && MemInfo.Type == MEM_IMAGE)
- {
- switch (MemInfo.Protect)
- {
- case PAGE_EXECUTE:
- case PAGE_EXECUTE_READ:
- case PAGE_READONLY:
+ SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo));
+ Assert(ret);
+ if (!ret)
{
- char *pRegion = (char *)MemInfo.BaseAddress;
+ VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError());
+ break;
+ }
- /* Skip the first region as it only contains the image file header. */
- if (pRegion != (char *)pModule->Info.modBaseAddr)
+ if ( MemInfo.State == MEM_COMMIT
+ && MemInfo.Type == MEM_IMAGE)
+ {
+ switch (MemInfo.Protect)
+ {
+ case PAGE_EXECUTE:
+ case PAGE_EXECUTE_READ:
+ case PAGE_READONLY:
{
- /* Touch all pages. */
- while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize)
+ char *pRegion = (char *)MemInfo.BaseAddress;
+
+ /* Skip the first region as it only contains the image file header. */
+ if (pRegion != (char *)pModule->Info.modBaseAddr)
{
- /* Try to trick the optimizer to leave the page touching code in place. */
- ASMProbeReadByte(pRegion);
- pRegion += PAGE_SIZE;
+ /* Touch all pages. */
+ while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize)
+ {
+ /* Try to trick the optimizer to leave the page touching code in place. */
+ ASMProbeReadByte(pRegion);
+ pRegion += PAGE_SIZE;
+ }
}
+#ifdef RT_ARCH_X86
+ aRegions[idxRegion].GCRegionAddr = (RTGCPTR32)MemInfo.BaseAddress;
+#else
+ aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress;
+#endif
+ aRegions[idxRegion].cbRegion = MemInfo.RegionSize;
+ idxRegion++;
+
+ break;
}
- aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress;
- aRegions[idxRegion].cbRegion = MemInfo.RegionSize;
- idxRegion++;
- break;
+ default:
+ break; /* ignore */
+ }
}
- default:
- break; /* ignore */
+ pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize;
+ if (dwModuleSize > MemInfo.RegionSize)
+ {
+ dwModuleSize -= MemInfo.RegionSize;
+ }
+ else
+ {
+ dwModuleSize = 0;
+ break;
}
- }
- pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize;
- if (dwModuleSize > MemInfo.RegionSize)
- {
- dwModuleSize -= MemInfo.RegionSize;
- }
- else
- {
- dwModuleSize = 0;
- break;
+ if (idxRegion >= RT_ELEMENTS(aRegions))
+ break; /* out of room */
}
-
- if (idxRegion >= RT_ELEMENTS(aRegions))
- break; /* out of room */
+ while (dwModuleSize);
+ }
+ else
+ {
+ /* We can't probe kernel memory ranges, so pretend it's one big region. */
+#ifdef RT_ARCH_X86
+ aRegions[idxRegion].GCRegionAddr = (RTGCPTR32)pBaseAddress;
+#else
+ aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)pBaseAddress;
+#endif
+ aRegions[idxRegion].cbRegion = dwModuleSize;
+ idxRegion++;
}
- while (dwModuleSize);
-
VBoxServiceVerbose(3, "VbglR3RegisterSharedModule %s %s base=%p size=%x cregions=%d\n", pModule->Info.szModule, pModule->szFileVersion, pModule->Info.modBaseAddr, pModule->Info.modBaseSize, idxRegion);
+#ifdef RT_ARCH_X86
+ int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR32)pModule->Info.modBaseAddr,
+ pModule->Info.modBaseSize, idxRegion, aRegions);
+#else
int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR64)pModule->Info.modBaseAddr,
pModule->Info.modBaseSize, idxRegion, aRegions);
+#endif
+
// AssertRC(rc);
if (RT_FAILURE(rc))
VBoxServiceVerbose(3, "VbglR3RegisterSharedModule failed with %d\n", rc);
@@ -258,18 +311,18 @@ void VBoxServicePageSharingInspectModules(DWORD dwProcessId, PAVLPVNODECORE *ppN
pModule->Core.Key = ModuleInfo.modBaseAddr;
pModule->hModule = LoadLibraryEx(ModuleInfo.szExePath, 0, DONT_RESOLVE_DLL_REFERENCES);
if (pModule->hModule)
- VBoxServicePageSharingRegisterModule(pModule);
+ VBoxServicePageSharingRegisterModule(pModule, true /* validate pages */);
+
+ VBoxServiceVerbose(3, "\n\n MODULE NAME: %s", ModuleInfo.szModule );
+ VBoxServiceVerbose(3, "\n executable = %s", ModuleInfo.szExePath );
+ VBoxServiceVerbose(3, "\n process ID = 0x%08X", ModuleInfo.th32ProcessID );
+ VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );
+ VBoxServiceVerbose(3, "\n base size = %d", ModuleInfo.modBaseSize );
pRec = &pModule->Core;
}
bool ret = RTAvlPVInsert(ppNewTree, pRec);
Assert(ret); NOREF(ret);
-
- VBoxServiceVerbose(3, "\n\n MODULE NAME: %s", ModuleInfo.szModule );
- VBoxServiceVerbose(3, "\n executable = %s", ModuleInfo.szExePath );
- VBoxServiceVerbose(3, "\n process ID = 0x%08X", ModuleInfo.th32ProcessID );
- VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );
- VBoxServiceVerbose(3, "\n base size = %d", ModuleInfo.modBaseSize );
}
}
while (Module32Next(hSnapshot, &ModuleInfo));
@@ -314,6 +367,102 @@ void VBoxServicePageSharingInspectGuest()
CloseHandle(hSnapshot);
+ /* Check all loaded kernel modules. */
+ if (ZwQuerySystemInformation)
+ {
+ ULONG cbBuffer = 0;
+ PVOID pBuffer = NULL;
+ PRTL_PROCESS_MODULES pSystemModules;
+
+ NTSTATUS ret = ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&cbBuffer, 0, &cbBuffer);
+ if (!cbBuffer)
+ {
+ VBoxServiceVerbose(1, "ZwQuerySystemInformation returned length 0\n");
+ goto skipkernelmodules;
+ }
+
+ pBuffer = RTMemAllocZ(cbBuffer);
+ if (!pBuffer)
+ goto skipkernelmodules;
+
+ ret = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, cbBuffer, &cbBuffer);
+ if (ret != STATUS_SUCCESS)
+ {
+ VBoxServiceVerbose(1, "ZwQuerySystemInformation returned %x (1)\n", ret);
+ goto skipkernelmodules;
+ }
+
+ pSystemModules = (PRTL_PROCESS_MODULES)pBuffer;
+ for (unsigned i = 0; i < pSystemModules->NumberOfModules; i++)
+ {
+ /* User-mode modules seem to have no flags set; skip them as we detected them above. */
+ if (pSystemModules->Modules[i].Flags == 0)
+ continue;
+
+ char *pszDot = strrchr(pSystemModules->Modules[i].FullPathName, '.');
+ if ( pszDot
+ && (pszDot[1] == 'e' || pszDot[1] == 'E'))
+ continue; /* ignore executables for now. */
+
+ /* Found it before? */
+ PAVLPVNODECORE pRec = RTAvlPVGet(&pNewTree, pSystemModules->Modules[i].ImageBase);
+ if (!pRec)
+ {
+ pRec = RTAvlPVRemove(&pKnownModuleTree, pSystemModules->Modules[i].ImageBase);
+ if (!pRec)
+ {
+ /* New module; register it. */
+ char szFullFilePath[512];
+ PKNOWN_MODULE pModule = (PKNOWN_MODULE)RTMemAllocZ(sizeof(*pModule));
+ Assert(pModule);
+ if (!pModule)
+ break;
+
+ strcpy(pModule->Info.szModule, &pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName]);
+ GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath));
+
+ /* skip \Systemroot\system32 */
+ char *lpPath = strchr(&pSystemModules->Modules[i].FullPathName[1], '\\');
+ if (!lpPath)
+ {
+ VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
+ RTMemFree(pModule);
+ break;
+ }
+
+ lpPath = strchr(lpPath+1, '\\');
+ if (!lpPath)
+ {
+ VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
+ RTMemFree(pModule);
+ break;
+ }
+
+ strcat(szFullFilePath, lpPath);
+ strcpy(pModule->Info.szExePath, szFullFilePath);
+ pModule->Info.modBaseAddr = (BYTE *)pSystemModules->Modules[i].ImageBase;
+ pModule->Info.modBaseSize = pSystemModules->Modules[i].ImageSize;
+
+ pModule->Core.Key = pSystemModules->Modules[i].ImageBase;
+ VBoxServicePageSharingRegisterModule(pModule, false /* don't check memory pages */);
+
+ VBoxServiceVerbose(3, "\n\n KERNEL MODULE NAME: %s", pModule->Info.szModule );
+ VBoxServiceVerbose(3, "\n executable = %s", pModule->Info.szExePath );
+ VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) pModule->Info.modBaseAddr );
+ VBoxServiceVerbose(3, "\n flags = 0x%08X", pSystemModules->Modules[i].Flags);
+ VBoxServiceVerbose(3, "\n base size = %d", pModule->Info.modBaseSize );
+
+ pRec = &pModule->Core;
+ }
+ bool ret = RTAvlPVInsert(&pNewTree, pRec);
+ Assert(ret); NOREF(ret);
+ }
+ }
+skipkernelmodules:
+ if (pBuffer)
+ RTMemFree(pBuffer);
+ }
+
/* Delete leftover modules in the old tree. */
RTAvlPVDestroy(&pKnownModuleTree, VBoxServicePageSharingEmptyTreeCallback, NULL);
@@ -382,6 +531,13 @@ static DECLCALLBACK(int) VBoxServicePageSharingInit(void)
int rc = RTSemEventMultiCreate(&g_PageSharingEvent);
AssertRCReturn(rc, rc);
+#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
+ hNtdll = LoadLibrary("ntdll.dll");
+
+ if (hNtdll)
+ ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
+#endif
+
/* @todo report system name and version */
/* Never fail here. */
return VINF_SUCCESS;
@@ -397,6 +553,23 @@ DECLCALLBACK(int) VBoxServicePageSharingWorker(bool volatile *pfShutdown)
RTThreadUserSignal(RTThreadSelf());
/*
+ * Block here first for a minute as using DONT_RESOLVE_DLL_REFERENCES is kind of risky; other code that uses LoadLibrary on a dll loaded like this
+ * before will end up crashing the process as the dll's init routine was never called.
+ *
+ * We have to use this feature as we can't simply execute all init code in our service process.
+ *
+ */
+ int rc = RTSemEventMultiWait(g_PageSharingEvent, 60000);
+ if (*pfShutdown)
+ goto end;
+
+ if (rc != VERR_TIMEOUT && RT_FAILURE(rc))
+ {
+ VBoxServiceError("RTSemEventMultiWait failed; rc=%Rrc\n", rc);
+ goto end;
+ }
+
+ /*
* Now enter the loop retrieving runtime data continuously.
*/
for (;;)
@@ -414,7 +587,7 @@ DECLCALLBACK(int) VBoxServicePageSharingWorker(bool volatile *pfShutdown)
*/
if (*pfShutdown)
break;
- int rc = RTSemEventMultiWait(g_PageSharingEvent, 60000);
+ rc = RTSemEventMultiWait(g_PageSharingEvent, 60000);
if (*pfShutdown)
break;
if (rc != VERR_TIMEOUT && RT_FAILURE(rc))
@@ -424,6 +597,7 @@ DECLCALLBACK(int) VBoxServicePageSharingWorker(bool volatile *pfShutdown)
}
}
+end:
RTSemEventMultiDestroy(g_PageSharingEvent);
g_PageSharingEvent = NIL_RTSEMEVENTMULTI;
@@ -435,6 +609,11 @@ DECLCALLBACK(int) VBoxServicePageSharingWorker(bool volatile *pfShutdown)
static DECLCALLBACK(void) VBoxServicePageSharingTerm(void)
{
VBoxServiceVerbose(3, "VBoxServicePageSharingTerm\n");
+
+#if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4)
+ if (hNtdll)
+ FreeLibrary(hNtdll);
+#endif
return;
}
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp b/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp
index 88b0dd3d2..a0a7b1b45 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxServicePropCache.cpp 29040 2010-05-04 20:09:03Z vboxsync $ */
+/* $Id: VBoxServicePropCache.cpp 29885 2010-05-31 09:04:43Z vboxsync $ */
/** @file
* VBoxServicePropCache - Guest property cache.
*/
@@ -267,6 +267,30 @@ int VBoxServicePropCacheUpdateEx(PVBOXSERVICEVEPROPCACHE pCache, const char *psz
/**
+ * Flushes the cache by writing every item regardless of its state.
+ *
+ * @param pCache The property cache.
+ */
+int VBoxServicePropCacheFlush(PVBOXSERVICEVEPROPCACHE pCache)
+{
+ AssertPtr(pCache);
+ int rc = VINF_SUCCESS;
+ PVBOXSERVICEVEPROPCACHEENTRY pNodeIt = NULL;
+ if (RT_SUCCESS(RTCritSectEnter(&pCache->CritSect)))
+ {
+ RTListForEach(&pCache->ListEntries, pNodeIt, VBOXSERVICEVEPROPCACHEENTRY, Node)
+ {
+ rc = VBoxServiceWritePropF(pCache->uClientID, pNodeIt->pszName, pNodeIt->pszValue);
+ if (RT_FAILURE(rc))
+ break;
+ }
+ RTCritSectLeave(&pCache->CritSect);
+ }
+ return rc;
+}
+
+
+/**
* Reset all temporary properties and destroy the cache.
*
* @param pCache The property cache.
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.h b/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.h
index a2b04d48c..465c306a3 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.h
+++ b/src/VBox/Additions/common/VBoxService/VBoxServicePropCache.h
@@ -29,6 +29,7 @@ int VBoxServicePropCacheCreate(PVBOXSERVICEVEPROPCACHE pCache, uint32_t uClientI
int VBoxServicePropCacheUpdateEntry(PVBOXSERVICEVEPROPCACHE pCache, const char *pszName, uint32_t fFlags, const char *pszValueReset);
int VBoxServicePropCacheUpdate(PVBOXSERVICEVEPROPCACHE pCache, const char *pszName, const char *pszValueFormat, ...);
int VBoxServicePropCacheUpdateEx(PVBOXSERVICEVEPROPCACHE pCache, const char *pszName, uint32_t fFlags, const char *pszValueReset, const char *pszValueFormat, ...);
+int VBoxServicePropCacheFlush(PVBOXSERVICEVEPROPCACHE pCache);
void VBoxServicePropCacheDestroy(PVBOXSERVICEVEPROPCACHE pCache);
#endif
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
index c8e042327..9b261ded0 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxServiceVMInfo-win.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: VBoxServiceVMInfo-win.cpp 29872 2010-05-28 15:40:39Z vboxsync $ */
/** @file
* VBoxService - Virtual Machine Information for the Host, Windows specifics.
*/
@@ -36,11 +36,39 @@
#include "VBoxServiceUtils.h"
+/** Structure for storing the looked up user information. */
+typedef struct
+{
+ WCHAR wszUser[_MAX_PATH];
+ WCHAR wszAuthenticationPackage[_MAX_PATH];
+ WCHAR wszLogonDomain[_MAX_PATH];
+} VBOXSERVICEVMINFOUSER, *PVBOXSERVICEVMINFOUSER;
+/** Structure for the file information lookup. */
+typedef struct
+{
+ char *pszFilePath;
+ char *pszFileName;
+} VBOXSERVICEVMINFOFILE, *PVBOXSERVICEVMINFOFILE;
+/** Structure for process information lookup. */
+typedef struct
+{
+ DWORD id;
+ LUID luid;
+} VBOXSERVICEVMINFOPROC, *PVBOXSERVICEVMINFOPROC;
+
+
+/*******************************************************************************
+* Prototypes
+*******************************************************************************/
+bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs);
+bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession);
+int VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
+void VBoxServiceVMInfoWinProcessesFree(PVBOXSERVICEVMINFOPROC paProcs);
+
+
/*******************************************************************************
* Global Variables *
*******************************************************************************/
-/** Function prototypes for dynamic loading. */
-PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId = NULL;
#ifndef TARGET_NT4
@@ -287,7 +315,7 @@ static void VBoxServiceVMInfoWinSafeCopy(PWCHAR pwszDst, size_t cbDst, LSA_UNICO
/**
- * Detects whether a user is logged on based on the enumerated processes.
+ * Detects whether a user is logged on.
*
* @returns true if logged in, false if not (or error).
* @param a_pUserInfo Where to return the user information.
@@ -295,6 +323,7 @@ static void VBoxServiceVMInfoWinSafeCopy(PWCHAR pwszDst, size_t cbDst, LSA_UNICO
*/
bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_pSession)
{
+ AssertPtr(a_pUserInfo);
if (!a_pSession)
return false;
@@ -302,29 +331,37 @@ bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_
NTSTATUS rcNt = LsaGetLogonSessionData(a_pSession, &pSessionData);
if (rcNt != STATUS_SUCCESS)
{
- VBoxServiceError("LsaGetLogonSessionData failed, LSA error %#x\n", LsaNtStatusToWinError(rcNt));
+ VBoxServiceError("VMInfo/Users: LsaGetLogonSessionData failed, LSA error %#x\n", LsaNtStatusToWinError(rcNt));
if (pSessionData)
LsaFreeReturnBuffer(pSessionData);
return false;
}
if (!pSessionData)
{
- VBoxServiceError("Invalid logon session data.\n");
+ VBoxServiceError("VMInfo/Users: Invalid logon session data!\n");
return false;
}
- VBoxServiceVerbose(3, "Users: Session data: Name = %ls, Len = %d, SID = %s, LogonID = %d,%d\n",
- pSessionData->UserName.Buffer,
- pSessionData->UserName.Length,
- pSessionData->Sid != NULL ? "1" : "0",
- pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);
+ /*
+ * Only handle users which can login interactively or logged in
+ * remotely over native RDP.
+ */
bool fFoundUser = false;
- if ( pSessionData->UserName.Buffer != NULL
- && pSessionData->Sid != NULL
- && pSessionData->LogonId.LowPart != 0)
+ DWORD dwErr = NO_ERROR;
+ if ( IsValidSid(pSessionData->Sid)
+ && ( (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive
+ || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive
+ || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedInteractive
+ || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedRemoteInteractive))
{
+ VBoxServiceVerbose(3, "VMInfo/Users: Session data: Name=%ls, Len=%d, SID=%s, LogonID=%ld,%ld\n",
+ pSessionData->UserName.Buffer,
+ pSessionData->UserName.Length,
+ pSessionData->Sid != NULL ? "1" : "0",
+ pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);
+
/*
- * Copy out the data.
+ * Copy out relevant data.
*/
VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszUser, sizeof(a_pUserInfo->wszUser),
&pSessionData->UserName, "User name");
@@ -333,91 +370,142 @@ bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER a_pUserInfo, PLUID a_
VBoxServiceVMInfoWinSafeCopy(a_pUserInfo->wszLogonDomain, sizeof(a_pUserInfo->wszLogonDomain),
&pSessionData->LogonDomain, "Logon domain name");
-
- /*
- * Only handle users which can login interactively or logged in
- * remotely over native RDP.
- */
- /** @todo r=bird: Whey don't we check this before copying the data? */
- if ( ( (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive
- || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive)
- && pSessionData->Sid != NULL)
+ TCHAR szOwnerName[_MAX_PATH] = { 0 };
+ DWORD dwOwnerNameSize = sizeof(szOwnerName);
+ TCHAR szDomainName[_MAX_PATH] = { 0 };
+ DWORD dwDomainNameSize = sizeof(szDomainName);
+ SID_NAME_USE enmOwnerType = SidTypeInvalid;
+ if (!LookupAccountSid(NULL,
+ pSessionData->Sid,
+ szOwnerName,
+ &dwOwnerNameSize,
+ szDomainName,
+ &dwDomainNameSize,
+ &enmOwnerType))
{
- TCHAR szOwnerName[_MAX_PATH] = { 0 };
- DWORD dwOwnerNameSize = sizeof(szOwnerName);
- TCHAR szDomainName[_MAX_PATH] = { 0 };
- DWORD dwDomainNameSize = sizeof(szDomainName);
- SID_NAME_USE enmOwnerType = SidTypeInvalid;
- if (LookupAccountSid(NULL,
- pSessionData->Sid,
- szOwnerName,
- &dwOwnerNameSize,
- szDomainName,
- &dwDomainNameSize,
- &enmOwnerType))
+ VBoxServiceError("VMInfo/Users: Failed looking up account info for user '%ls': %ld!\n",
+ a_pUserInfo->wszUser, GetLastError());
+ }
+ else
+ {
+ if (enmOwnerType == SidTypeUser) /* Only recognize users; we don't care about the rest! */
{
- VBoxServiceVerbose(3, "Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",
+ VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, Session=%ld, LUID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",
a_pUserInfo->wszUser, pSessionData->Session, pSessionData->LogonId.HighPart,
pSessionData->LogonId.LowPart, a_pUserInfo->wszAuthenticationPackage,
a_pUserInfo->wszLogonDomain);
-#if 1 /** @todo If we don't use this, drop it? */
- /* The session ID increments/decrements on Vista often! So don't compare
- the session data SID with the current SID here. */
- DWORD dwActiveSession = 0;
- if (g_pfnWTSGetActiveConsoleSessionId != NULL) /* Check terminal session ID. */
- dwActiveSession = g_pfnWTSGetActiveConsoleSessionId();
- /*VBoxServiceVerbose(3, ("Users: Current active session ID: %ld\n", dwActiveSession));*/
-#endif
-
- if (enmOwnerType == SidTypeUser)
+ /* Detect RDP sessions as well. */
+ LPTSTR pBuffer = NULL;
+ DWORD cbRet = 0;
+ int iState = 0;
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
+ pSessionData->Session,
+ WTSConnectState,
+ &pBuffer,
+ &cbRet))
{
- /* Detect RDP sessions as well. */
- LPTSTR pBuffer = NULL;
- DWORD cbRet = 0;
- int iState = 0;
- if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
- WTS_CURRENT_SESSION,
- WTSConnectState,
- &pBuffer,
- &cbRet))
+ if(cbRet)
+ iState = *pBuffer;
+ VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, WTSConnectState=%d\n",
+ a_pUserInfo->wszUser, iState);
+ if ( iState == WTSActive /* User logged on to WinStation. */
+ || iState == WTSShadow /* Shadowing another WinStation. */
+ || iState == WTSDisconnected) /* WinStation logged on without client. */
{
- /*VBoxServiceVerbose(3, ("Users: WTSQuerySessionInformation returned %ld bytes, p=%p, state=%d\n", cbRet, pBuffer, pBuffer != NULL ? (INT)*pBuffer : -1));*/
- if(cbRet)
- iState = *pBuffer;
-
- if ( iState == WTSActive /* User logged on to WinStation. */
- || iState == WTSShadow /* Shadowing another WinStation. */
- || iState == WTSDisconnected) /* WinStation logged on without client. */
- {
- /** @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->wszUser, iState);
- fFoundUser = true;
- }
-
- if (pBuffer)
- WTSFreeMemory(pBuffer);
- }
- else
- {
- /*
- * Terminal services don't run (for example in W2K,
- * nothing to worry about ...). ... or is on the Vista
- * fast user switching page!
- */
+ /** @todo On Vista and W2K, always "old" user name are still
+ * there. Filter out the old one! */
+ VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls is logged in via TCS/RDP. State=%d\n",
+ a_pUserInfo->wszUser, iState);
fFoundUser = true;
}
+ if (pBuffer)
+ WTSFreeMemory(pBuffer);
+ }
+ else
+ {
+ VBoxServiceVerbose(3, "VMInfo/Users: Account User=%ls, WTSConnectState returnd %ld\n",
+ a_pUserInfo->wszUser, GetLastError());
+
+ /*
+ * Terminal services don't run (for example in W2K,
+ * nothing to worry about ...). ... or is on the Vista
+ * fast user switching page!
+ */
+ fFoundUser = true;
}
}
}
- }
+ }
LsaFreeReturnBuffer(pSessionData);
return fFoundUser;
}
+
+/**
+ * Retrieves the currently logged in users and stores their names along with the
+ * user count.
+ *
+ * @returns VBox status code.
+ * @param ppszUserList Where to store the user list (separated by commas). Must be
+ * freed with RTStrFree().
+ * @param pcUsersInList Where to store the number of users in the list.
+ */
+int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList)
+{
+ PLUID paSessions = NULL;
+ ULONG cSession = 0;
+ NTSTATUS r = 0;
+
+ /* This function can report stale or orphaned interactive logon sessions
+ of already logged off users (especially in Windows 2000). */
+ r = LsaEnumerateLogonSessions(&cSession, &paSessions);
+ VBoxServiceVerbose(3, "VMInfo/Users: Found %ld users\n", cSession);
+ if (r != STATUS_SUCCESS)
+ {
+ VBoxServiceError("VMInfo/Users: LsaEnumerate failed with %lu\n", LsaNtStatusToWinError(r));
+ return RTErrConvertFromWin32(LsaNtStatusToWinError(r));
+ }
+
+ PVBOXSERVICEVMINFOPROC paProcs;
+ DWORD cProcs;
+ int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
+ if (RT_SUCCESS(rc))
+ {
+ *pcUsersInList = 0;
+ for (ULONG i = 0; i < cSession; i++)
+ {
+ VBOXSERVICEVMINFOUSER UserInfo;
+ if ( VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])
+ && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs))
+ {
+ if (*pcUsersInList > 0)
+ {
+ rc = RTStrAAppend(ppszUserList, ",");
+ AssertRCReturn(rc, rc);
+ }
+
+ *pcUsersInList += 1;
+
+ char *pszTemp;
+ int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp);
+ if (RT_SUCCESS(rc2))
+ {
+ rc = RTStrAAppend(ppszUserList, pszTemp);
+ RTMemFree(pszTemp);
+ AssertRCReturn(rc, rc);
+ }
+ else
+ RTStrAAppend(ppszUserList, "<string-convertion-error>");
+ }
+ }
+ VBoxServiceVMInfoWinProcessesFree(paProcs);
+ }
+ LsaFreeReturnBuffer(paSessions);
+ return rc;
+}
+
#endif /* TARGET_NT4 */
int VBoxServiceWinGetComponentVersions(uint32_t uClientID)
@@ -481,7 +569,7 @@ int VBoxServiceWinGetComponentVersions(uint32_t uClientID)
{ szSysDir, "VBoxControl.exe" },
{ szSysDir, "VBoxHook.dll" },
{ szSysDir, "VBoxDisp.dll" },
- { szSysDir, "VBoxService.exe" },
+ { szSysDir, "VBoxServiceNT.exe" },
{ szSysDir, "VBoxTray.exe" },
{ szDriversDir, "VBoxGuestNT.sys" },
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
index 3c90bc916..430077831 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxServiceVMInfo.cpp 29594 2010-05-18 07:45:58Z vboxsync $ */
+/* $Id: VBoxServiceVMInfo.cpp 29861 2010-05-28 13:19:08Z vboxsync $ */
/** @file
* VBoxService - Virtual Machine Information for the Host.
*/
@@ -21,10 +21,11 @@
* Header Files *
*******************************************************************************/
#ifdef RT_OS_WINDOWS
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <Ntsecapi.h>
+# include <winsock2.h>
+# include <iphlpapi.h>
+# include <ws2tcpip.h>
+# include <windows.h>
+# include <Ntsecapi.h>
#else
# define __STDC_LIMIT_MACROS
# include <arpa/inet.h>
@@ -40,6 +41,11 @@
# ifdef RT_OS_SOLARIS
# include <sys/sockio.h>
# endif
+# ifdef RT_OS_FREEBSD
+# include <ifaddrs.h> /* getifaddrs, freeifaddrs */
+# include <net/if_dl.h> /* LLADDR */
+# include <netdb.h> /* getnameinfo */
+# endif
#endif
#include <iprt/mem.h>
@@ -106,18 +112,6 @@ static DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
int rc = RTSemEventMultiCreate(&g_hVMInfoEvent);
AssertRCReturn(rc, rc);
-#ifdef RT_OS_WINDOWS
- /** @todo r=bird: call a windows specific init function and move
- * g_pfnWTSGetActiveConsoleSessionId out of the global scope. */
- /* Get function pointers. */
- HMODULE hKernel32 = LoadLibrary("kernel32");
- if (hKernel32 != NULL)
- {
- g_pfnWTSGetActiveConsoleSessionId = (PFNWTSGETACTIVECONSOLESESSIONID)GetProcAddress(hKernel32, "WTSGetActiveConsoleSessionId");
- FreeLibrary(hKernel32);
- }
-#endif
-
rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
if (RT_SUCCESS(rc))
VBoxServiceVerbose(3, "VMInfo: Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
@@ -221,56 +215,12 @@ static void VBoxServiceVMInfoWriteFixedProperties(void)
int VBoxServiceVMInfoWriteUsers()
{
int rc;
- char szUserList[4096] = {0};
+ char *pszUserList = NULL;
uint32_t cUsersInList = 0;
#ifdef RT_OS_WINDOWS
# ifndef TARGET_NT4
- PLUID paSessions = NULL;
- ULONG cSession = 0;
- NTSTATUS r = 0;
-
- /* This function can report stale or orphaned interactive logon sessions
- of already logged off users (especially in Windows 2000). */
- r = ::LsaEnumerateLogonSessions(&cSession, &paSessions);
- VBoxServiceVerbose(3, "Users: Found %ld users.\n", cSession);
- if (r != STATUS_SUCCESS)
- {
- VBoxServiceError("LsaEnumerate failed %lu\n", LsaNtStatusToWinError(r));
- return RTErrConvertFromWin32(LsaNtStatusToWinError(r));
- }
-
- PVBOXSERVICEVMINFOPROC paProcs;
- DWORD cProcs;
- rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
- if (RT_SUCCESS(rc))
- {
- for (ULONG i = 0; i < cSession; i++)
- {
- VBOXSERVICEVMINFOUSER UserInfo;
- if ( VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])
- && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs))
- {
- if (cUsersInList > 0)
- strcat(szUserList, ",");
-
- cUsersInList++;
-
- char *pszTemp;
- int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp);
- if (RT_SUCCESS(rc2))
- {
- strcat(szUserList, pszTemp);
- RTMemFree(pszTemp);
- }
- else
- strcat(szUserList, "<string-convertion-error>");
- }
- }
- VBoxServiceVMInfoWinProcessesFree(paProcs);
- }
-
- ::LsaFreeReturnBuffer(paSessions);
+ rc = VBoxServiceVMInfoWinWriteUsers(&pszUserList, &cUsersInList);
# endif /* TARGET_NT4 */
#elif defined(RT_OS_FREEBSD)
/** @todo FreeBSD: Port logged on user info retrival. */
@@ -284,51 +234,43 @@ int VBoxServiceVMInfoWriteUsers()
if (rc != 0)
# endif
{
- VBoxServiceError("Could not set UTMP file! Error: %ld\n", errno);
+ VBoxServiceError("VMInfo/Users: Could not set UTMP file! Error: %ld\n", errno);
}
setutent();
utmp *ut_user;
while ((ut_user = getutent()))
{
/* Make sure we don't add user names which are not
- * part of type USER_PROCESS and don't add same users twice. */
- if ( ut_user->ut_type == USER_PROCESS
- && strstr(szUserList, ut_user->ut_user) == NULL)
+ * part of type USER_PROCESS. */
+
+ /** @todo Do we want to filter out user names? What if a user is logged in twice? */
+ if (ut_user->ut_type == USER_PROCESS)
{
- /** @todo Do we really want to filter out double user names? (Same user logged in twice)
- * bird: If we do, then we must add checks for buffer overflows here! */
- /** @todo r=bird: strstr will filtering out users with similar names. For
- * example: smith, smithson, joesmith and bobsmith */
if (cUsersInList > 0)
- strcat(szUserList, ",");
- strcat(szUserList, ut_user->ut_user);
+ {
+ rc = RTStrAAppend(&pszUserList, ",");
+ AssertRCReturn(rc, rc);
+ }
+ rc = RTStrAAppend(&pszUserList, ut_user->ut_user);
+ AssertRCReturn(rc, rc);
cUsersInList++;
}
}
endutent();
#endif /* !RT_OS_WINDOWS */
- if (cUsersInList > 0)
- VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList);
+ if (pszUserList && cUsersInList > 0)
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", pszUserList);
else
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList);
- if ( g_cVMInfoLoggedInUsers != cUsersInList
- || g_cVMInfoLoggedInUsers == UINT32_MAX)
+ if (g_cVMInfoLoggedInUsers != cUsersInList)
{
- /*
- * 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 (cUsersInList == 0)
- VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true");
- else if (g_cVMInfoLoggedInUsers == 0)
- VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false");
- }
- g_cVMInfoLoggedInUsers = cUsersInList;
-
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", cUsersInList == 0 ? "true" : "false");
+ g_cVMInfoLoggedInUsers = cUsersInList;
+ }
+ if (pszUserList)
+ RTStrFree(pszUserList);
return VINF_SUCCESS;
}
@@ -342,10 +284,41 @@ int VBoxServiceVMInfoWriteNetwork()
char szPropPath [FILENAME_MAX];
#ifdef RT_OS_WINDOWS
+ IP_ADAPTER_INFO *pAdpInfo = NULL;
+
+# ifndef TARGET_NT4
+ ULONG cbAdpInfo = sizeof(*pAdpInfo);
+ pAdpInfo = (IP_ADAPTER_INFO*)RTMemAlloc(cbAdpInfo);
+ if (!pAdpInfo)
+ {
+ VBoxServiceError("VMInfo/Network: Failed to allocate IP_ADAPTER_INFO\n");
+ return VERR_NO_MEMORY;
+ }
+ DWORD dwRet = GetAdaptersInfo(pAdpInfo, &cbAdpInfo);
+ if (dwRet == ERROR_BUFFER_OVERFLOW)
+ {
+ IP_ADAPTER_INFO *pAdpInfoNew = (IP_ADAPTER_INFO*)RTMemRealloc(pAdpInfo, cbAdpInfo);
+ if (pAdpInfoNew)
+ {
+ pAdpInfo = pAdpInfoNew;
+ dwRet = GetAdaptersInfo(pAdpInfo, &cbAdpInfo);
+ }
+ }
+ if (dwRet != ERROR_SUCCESS)
+ {
+ if (pAdpInfo)
+ RTMemFree(pAdpInfo);
+ VBoxServiceError("VMInfo/Network: Failed to get adapter info: Error %d\n", dwRet);
+ return RTErrConvertFromWin32(dwRet);
+ }
+# endif
+
SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
if (sd == SOCKET_ERROR) /* Socket invalid. */
{
- VBoxServiceError("Failed to get a socket: Error %d\n", WSAGetLastError());
+ VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %d\n", WSAGetLastError());
+ if (pAdpInfo)
+ RTMemFree(pAdpInfo);
return RTErrConvertFromWin32(WSAGetLastError());
}
@@ -361,7 +334,9 @@ int VBoxServiceVMInfoWriteNetwork()
0,
0) == SOCKET_ERROR)
{
- VBoxServiceError("Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
+ VBoxServiceError("VMInfo/Network: Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
+ if (pAdpInfo)
+ RTMemFree(pAdpInfo);
return RTErrConvertFromWin32(WSAGetLastError());
}
int cIfacesSystem = nBytesReturned / sizeof(INTERFACE_INFO);
@@ -376,8 +351,10 @@ int VBoxServiceVMInfoWriteNetwork()
nFlags = InterfaceList[i].iiFlags;
pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress);
Assert(pAddress);
+ char szIp[32];
+ RTStrPrintf(szIp, sizeof(szIp), "%s", inet_ntoa(pAddress->sin_addr));
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
- VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szIp);
pAddress = (sockaddr_in *) & (InterfaceList[i].iiBroadcastAddress);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
@@ -389,15 +366,110 @@ int VBoxServiceVMInfoWriteNetwork()
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, nFlags & IFF_UP ? "Up" : "Down");
+
+# ifndef TARGET_NT4
+ IP_ADAPTER_INFO *pAdp;
+ for (pAdp = pAdpInfo; pAdp; pAdp = pAdp->Next)
+ if (!strcmp(pAdp->IpAddressList.IpAddress.String, szIp))
+ break;
+
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
+ if (pAdp)
+ {
+ char szMac[32];
+ RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
+ pAdp->Address[0], pAdp->Address[1], pAdp->Address[2],
+ pAdp->Address[3], pAdp->Address[4], pAdp->Address[5]);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
+ }
+ else
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, NULL);
+# endif
+
cIfacesReport++;
}
+ if (pAdpInfo)
+ RTMemFree(pAdpInfo);
if (sd >= 0)
closesocket(sd);
-#else /* !RT_OS_WINDOWS */
+
+#elif defined(RT_OS_FREEBSD)
+ int rc = 0;
+ struct ifaddrs *pIfHead = NULL;
+
+ /* Get all available interfaces */
+ rc = getifaddrs(&pIfHead);
+ if (rc < 0)
+ {
+ VBoxServiceError("VMInfo/Network: Failed to get all interfaces: Error %d\n", errno);
+ return RTErrConvertFromErrno(errno);
+ }
+
+ /* Loop through all interfaces and set the data. */
+ for (struct ifaddrs *pIfCurr = pIfHead; pIfCurr; pIfCurr = pIfCurr->ifa_next)
+ {
+ /*
+ * Only AF_INET and no loopback interfaces
+ * @todo: IPv6 interfaces
+ */
+ if ( pIfCurr->ifa_addr->sa_family == AF_INET
+ && !(pIfCurr->ifa_flags & IFF_LOOPBACK))
+ {
+ char szInetAddr[NI_MAXHOST];
+
+ memset(szInetAddr, 0, NI_MAXHOST);
+ getnameinfo(pIfCurr->ifa_addr, sizeof(struct sockaddr_in),
+ szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
+
+ memset(szInetAddr, 0, NI_MAXHOST);
+ getnameinfo(pIfCurr->ifa_broadaddr, sizeof(struct sockaddr_in),
+ szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
+
+ memset(szInetAddr, 0, NI_MAXHOST);
+ getnameinfo(pIfCurr->ifa_netmask, sizeof(struct sockaddr_in),
+ szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
+
+ /* Search for the AF_LINK interface of the current AF_INET one and get the mac. */
+ for (struct ifaddrs *pIfLinkCurr = pIfHead; pIfLinkCurr; pIfLinkCurr = pIfLinkCurr->ifa_next)
+ {
+ if ( pIfLinkCurr->ifa_addr->sa_family == AF_LINK
+ && !strcmp(pIfCurr->ifa_name, pIfLinkCurr->ifa_name))
+ {
+ char szMac[32];
+ uint8_t *pu8Mac = NULL;
+ struct sockaddr_dl *pLinkAddress = (struct sockaddr_dl *)pIfLinkCurr->ifa_addr;
+
+ AssertPtr(pLinkAddress);
+ pu8Mac = (uint8_t *)LLADDR(pLinkAddress);
+ RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
+ pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3], pu8Mac[4], pu8Mac[5]);
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
+ break;
+ }
+ }
+
+ RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
+ VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, pIfCurr->ifa_flags & IFF_UP ? "Up" : "Down");
+
+ cIfacesReport++;
+ }
+ }
+
+ /* Free allocated resources. */
+ freeifaddrs(pIfHead);
+
+#else /* !RT_OS_WINDOWS && !RT_OS_FREEBSD */
int sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0)
{
- VBoxServiceError("Failed to get a socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %d\n", errno);
return RTErrConvertFromErrno(errno);
}
@@ -407,7 +479,7 @@ int VBoxServiceVMInfoWriteNetwork()
ifcfg.ifc_buf = buffer;
if (ioctl(sd, SIOCGIFCONF, &ifcfg) < 0)
{
- VBoxServiceError("Failed to ioctl(SIOCGIFCONF) on socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFCONF) on socket: Error %d\n", errno);
return RTErrConvertFromErrno(errno);
}
@@ -419,7 +491,7 @@ int VBoxServiceVMInfoWriteNetwork()
sockaddr_in *pAddress;
if (ioctl(sd, SIOCGIFFLAGS, &ifrequest[i]) < 0)
{
- VBoxServiceError("Failed to ioctl(SIOCGIFFLAGS) on socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFFLAGS) on socket: Error %d\n", errno);
close(sd);
return RTErrConvertFromErrno(errno);
}
@@ -434,7 +506,7 @@ int VBoxServiceVMInfoWriteNetwork()
if (ioctl(sd, SIOCGIFBRDADDR, &ifrequest[i]) < 0)
{
- VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
close(sd);
return RTErrConvertFromErrno(errno);
}
@@ -444,11 +516,11 @@ int VBoxServiceVMInfoWriteNetwork()
if (ioctl(sd, SIOCGIFNETMASK, &ifrequest[i]) < 0)
{
- VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
close(sd);
return RTErrConvertFromErrno(errno);
}
- #if defined(RT_OS_FREEBSD) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
+ #if defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
pAddress = (sockaddr_in *)&ifrequest[i].ifr_addr;
#else
pAddress = (sockaddr_in *)&ifrequest[i].ifr_netmask;
@@ -463,7 +535,7 @@ int VBoxServiceVMInfoWriteNetwork()
if (ioctl(sd, SIOCGIFHWADDR, &ifrequest[i]) < 0)
#endif
{
- VBoxServiceError("Failed to ioctl(SIOCGIFHWADDR) on socket: Error %d\n", errno);
+ VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFHWADDR) on socket: Error %d\n", errno);
close(sd);
return RTErrConvertFromErrno(errno);
}
@@ -518,7 +590,7 @@ DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown)
/* Required for network information (must be called per thread). */
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
- VBoxServiceError("WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));
+ VBoxServiceError("VMInfo/Users: WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));
#endif /* RT_OS_WINDOWS */
/*
@@ -552,7 +624,7 @@ DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown)
break;
if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
{
- VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
+ VBoxServiceError("VMInfo: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
rc = rc2;
break;
}
@@ -601,7 +673,7 @@ static DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
/* Disconnect from guest properties service. */
rc = VbglR3GuestPropDisconnect(g_uVMInfoGuestPropSvcClientID);
if (RT_FAILURE(rc))
- VBoxServiceError("Failed to disconnect from guest property service! Error: %Rrc\n", rc);
+ VBoxServiceError("VMInfo: Failed to disconnect from guest property service! Error: %Rrc\n", rc);
g_uVMInfoGuestPropSvcClientID = 0;
RTSemEventMultiDestroy(g_hVMInfoEvent);
diff --git a/src/VBox/Additions/common/crOpenGL/Makefile.kmk b/src/VBox/Additions/common/crOpenGL/Makefile.kmk
index d85062b83..9b11037ef 100644
--- a/src/VBox/Additions/common/crOpenGL/Makefile.kmk
+++ b/src/VBox/Additions/common/crOpenGL/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 28800 2010-04-27 08:22:32Z vboxsync $
+# $Id: Makefile.kmk 29790 2010-05-25 14:27:13Z vboxsync $
## @file
# Sub-Makefile for the VirtualBox Guest OpenGL part
#
@@ -218,9 +218,15 @@ ifeq ($(KBUILD_TARGET),win)
$(VBOX_PATH_CROGL_GENFILES)/getprocaddress.c: $(PATH_SUB_CURRENT)/windows_getprocaddress.py $(VBOX_CROGL_API_FILES) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
+ ifeq ($(KBUILD_TARGET_ARCH),amd64)
+$(VBOX_PATH_CROGL_GENFILES)/cropengl.def: $(PATH_SUB_CURRENT)/defs64.py $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+ $(call MSG_GENERATE,python,$@,$<)
+ $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
+ else
$(VBOX_PATH_CROGL_GENFILES)/cropengl.def: $(PATH_SUB_CURRENT)/defs.py $(VBOX_CROGL_API_FILES) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
+ endif
$(VBOX_PATH_CROGL_GENFILES)/cr_gl.h: $(PATH_SUB_CURRENT)/cr_gl.py $(VBOX_CROGL_API_FILES) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
diff --git a/src/VBox/Additions/common/crOpenGL/defs64.py b/src/VBox/Additions/common/crOpenGL/defs64.py
new file mode 100644
index 000000000..69a71dbc5
--- /dev/null
+++ b/src/VBox/Additions/common/crOpenGL/defs64.py
@@ -0,0 +1,479 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+import sys
+
+import apiutil
+
+apiutil.CopyrightDef()
+
+print "LIBRARY VBoxOGL"
+print "DESCRIPTION \"\""
+print "EXPORTS"
+
+# XXX can't these values be automatically computed by analyzing parameters?
+
+exports_special = [
+ 'Accum',
+ 'AlphaFunc',
+ 'AreTexturesResident',
+ 'ArrayElement',
+ 'Begin',
+ 'BindTexture',
+ 'Bitmap',
+ 'BlendFunc',
+ 'CallList',
+ 'CallLists',
+ 'Clear',
+ 'ClearAccum',
+ 'ClearColor',
+ 'ClearDepth',
+ 'ClearIndex',
+ 'ClearStencil',
+ 'ClipPlane',
+ 'Color3b',
+ 'Color3bv',
+ 'Color3d',
+ 'Color3dv',
+ 'Color3f',
+ 'Color3fv',
+ 'Color3i',
+ 'Color3iv',
+ 'Color3s',
+ 'Color3sv',
+ 'Color3ub',
+ 'Color3ubv',
+ 'Color3ui',
+ 'Color3uiv',
+ 'Color3us',
+ 'Color3usv',
+ 'Color4b',
+ 'Color4bv',
+ 'Color4d',
+ 'Color4dv',
+ 'Color4f',
+ 'Color4fv',
+ 'Color4i',
+ 'Color4iv',
+ 'Color4s',
+ 'Color4sv',
+ 'Color4ub',
+ 'Color4ubv',
+ 'Color4ui',
+ 'Color4uiv',
+ 'Color4us',
+ 'Color4usv',
+ 'ColorMask',
+ 'ColorMaterial',
+ 'ColorPointer',
+ 'CopyPixels',
+ 'CopyTexImage1D',
+ 'CopyTexImage2D',
+ 'CopyTexSubImage1D',
+ 'CopyTexSubImage2D',
+ 'CullFace',
+ 'DebugEntry',
+ 'DeleteLists',
+ 'DeleteTextures',
+ 'DepthFunc',
+ 'DepthMask',
+ 'DepthRange',
+ 'Disable',
+ 'DisableClientState',
+ 'DrawArrays',
+ 'DrawBuffer',
+ 'DrawElements',
+ 'DrawPixels',
+ 'EdgeFlag',
+ 'EdgeFlagPointer',
+ 'EdgeFlagv',
+ 'Enable',
+ 'EnableClientState',
+ 'End',
+ 'EndList',
+ 'EvalCoord1d',
+ 'EvalCoord1dv',
+ 'EvalCoord1f',
+ 'EvalCoord1fv',
+ 'EvalCoord2d',
+ 'EvalCoord2dv',
+ 'EvalCoord2f',
+ 'EvalCoord2fv',
+ 'EvalMesh1',
+ 'EvalMesh2',
+ 'EvalPoint1',
+ 'EvalPoint2',
+ 'FeedbackBuffer',
+ 'Finish',
+ 'Flush',
+ 'Fogf',
+ 'Fogfv',
+ 'Fogi',
+ 'Fogiv',
+ 'FrontFace',
+ 'Frustum',
+ 'GenLists',
+ 'GenTextures',
+ 'GetBooleanv',
+ 'GetClipPlane',
+ 'GetDoublev',
+ 'GetError',
+ 'GetFloatv',
+ 'GetIntegerv',
+ 'GetLightfv',
+ 'GetLightiv',
+ 'GetMapdv',
+ 'GetMapfv',
+ 'GetMapiv',
+ 'GetMaterialfv',
+ 'GetMaterialiv',
+ 'GetPixelMapfv',
+ 'GetPixelMapuiv',
+ 'GetPixelMapusv',
+ 'GetPointerv',
+ 'GetPolygonStipple',
+ 'GetString',
+ 'GetTexEnvfv',
+ 'GetTexEnviv',
+ 'GetTexGendv',
+ 'GetTexGenfv',
+ 'GetTexGeniv',
+ 'GetTexImage',
+ 'GetTexLevelParameterfv',
+ 'GetTexLevelParameteriv',
+ 'GetTexParameterfv',
+ 'GetTexParameteriv',
+ 'Hint',
+ 'IndexMask',
+ 'IndexPointer',
+ 'Indexd',
+ 'Indexdv',
+ 'Indexf',
+ 'Indexfv',
+ 'Indexi',
+ 'Indexiv',
+ 'Indexs',
+ 'Indexsv',
+ 'Indexub',
+ 'Indexubv',
+ 'InitNames',
+ 'InterleavedArrays',
+ 'IsEnabled',
+ 'IsList',
+ 'IsTexture',
+ 'LightModelf',
+ 'LightModelfv',
+ 'LightModeli',
+ 'LightModeliv',
+ 'Lightf',
+ 'Lightfv',
+ 'Lighti',
+ 'Lightiv',
+ 'LineStipple',
+ 'LineWidth',
+ 'ListBase',
+ 'LoadIdentity',
+ 'LoadMatrixd',
+ 'LoadMatrixf',
+ 'LoadName',
+ 'LogicOp',
+ 'Map1d',
+ 'Map1f',
+ 'Map2d',
+ 'Map2f',
+ 'MapGrid1d',
+ 'MapGrid1f',
+ 'MapGrid2d',
+ 'MapGrid2f',
+ 'Materialf',
+ 'Materialfv',
+ 'Materiali',
+ 'Materialiv',
+ 'MatrixMode',
+ 'MultMatrixd',
+ 'MultMatrixf',
+ 'NewList',
+ 'Normal3b',
+ 'Normal3bv',
+ 'Normal3d',
+ 'Normal3dv',
+ 'Normal3f',
+ 'Normal3fv',
+ 'Normal3i',
+ 'Normal3iv',
+ 'Normal3s',
+ 'Normal3sv',
+ 'NormalPointer',
+ 'Ortho',
+ 'PassThrough',
+ 'PixelMapfv',
+ 'PixelMapuiv',
+ 'PixelMapusv',
+ 'PixelStoref',
+ 'PixelStorei',
+ 'PixelTransferf',
+ 'PixelTransferi',
+ 'PixelZoom',
+ 'PointSize',
+ 'PolygonMode',
+ 'PolygonOffset',
+ 'PolygonStipple',
+ 'PopAttrib',
+ 'PopClientAttrib',
+ 'PopMatrix',
+ 'PopName',
+ 'PrioritizeTextures',
+ 'PushAttrib',
+ 'PushClientAttrib',
+ 'PushMatrix',
+ 'PushName',
+ 'RasterPos2d',
+ 'RasterPos2dv',
+ 'RasterPos2f',
+ 'RasterPos2fv',
+ 'RasterPos2i',
+ 'RasterPos2iv',
+ 'RasterPos2s',
+ 'RasterPos2sv',
+ 'RasterPos3d',
+ 'RasterPos3dv',
+ 'RasterPos3f',
+ 'RasterPos3fv',
+ 'RasterPos3i',
+ 'RasterPos3iv',
+ 'RasterPos3s',
+ 'RasterPos3sv',
+ 'RasterPos4d',
+ 'RasterPos4dv',
+ 'RasterPos4f',
+ 'RasterPos4fv',
+ 'RasterPos4i',
+ 'RasterPos4iv',
+ 'RasterPos4s',
+ 'RasterPos4sv',
+ 'ReadBuffer',
+ 'ReadPixels',
+ 'Rectd',
+ 'Rectdv',
+ 'Rectf',
+ 'Rectfv',
+ 'Recti',
+ 'Rectiv',
+ 'Rects',
+ 'Rectsv',
+ 'RenderMode',
+ 'Rotated',
+ 'Rotatef',
+ 'Scaled',
+ 'Scalef',
+ 'Scissor',
+ 'SelectBuffer',
+ 'ShadeModel',
+ 'StencilFunc',
+ 'StencilMask',
+ 'StencilOp',
+ 'TexCoord1d',
+ 'TexCoord1dv',
+ 'TexCoord1f',
+ 'TexCoord1fv',
+ 'TexCoord1i',
+ 'TexCoord1iv',
+ 'TexCoord1s',
+ 'TexCoord1sv',
+ 'TexCoord2d',
+ 'TexCoord2dv',
+ 'TexCoord2f',
+ 'TexCoord2fv',
+ 'TexCoord2i',
+ 'TexCoord2iv',
+ 'TexCoord2s',
+ 'TexCoord2sv',
+ 'TexCoord3d',
+ 'TexCoord3dv',
+ 'TexCoord3f',
+ 'TexCoord3fv',
+ 'TexCoord3i',
+ 'TexCoord3iv',
+ 'TexCoord3s',
+ 'TexCoord3sv',
+ 'TexCoord4d',
+ 'TexCoord4dv',
+ 'TexCoord4f',
+ 'TexCoord4fv',
+ 'TexCoord4i',
+ 'TexCoord4iv',
+ 'TexCoord4s',
+ 'TexCoord4sv',
+ 'TexCoordPointer',
+ 'TexEnvf',
+ 'TexEnvfv',
+ 'TexEnvi',
+ 'TexEnviv',
+ 'TexGend',
+ 'TexGendv',
+ 'TexGenf',
+ 'TexGenfv',
+ 'TexGeni',
+ 'TexGeniv',
+ 'TexImage1D',
+ 'TexImage2D',
+ 'TexImage3D',
+ 'TexParameterf',
+ 'TexParameterfv',
+ 'TexParameteri',
+ 'TexParameteriv',
+ 'TexSubImage1D',
+ 'TexSubImage2D',
+ 'Translated',
+ 'Translatef',
+ 'Vertex2d',
+ 'Vertex2dv',
+ 'Vertex2f',
+ 'Vertex2fv',
+ 'Vertex2i',
+ 'Vertex2iv',
+ 'Vertex2s',
+ 'Vertex2sv',
+ 'Vertex3d',
+ 'Vertex3dv',
+ 'Vertex3f',
+ 'Vertex3fv',
+ 'Vertex3i',
+ 'Vertex3iv',
+ 'Vertex3s',
+ 'Vertex3sv',
+ 'Vertex4d',
+ 'Vertex4dv',
+ 'Vertex4f',
+ 'Vertex4fv',
+ 'Vertex4i',
+ 'Vertex4iv',
+ 'Vertex4s',
+ 'Vertex4sv',
+ 'VertexPointer',
+ 'Viewport',
+ 'wglChoosePixelFormat',
+ 'wglCopyContext',
+ 'wglCreateContext',
+ 'wglCreateLayerContext',
+ 'wglDeleteContext',
+ 'wglDescribeLayerPlane',
+ 'wglDescribePixelFormat',
+ 'wglGetCurrentContext',
+ 'wglGetCurrentDC',
+ 'wglGetDefaultProcAddress',
+ 'wglGetLayerPaletteEntries',
+ 'wglGetPixelFormat',
+ 'wglGetProcAddress',
+ 'wglMakeCurrent',
+ 'wglRealizeLayerPalette',
+ 'wglSetLayerPaletteEntries',
+ 'wglSetPixelFormat',
+ 'wglShareLists',
+ 'wglSwapBuffers',
+ 'wglSwapLayerBuffers',
+ 'wglSwapMultipleBuffers',
+ 'wglUseFontBitmapsA',
+ 'wglUseFontBitmapsW',
+ 'wglUseFontOutlinesA',
+ 'wglUseFontOutlinesW',
+ 'wglChoosePixelFormatEXT',
+ 'wglGetPixelFormatAttribivEXT',
+ 'wglGetPixelFormatAttribfvEXT',
+ 'wglGetExtensionsStringEXT',
+ 'CopyContext',
+ 'CreateContext',
+ 'CreateLayerContext',
+ 'DeleteContext',
+ 'DescribeLayerPlane',
+ 'DescribePixelFormat',
+ 'GetLayerPaletteEntries',
+ 'GetProcAddress',
+ 'RealizeLayerPalette',
+ 'ReleaseContext',
+ 'SetContext',
+ 'SetLayerPaletteEntries',
+ 'SetPixelFormat',
+ 'ShareLists',
+ 'SwapBuffers',
+ 'SwapLayerBuffers',
+ 'ValidateVersion',
+]
+
+noexport_special = [
+ "BoundsInfoCR",
+ "CreateContext",
+ "DestroyContext",
+ "MakeCurrent",
+ "WindowCreate",
+ "WindowDestroy",
+ "WindowSize",
+ "WindowPosition",
+ "WindowVisibleRegion",
+ "WindowShow",
+ "SwapBuffers"
+]
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+
+for func_name in keys:
+ if func_name in noexport_special:
+ continue
+ if func_name in exports_special:
+ print "gl%s = cr_gl%s" % (func_name,func_name)
+
+for func_name in ( "wglChoosePixelFormat",
+ "wglCopyContext",
+ "wglCreateContext",
+ "wglCreateLayerContext",
+ "wglDeleteContext",
+ "wglDescribeLayerPlane",
+ "wglDescribePixelFormat",
+ "wglGetCurrentContext",
+ "wglGetCurrentDC",
+ "wglGetLayerPaletteEntries",
+ "wglGetPixelFormat",
+ "wglGetProcAddress",
+ "wglMakeCurrent",
+ "wglRealizeLayerPalette",
+ "wglSetLayerPaletteEntries",
+ "wglSetPixelFormat",
+ "wglShareLists",
+ "wglSwapBuffers",
+ "wglSwapLayerBuffers",
+ "wglSwapMultipleBuffers",
+ "wglUseFontBitmapsA",
+ "wglUseFontBitmapsW",
+ "wglUseFontOutlinesA",
+ "wglUseFontOutlinesW",
+ "wglChoosePixelFormatEXT",
+ "wglGetPixelFormatAttribivEXT",
+ "wglGetPixelFormatAttribfvEXT",
+ "wglGetExtensionsStringEXT"):
+ print "%s = %s_prox" % (func_name,func_name)
+
+print """DrvCopyContext
+DrvCreateContext
+DrvCreateLayerContext
+DrvDeleteContext
+DrvDescribeLayerPlane
+DrvDescribePixelFormat
+DrvGetLayerPaletteEntries
+DrvGetProcAddress = wglGetProcAddress_prox
+DrvRealizeLayerPalette
+DrvSetLayerPaletteEntries
+DrvShareLists
+DrvSwapBuffers
+DrvSwapLayerBuffers
+DrvReleaseContext = DrvReleaseContext
+DrvSetContext = DrvSetContext
+DrvValidateVersion = DrvValidateVersion
+DrvSetPixelFormat = DrvSetPixelFormat"""
+
+print """crCreateContext
+crMakeCurrent
+crSwapBuffers
+crGetProcAddress"""
+#print "DllMain"
diff --git a/src/VBox/Additions/linux/export_modules b/src/VBox/Additions/linux/export_modules
index b0f925f14..a8c929ed2 100755
--- a/src/VBox/Additions/linux/export_modules
+++ b/src/VBox/Additions/linux/export_modules
@@ -25,15 +25,23 @@ PATH_TMP="`cd \`dirname $1\`; pwd`/.vbox_modules"
PATH_OUT=$PATH_TMP
FILE_OUT="`cd \`dirname $1\`; pwd`/`basename $1`"
PATH_ROOT="`cd \`dirname $0\`/../../../..; pwd`"
+PATH_LINUX="$PATH_ROOT/src/VBox/Additions/linux"
PATH_VBOXGUEST="$PATH_ROOT/src/VBox/Additions/common/VBoxGuest"
PATH_VBOXSF="$PATH_ROOT/src/VBox/Additions/linux/sharedfolders"
+PATH_VBOXVIDEO="$PATH_ROOT/src/VBox/Additions/linux/drm"
VBOX_VERSION_MAJOR=`sed -e "s/^ *VBOX_VERSION_MAJOR *= \+\([0-9]\+\)/\1/;t;d" $PATH_ROOT/Config.kmk`
VBOX_VERSION_MINOR=`sed -e "s/^ *VBOX_VERSION_MINOR *= \+\([0-9]\+\)/\1/;t;d" $PATH_ROOT/Config.kmk`
VBOX_VERSION_BUILD=`sed -e "s/^ *VBOX_VERSION_BUILD *= \+\([0-9]\+\)/\1/;t;d" $PATH_ROOT/Config.kmk`
+VBOX_SVN_REV=`sed -e 's/^ *VBOX_SVN_REV_FALLBACK *:= \+\$(patsubst *%:,, *\$Rev: *\([0-9]\+\) *\$ *) */\1/;t;d' $PATH_ROOT/Config.kmk`
+VBOX_VENDOR=`sed -e 's/^ *VBOX_VENDOR *= \+\(.\+\)/\1/;t;d' $PATH_ROOT/Config.kmk`
+VBOX_VENDOR_SHORT=`sed -e 's/^ *VBOX_VENDOR_SHORT *= \+\(.\+\)/\1/;t;d' $PATH_ROOT/Config.kmk`
+VBOX_PRODUCT=`sed -e 's/^ *VBOX_PRODUCT *= \+\(.\+\)/\1/;t;d' $PATH_ROOT/Config.kmk`
+VBOX_C_YEAR=`date +%Y`
. $PATH_VBOXGUEST/linux/files_vboxguest
. $PATH_VBOXSF/files_vboxsf
+. $PATH_VBOXVIDEO/files_vboxvideo_drm
# Temporary path for creating the modules, will be removed later
mkdir $PATH_TMP || exit 1
@@ -49,6 +57,26 @@ echo "#define VBOX_VERSION_STRING \"$VBOX_VERSION_MAJOR.$VBOX_VERSION_MINOR.$VBO
echo "" >> $PATH_TMP/version-generated.h
echo "#endif" >> $PATH_TMP/version-generated.h
+# Create auto-generated revision file, needed by all modules
+echo "#ifndef __revision_generated_h__" > $PATH_TMP/revision-generated.h
+echo "#define __revision_generated_h__" >> $PATH_TMP/revision-generated.h
+echo "" >> $PATH_TMP/revision-generated.h
+echo "#define VBOX_SVN_REV $VBOX_SVN_REV" >> $PATH_TMP/revision-generated.h
+echo "" >> $PATH_TMP/revision-generated.h
+echo "#endif" >> $PATH_TMP/revision-generated.h
+
+# Create auto-generated product file, needed by all modules
+echo "#ifndef __product_generated_h__" > $PATH_TMP/product-generated.h
+echo "#define __product_generated_h__" >> $PATH_TMP/product-generated.h
+echo "" >> $PATH_TMP/product-generated.h
+echo "#define VBOX_VENDOR \"$VBOX_VENDOR\"" >> $PATH_TMP/product-generated.h
+echo "#define VBOX_VENDOR_SHORT \"$VBOX_VENDOR_SHORT\"" >> $PATH_TMP/product-generated.h
+echo "" >> $PATH_TMP/product-generated.h
+echo "#define VBOX_PRODUCT \"$VBOX_PRODUCT\"" >> $PATH_TMP/product-generated.h
+echo "#define VBOX_C_YEAR \"$VBOX_C_YEAR\"" >> $PATH_TMP/product-generated.h
+echo "" >> $PATH_TMP/product-generated.h
+echo "#endif" >> $PATH_TMP/product-generated.h
+
# vboxguest (VirtualBox guest kernel module)
mkdir $PATH_TMP/vboxguest || exit 1
for f in $FILES_VBOXGUEST_NOBIN; do
@@ -67,8 +95,22 @@ for f in $FILES_VBOXSF_BIN; do
install -D -m 0755 `echo $f|cut -d'=' -f1` "$PATH_TMP/vboxsf/`echo $f|cut -d'>' -f2`"
done
+# vboxvideo (VirtualBox guest kernel module for drm support)
+mkdir $PATH_TMP/vboxvideo || exit 1
+for f in $FILES_VBOXVIDEO_DRM_NOBIN; do
+ install -D -m 0644 `echo $f|cut -d'=' -f1` "$PATH_TMP/vboxvideo/`echo $f|cut -d'>' -f2`"
+done
+for f in $FILES_VBOXVIDEO_DRM_BIN; do
+ install -D -m 0755 `echo $f|cut -d'=' -f1` "$PATH_TMP/vboxvideo/`echo $f|cut -d'>' -f2`"
+done
+
+# convenience Makefile
+install -D -m 0644 $PATH_LINUX/Makefile "$PATH_TMP/Makefile"
+
# Only temporary, omit from archive
rm $PATH_TMP/version-generated.h
+rm $PATH_TMP/revision-generated.h
+rm $PATH_TMP/product-generated.h
# Create the archive
tar -czf $FILE_OUT -C $PATH_TMP . || exit 1
diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c
index 59623c14d..8cf3147a7 100644
--- a/src/VBox/Additions/linux/sharedfolders/regops.c
+++ b/src/VBox/Additions/linux/sharedfolders/regops.c
@@ -521,7 +521,11 @@ struct file_operations sf_reg_fops = {
# endif
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
+# if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 35)
+ .fsync = noop_fsync,
+# else
.fsync = simple_sync_file,
+# endif
.llseek = generic_file_llseek,
#endif
};
diff --git a/src/VBox/Additions/solaris/Installer/postinstall.sh b/src/VBox/Additions/solaris/Installer/postinstall.sh
index 3cf906989..b2a058cdc 100644
--- a/src/VBox/Additions/solaris/Installer/postinstall.sh
+++ b/src/VBox/Additions/solaris/Installer/postinstall.sh
@@ -280,10 +280,18 @@ if test ! -z "$xorgbin"; then
/usr/sbin/installf -c none $PKGINST $vboxclient_dest/1099.vboxclient=$vboxadditions_path/1099.vboxclient s
clientinstalled=1
fi
+
+ # Try other autostart locations if none of the above ones work
if test $clientinstalled -eq 0; then
- echo "*** Failed to configure client, couldn't find any autostart directory!"
- # Exit as partially failed installation
- retval=2
+ vboxclient_dest="/etc/xdg/autostart"
+ if test -d "$vboxclient_dest"; then
+ /usr/sbin/installf -c none $PKGINST $vboxclient_dest/1099.vboxclient=$vboxadditions_path/1099.vboxclient s
+ clientinstalled=1
+ else
+ echo "*** Failed to configure client, couldn't find any autostart directory!"
+ # Exit as partially failed installation
+ retval=2
+ fi
fi
else
echo "(*) X.Org not found, skipped configuring X.Org guest additions."
diff --git a/src/VBox/Additions/x11/vboxmouse/xorg71/mouse.c b/src/VBox/Additions/x11/vboxmouse/xorg71/mouse.c
index bae37d122..1cab60627 100644
--- a/src/VBox/Additions/x11/vboxmouse/xorg71/mouse.c
+++ b/src/VBox/Additions/x11/vboxmouse/xorg71/mouse.c
@@ -75,6 +75,9 @@
#include <math.h>
#include <string.h>
+#ifdef RT_OS_FREEBSD
+# include <strings.h>
+#endif
#include <stdio.h>
#define NEED_EVENTS
#include <X11/X.h>