diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/common/VBoxControl/VBoxControl.cpp | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-master.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/common/VBoxControl/VBoxControl.cpp')
-rw-r--r-- | src/VBox/Additions/common/VBoxControl/VBoxControl.cpp | 392 |
1 files changed, 327 insertions, 65 deletions
diff --git a/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp b/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp index afa7b69c..13242a09 100644 --- a/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp +++ b/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2008-2010 Oracle Corporation + * Copyright (C) 2008-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -36,6 +36,11 @@ #ifdef VBOX_WITH_GUEST_PROPS # include <VBox/HostServices/GuestPropertySvc.h> #endif +#ifdef VBOX_WITH_DPC_LATENCY_CHECKER +# include <VBox/VBoxGuest.h> +# include "../VBoxGuestLib/VBGLR3Internal.h" /* HACK ALERT! Using vbglR3DoIOCtl directly!! */ +#endif + /******************************************************************************* * Global Variables * @@ -70,6 +75,7 @@ enum VBoxControlUsage #ifdef RT_OS_WINDOWS GET_VIDEO_ACCEL, SET_VIDEO_ACCEL, + VIDEO_FLAGS, LIST_CUST_MODES, ADD_CUST_MODE, REMOVE_CUST_MODE, @@ -100,27 +106,30 @@ static void usage(enum VBoxControlUsage eWhich = USAGE_ALL) doUsage("suppress the logo", g_pszProgName, "--nologo ..."); RTPrintf("\n"); -/* Exclude the Windows bits from the test version. Anyone who needs to test - * them can fix this. */ + /* Exclude the Windows bits from the test version. Anyone who needs to + test them can fix this. */ #if defined(RT_OS_WINDOWS) && !defined(VBOX_CONTROL_TEST) - if (GET_VIDEO_ACCEL == eWhich || eWhich == USAGE_ALL) + if (eWhich == GET_VIDEO_ACCEL || eWhich == USAGE_ALL) doUsage("", g_pszProgName, "getvideoacceleration"); - if (SET_VIDEO_ACCEL == eWhich || eWhich == USAGE_ALL) + if (eWhich == SET_VIDEO_ACCEL || eWhich == USAGE_ALL) doUsage("<on|off>", g_pszProgName, "setvideoacceleration"); - if (LIST_CUST_MODES == eWhich || eWhich == USAGE_ALL) + if (eWhich == VIDEO_FLAGS || eWhich == USAGE_ALL) + doUsage("<get|set|clear|delete> [hex mask]", g_pszProgName, "videoflags"); + if (eWhich == LIST_CUST_MODES || eWhich == USAGE_ALL) doUsage("", g_pszProgName, "listcustommodes"); - if (ADD_CUST_MODE == eWhich || eWhich == USAGE_ALL) + if (eWhich == ADD_CUST_MODE || eWhich == USAGE_ALL) doUsage("<width> <height> <bpp>", g_pszProgName, "addcustommode"); - if (REMOVE_CUST_MODE == eWhich || eWhich == USAGE_ALL) + if (eWhich == REMOVE_CUST_MODE || eWhich == USAGE_ALL) doUsage("<width> <height> <bpp>", g_pszProgName, "removecustommode"); - if (SET_VIDEO_MODE == eWhich || eWhich == USAGE_ALL) + if (eWhich == SET_VIDEO_MODE || eWhich == USAGE_ALL) doUsage("<width> <height> <bpp> <screen>", g_pszProgName, "setvideomode"); #endif #ifdef VBOX_WITH_GUEST_PROPS - if (GUEST_PROP == eWhich || eWhich == USAGE_ALL) + if (eWhich == GUEST_PROP || eWhich == USAGE_ALL) { doUsage("get <property> [--verbose]", g_pszProgName, "guestproperty"); doUsage("set <property> [<value> [--flags <flags>]]", g_pszProgName, "guestproperty"); + doUsage("delete|unset <property>", g_pszProgName, "guestproperty"); doUsage("enumerate [--patterns <patterns>]", g_pszProgName, "guestproperty"); doUsage("wait <patterns>", g_pszProgName, "guestproperty"); doUsage("[--timestamp <last timestamp>]"); @@ -128,7 +137,7 @@ static void usage(enum VBoxControlUsage eWhich = USAGE_ALL) } #endif #ifdef VBOX_WITH_SHARED_FOLDERS - if (GUEST_SHAREDFOLDERS == eWhich || eWhich == USAGE_ALL) + if (eWhich == GUEST_SHAREDFOLDERS || eWhich == USAGE_ALL) { doUsage("list [-automount]", g_pszProgName, "sharedfolder"); } @@ -575,7 +584,7 @@ static RTEXITCODE handleSetVideoMode(int argc, char *argv[]) scr = atoi(argv[3]); } - HMODULE hUser = GetModuleHandle("USER32"); + HMODULE hUser = GetModuleHandle("user32.dll"); if (hUser) { @@ -603,38 +612,120 @@ static RTEXITCODE handleSetVideoMode(int argc, char *argv[]) return RTEXITCODE_SUCCESS; } -HKEY getVideoKey(bool writable) +static int checkVBoxVideoKey(HKEY hkeyVideo) { - HKEY hkeyDeviceMap = 0; - HKEY hkeyVideo = 0; - LONG status; + char szValue[128]; + DWORD len = sizeof(szValue); + DWORD dwKeyType; + LONG status = RegQueryValueExA(hkeyVideo, "Device Description", NULL, &dwKeyType, + (LPBYTE)szValue, &len); - status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap); - if ((status != ERROR_SUCCESS) || !hkeyDeviceMap) + if (status == ERROR_SUCCESS) + { + /* WDDM has additional chars after "Adapter" */ + static char sszDeviceDescription[] = "VirtualBox Graphics Adapter"; + if (_strnicmp(szValue, sszDeviceDescription, sizeof(sszDeviceDescription) - sizeof(char)) == 0) + { + return VINF_SUCCESS; + } + } + + return VERR_NOT_FOUND; +} + +static HKEY getVideoKey(bool writable) +{ + HKEY hkeyDeviceMap = 0; + LONG status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap); + if (status != ERROR_SUCCESS || !hkeyDeviceMap) { VBoxControlError("Error opening video device map registry key!\n"); return 0; } - char szVideoLocation[256]; + + HKEY hkeyVideo = 0; + ULONG iDevice; DWORD dwKeyType; - szVideoLocation[0] = 0; - DWORD len = sizeof(szVideoLocation); - status = RegQueryValueExA(hkeyDeviceMap, "\\Device\\Video0", NULL, &dwKeyType, (LPBYTE)szVideoLocation, &len); + /* - * This value will start with a weird value: \REGISTRY\Machine - * Make sure this is true. + * Scan all '\Device\VideoX' REG_SZ keys to find VBox video driver entry. + * 'ObjectNumberList' REG_BINARY is an array of 32 bit device indexes (X). */ - if ( (status == ERROR_SUCCESS) - && (dwKeyType == REG_SZ) - && (_strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0)) + + /* Get the 'ObjectNumberList' */ + ULONG numDevices = 0; + DWORD adwObjectNumberList[256]; + DWORD len = sizeof(adwObjectNumberList); + status = RegQueryValueExA(hkeyDeviceMap, "ObjectNumberList", NULL, &dwKeyType, (LPBYTE)&adwObjectNumberList[0], &len); + + if ( status == ERROR_SUCCESS + && dwKeyType == REG_BINARY) { - /* open that branch */ - status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo); + numDevices = len / sizeof(DWORD); } else { - VBoxControlError("Error opening registry key '%s'\n", &szVideoLocation[18]); + /* The list might not exists. Use 'MaxObjectNumber' REG_DWORD and build a list. */ + DWORD dwMaxObjectNumber = 0; + len = sizeof(dwMaxObjectNumber); + status = RegQueryValueExA(hkeyDeviceMap, "MaxObjectNumber", NULL, &dwKeyType, (LPBYTE)&dwMaxObjectNumber, &len); + + if ( status == ERROR_SUCCESS + && dwKeyType == REG_DWORD) + { + /* 'MaxObjectNumber' is inclusive. */ + numDevices = RT_MIN(dwMaxObjectNumber + 1, RT_ELEMENTS(adwObjectNumberList)); + for (iDevice = 0; iDevice < numDevices; iDevice++) + { + adwObjectNumberList[iDevice] = iDevice; + } + } } + + if (numDevices == 0) + { + /* Always try '\Device\Video0' as the old code did. Enum can be used in this case in principle. */ + adwObjectNumberList[0] = 0; + numDevices = 1; + } + + /* Scan device entries */ + for (iDevice = 0; iDevice < numDevices; iDevice++) + { + char szValueName[64]; + RTStrPrintf(szValueName, sizeof(szValueName), "\\Device\\Video%u", adwObjectNumberList[iDevice]); + + char szVideoLocation[256]; + len = sizeof(szVideoLocation); + status = RegQueryValueExA(hkeyDeviceMap, szValueName, NULL, &dwKeyType, (LPBYTE)&szVideoLocation[0], &len); + + /* This value starts with '\REGISTRY\Machine' */ + if ( status == ERROR_SUCCESS + && dwKeyType == REG_SZ + && _strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0) + { + status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, + KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo); + if (status == ERROR_SUCCESS) + { + int rc = checkVBoxVideoKey(hkeyVideo); + if (RT_SUCCESS(rc)) + { + /* Found, return hkeyVideo to the caller. */ + break; + } + + RegCloseKey(hkeyVideo); + hkeyVideo = 0; + } + } + } + + if (hkeyVideo == 0) + { + VBoxControlError("Error opening video registry key!\n"); + } + RegCloseKey(hkeyDeviceMap); return hkeyVideo; } @@ -692,6 +783,135 @@ static RTEXITCODE handleSetVideoAcceleration(int argc, char *argv[]) return RTEXITCODE_SUCCESS; } +static RTEXITCODE videoFlagsGet(void) +{ + HKEY hkeyVideo = getVideoKey(false); + + if (hkeyVideo) + { + DWORD dwFlags = 0; + DWORD len = sizeof(dwFlags); + DWORD dwKeyType; + ULONG status = RegQueryValueExA(hkeyVideo, "VBoxVideoFlags", NULL, &dwKeyType, (LPBYTE)&dwFlags, &len); + if (status != ERROR_SUCCESS) + RTPrintf("Video flags: default\n"); + else + RTPrintf("Video flags: 0x%08X\n", dwFlags); + RegCloseKey(hkeyVideo); + return RTEXITCODE_SUCCESS; + } + + return RTEXITCODE_FAILURE; +} + +static RTEXITCODE videoFlagsDelete(void) +{ + HKEY hkeyVideo = getVideoKey(true); + + if (hkeyVideo) + { + ULONG status = RegDeleteValueA(hkeyVideo, "VBoxVideoFlags"); + if (status != ERROR_SUCCESS) + VBoxControlError("Error %d deleting video flags.\n", status); + RegCloseKey(hkeyVideo); + return RTEXITCODE_SUCCESS; + } + + return RTEXITCODE_FAILURE; +} + +static RTEXITCODE videoFlagsModify(bool fSet, int argc, char *argv[]) +{ + if (argc != 1) + { + VBoxControlError("Mask required.\n"); + return RTEXITCODE_FAILURE; + } + + uint32_t u32Mask = 0; + int rc = RTStrToUInt32Full(argv[0], 16, &u32Mask); + if (RT_FAILURE(rc)) + { + VBoxControlError("Invalid video flags mask.\n"); + return RTEXITCODE_FAILURE; + } + + RTEXITCODE exitCode = RTEXITCODE_SUCCESS; + + HKEY hkeyVideo = getVideoKey(true); + if (hkeyVideo) + { + DWORD dwFlags = 0; + DWORD len = sizeof(dwFlags); + DWORD dwKeyType; + ULONG status = RegQueryValueExA(hkeyVideo, "VBoxVideoFlags", NULL, &dwKeyType, (LPBYTE)&dwFlags, &len); + if (status != ERROR_SUCCESS) + { + dwFlags = 0; + } + + dwFlags = fSet? (dwFlags | u32Mask): + (dwFlags & ~u32Mask); + + status = RegSetValueExA(hkeyVideo, "VBoxVideoFlags", 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags)); + if (status != ERROR_SUCCESS) + { + VBoxControlError("Error %d writing video flags.\n", status); + exitCode = RTEXITCODE_FAILURE; + } + + RegCloseKey(hkeyVideo); + } + else + { + exitCode = RTEXITCODE_FAILURE; + } + + return exitCode; +} + +static RTEXITCODE handleVideoFlags(int argc, char *argv[]) +{ + /* Must have a keyword and optional value (32 bit hex string). */ + if (argc != 1 && argc != 2) + { + VBoxControlError("Invalid number of arguments.\n"); + usage(VIDEO_FLAGS); + return RTEXITCODE_FAILURE; + } + + RTEXITCODE exitCode = RTEXITCODE_SUCCESS; + + if (RTStrICmp(argv[0], "get") == 0) + { + exitCode = videoFlagsGet(); + } + else if (RTStrICmp(argv[0], "delete") == 0) + { + exitCode = videoFlagsDelete(); + } + else if (RTStrICmp(argv[0], "set") == 0) + { + exitCode = videoFlagsModify(true, argc - 1, &argv[1]); + } + else if (RTStrICmp(argv[0], "clear") == 0) + { + exitCode = videoFlagsModify(false, argc - 1, &argv[1]); + } + else + { + VBoxControlError("Invalid command.\n"); + exitCode = RTEXITCODE_FAILURE; + } + + if (exitCode != RTEXITCODE_SUCCESS) + { + usage(VIDEO_FLAGS); + } + + return exitCode; +} + #define MAX_CUSTOM_MODES 128 /* the table of custom modes */ @@ -1092,6 +1312,51 @@ static RTEXITCODE setGuestProperty(int argc, char *argv[]) /** + * Deletes a guest property from the guest property store. + * This is accessed through the "VBoxGuestPropSvc" HGCM service. + * + * @returns Command exit code. + * @note see the command line API description for parameters + */ +static RTEXITCODE deleteGuestProperty(int argc, char *argv[]) +{ + /* + * Check the syntax. We can deduce the correct syntax from the number of + * arguments. + */ + bool usageOK = true; + const char *pszName = NULL; + if (argc < 1) + usageOK = false; + if (!usageOK) + { + usage(GUEST_PROP); + return RTEXITCODE_FAILURE; + } + /* This is always needed. */ + pszName = argv[0]; + + /* + * Do the actual setting. + */ + uint32_t u32ClientId = 0; + int rc = VbglR3GuestPropConnect(&u32ClientId); + if (!RT_SUCCESS(rc)) + VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc); + if (RT_SUCCESS(rc)) + { + rc = VbglR3GuestPropDelete(u32ClientId, pszName); + if (!RT_SUCCESS(rc)) + VBoxControlError("Failed to delete the property value, error %Rrc\n", rc); + } + + if (u32ClientId != 0) + VbglR3GuestPropDisconnect(u32ClientId); + return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** * Enumerates the properties in the guest property store. * This is accessed through the "VBoxGuestPropSvc" HGCM service. * @@ -1311,6 +1576,8 @@ static RTEXITCODE handleGuestProperty(int argc, char *argv[]) return getGuestProperty(argc - 1, argv + 1); else if (!strcmp(argv[0], "set")) return setGuestProperty(argc - 1, argv + 1); + else if (!strcmp(argv[0], "delete") || !strcmp(argv[0], "unset")) + return deleteGuestProperty(argc - 1, argv + 1); else if (!strcmp(argv[0], "enumerate")) return enumGuestProperty(argc - 1, argv + 1); else if (!strcmp(argv[0], "wait")) @@ -1429,6 +1696,32 @@ static RTEXITCODE handleWriteCoreDump(int argc, char *argv[]) } #endif +#ifdef VBOX_WITH_DPC_LATENCY_CHECKER +/** + * @callback_method_impl{FNVBOXCTRLCMDHANDLER, Command: help} + */ +static RTEXITCODE handleDpc(int argc, char *argv[]) +{ +# ifndef VBOX_CONTROL_TEST + int rc; + for (int i = 0; i < 30; i++) + { + rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_DPC_LATENCY_CHECKER, NULL, 0); + if (RT_FAILURE(rc)) + break; + RTPrintf("%d\n", i); + } +# else + int rc = VERR_NOT_IMPLEMENTED; +# endif + if (RT_FAILURE(rc)) + return VBoxControlError("Error. rc=%Rrc\n", rc); + RTPrintf("Samples collection completed.\n"); + return RTEXITCODE_SUCCESS; +} +#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ + + /** * @callback_method_impl{FNVBOXCTRLCMDHANDLER, Command: takesnapshot} */ @@ -1486,38 +1779,6 @@ static RTEXITCODE handleHelp(int argc, char *argv[]) return RTEXITCODE_SUCCESS; } -#ifdef VBOX_WITH_DPC_LATENCY_CHECKER -#include "..\VBoxGuestLib\VBGLR3Internal.h" - -static RTEXITCODE handleDpc(int argc, char *argv[]) -{ -#ifndef VBOX_CONTROL_TEST - int rc = VINF_SUCCESS; - int i; - for (i = 0; i < 30; i++) - { - rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_DPC, NULL, 0); - if (RT_FAILURE(rc)) - { - break; - } - RTPrintf("%d\n", i); - } -#else - int rc = VERR_NOT_IMPLEMENTED; -#endif - if (RT_SUCCESS(rc)) - { - RTPrintf("Samples collection completed.\n"); - return RTEXITCODE_SUCCESS; - } - else - { - VBoxControlError("Error. rc=%Rrc\n", rc); - return RTEXITCODE_FAILURE; - } -} -#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ /** command handler type */ typedef DECLCALLBACK(RTEXITCODE) FNVBOXCTRLCMDHANDLER(int argc, char *argv[]); @@ -1533,6 +1794,7 @@ struct COMMANDHANDLER #if defined(RT_OS_WINDOWS) && !defined(VBOX_CONTROL_TEST) { "getvideoacceleration", handleGetVideoAcceleration }, { "setvideoacceleration", handleSetVideoAcceleration }, + { "videoflags", handleVideoFlags }, { "listcustommodes", handleListCustomModes }, { "addcustommode", handleAddCustomMode }, { "removecustommode", handleRemoveCustomMode }, @@ -1547,6 +1809,9 @@ struct COMMANDHANDLER #if !defined(VBOX_CONTROL_TEST) { "writecoredump", handleWriteCoreDump }, #endif +#ifdef VBOX_WITH_DPC_LATENCY_CHECKER + { "dpc", handleDpc }, +#endif { "takesnapshot", handleTakeSnapshot }, { "savestate", handleSaveState }, { "suspend", handleSuspend }, @@ -1555,9 +1820,6 @@ struct COMMANDHANDLER { "powerdown", handlePowerOff }, { "getversion", handleVersion }, { "version", handleVersion }, -#ifdef VBOX_WITH_DPC_LATENCY_CHECKER - { "dpc", handleDpc }, -#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ { "help", handleHelp } }; |