diff options
| author | Michael Meskes <meskes@debian.org> | 2010-06-04 09:49:50 +0200 |
|---|---|---|
| committer | Michael Meskes <meskes@debian.org> | 2010-06-04 09:49:50 +0200 |
| commit | e13debb062071c46f2707d0d0e59c57675b49360 (patch) | |
| tree | 922f54068563b5cf3274bae8ba8122ce4b4ede1d /src/VBox/Additions | |
| parent | abd0051802e55207e88435a185ff8d6e6b8d17d5 (diff) | |
| download | virtualbox-upstream/3.2.2-dfsg.tar.gz | |
Imported Upstream version 3.2.2-dfsgupstream/3.2.2-dfsg
Diffstat (limited to 'src/VBox/Additions')
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> |
