VirtualBox

Ignore:
Timestamp:
Jul 22, 2008 8:12:42 AM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33575
Message:

Guest properties: initial commit of new interface

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp

    r10236 r10797  
    2525*   Header Files                                                               *
    2626*******************************************************************************/
    27 #include <iprt/thread.h>
     27#include <iprt/mem.h>
    2828#include <iprt/string.h>
    2929#include <iprt/stream.h>
    3030#include <iprt/path.h>
    3131#include <iprt/initterm.h>
     32#include <VBox/log.h>
    3233#include <VBox/VBoxGuest.h>
    3334#include <VBox/version.h>
    34 #ifdef VBOX_WITH_INFO_SVC
    35 # include <VBox/HostServices/VBoxInfoSvc.h>
     35#ifdef RT_OS_WINDOWS
     36# include <windows.h>
     37# include <malloc.h>  /* for alloca */
     38#endif
     39#ifdef VBOX_WITH_GUEST_PROPS
     40# include <VBox/HostServices/GuestPropertySvc.h>
    3641#endif
    3742#include "VBoxControl.h"
     
    5762static void doUsage(char const *line, char const *name = "", char const *command = "")
    5863{
    59     RTPrintf("%s %-*s%s", name, 30 - strlen(name), command, line);
     64    RTPrintf("%s %-*s%s", name, 32 - strlen(name), command, line);
    6065}
    6166
     
    6368enum g_eUsage
    6469{
    65 #ifdef VBOX_WITH_INFO_SVC
     70#ifdef RT_OS_WINDOWS
     71    GET_VIDEO_ACCEL,
     72    SET_VIDEO_ACCEL,
     73    LIST_CUST_MODES,
     74    ADD_CUST_MODE,
     75    REMOVE_CUST_MODE,
     76    SET_VIDEO_MODE,
     77#endif
     78#ifdef VBOX_WITH_GUEST_PROPS
    6679    GET_GUEST_PROP,
    6780    SET_GUEST_PROP,
     
    7386{
    7487    RTPrintf("Usage:\n\n");
    75     RTPrintf("%s [-v|--version]    print version number and exit\n", g_pszProgName);
    76     RTPrintf("%s --nologo ...      suppress the logo\n\n", g_pszProgName);
    77 
    78 #ifdef VBOX_WITH_INFO_SVC
     88    RTPrintf("%s [-v|--version]       print version number and exit\n", g_pszProgName);
     89    RTPrintf("%s --nologo ...         suppress the logo\n\n", g_pszProgName);
     90
     91#ifdef RT_OS_WINDOWS
     92    if ((GET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich))
     93        doUsage("\n", g_pszProgName, "getvideoacceleration");
     94    if ((SET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich))
     95        doUsage("<on|off>\n", g_pszProgName, "setvideoacceleration");
     96    if ((LIST_CUST_MODES == eWhich) || (USAGE_ALL == eWhich))
     97        doUsage("\n", g_pszProgName, "listcustommodes");
     98    if ((ADD_CUST_MODE == eWhich) || (USAGE_ALL == eWhich))
     99        doUsage("<width> <height> <bpp>\n", g_pszProgName, "addcustommode");
     100    if ((REMOVE_CUST_MODE == eWhich) || (USAGE_ALL == eWhich))
     101        doUsage("<width> <height> <bpp>\n", g_pszProgName, "removecustommode");
     102    if ((SET_VIDEO_MODE == eWhich) || (USAGE_ALL == eWhich))
     103        doUsage("<width> <height> <bpp> <screen>\n", g_pszProgName, "setvideomode");
     104#endif
     105#ifdef VBOX_WITH_GUEST_PROPS
    79106    if ((GET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich))
    80         doUsage("<key>\n", g_pszProgName, "getguestproperty");
     107        doUsage("<name>\n", g_pszProgName, "getguestproperty");
    81108    if ((SET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich))
    82         doUsage("<key> [<value>] (no value deletes key)\n", g_pszProgName, "setguestproperty");
     109        doUsage("<name> [<value>] (no value deletes property)\n", g_pszProgName, "setguestproperty");
    83110#endif
    84111}
     
    101128}
    102129
    103 #ifdef VBOX_WITH_INFO_SVC
     130#ifdef RT_OS_WINDOWS
     131
     132LONG (WINAPI * gpfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam);
     133
     134static unsigned nextAdjacentRectXP (RECTL *paRects, unsigned nRects, unsigned iRect)
     135{
     136    unsigned i;
     137    for (i = 0; i < nRects; i++)
     138    {
     139        if (paRects[iRect].right == paRects[i].left)
     140        {
     141            return i;
     142        }
     143    }
     144    return ~0;
     145}
     146
     147static unsigned nextAdjacentRectXN (RECTL *paRects, unsigned nRects, unsigned iRect)
     148{
     149    unsigned i;
     150    for (i = 0; i < nRects; i++)
     151    {
     152        if (paRects[iRect].left == paRects[i].right)
     153        {
     154            return i;
     155        }
     156    }
     157    return ~0;
     158}
     159
     160static unsigned nextAdjacentRectYP (RECTL *paRects, unsigned nRects, unsigned iRect)
     161{
     162    unsigned i;
     163    for (i = 0; i < nRects; i++)
     164    {
     165        if (paRects[iRect].bottom == paRects[i].top)
     166        {
     167            return i;
     168        }
     169    }
     170    return ~0;
     171}
     172
     173unsigned nextAdjacentRectYN (RECTL *paRects, unsigned nRects, unsigned iRect)
     174{
     175    unsigned i;
     176    for (i = 0; i < nRects; i++)
     177    {
     178        if (paRects[iRect].top == paRects[i].bottom)
     179        {
     180            return i;
     181        }
     182    }
     183    return ~0;
     184}
     185
     186void resizeRect(RECTL *paRects, unsigned nRects, unsigned iPrimary, unsigned iResized, int NewWidth, int NewHeight)
     187{
     188    RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects);
     189    memcpy (paNewRects, paRects, sizeof (RECTL) * nRects);
     190    paNewRects[iResized].right += NewWidth - (paNewRects[iResized].right - paNewRects[iResized].left);
     191    paNewRects[iResized].bottom += NewHeight - (paNewRects[iResized].bottom - paNewRects[iResized].top);
     192   
     193    /* Verify all pairs of originally adjacent rectangles for all 4 directions.
     194     * If the pair has a "good" delta (that is the first rectangle intersects the second)
     195     * at a direction and the second rectangle is not primary one (which can not be moved),
     196     * move the second rectangle to make it adjacent to the first one.
     197     */
     198   
     199    /* X positive. */
     200    unsigned iRect;
     201    for (iRect = 0; iRect < nRects; iRect++)
     202    {
     203        /* Find the next adjacent original rect in x positive direction. */
     204        unsigned iNextRect = nextAdjacentRectXP (paRects, nRects, iRect);
     205        Log(("next %d -> %d\n", iRect, iNextRect));
     206       
     207        if (iNextRect == ~0 || iNextRect == iPrimary)
     208        {
     209            continue;
     210        }
     211       
     212        /* Check whether there is an X intesection between these adjacent rects in the new rectangles
     213         * and fix the intersection if delta is "good".
     214         */
     215        int delta = paNewRects[iRect].right - paNewRects[iNextRect].left;
     216       
     217        if (delta > 0)
     218        {
     219            Log(("XP intersection right %d left %d, diff %d\n",
     220                     paNewRects[iRect].right, paNewRects[iNextRect].left,
     221                     delta));
     222           
     223            paNewRects[iNextRect].left += delta;
     224            paNewRects[iNextRect].right += delta;
     225        }
     226    }
     227   
     228    /* X negative. */
     229    for (iRect = 0; iRect < nRects; iRect++)
     230    {
     231        /* Find the next adjacent original rect in x negative direction. */
     232        unsigned iNextRect = nextAdjacentRectXN (paRects, nRects, iRect);
     233        Log(("next %d -> %d\n", iRect, iNextRect));
     234       
     235        if (iNextRect == ~0 || iNextRect == iPrimary)
     236        {
     237            continue;
     238        }
     239       
     240        /* Check whether there is an X intesection between these adjacent rects in the new rectangles
     241         * and fix the intersection if delta is "good".
     242         */
     243        int delta = paNewRects[iRect].left - paNewRects[iNextRect].right;
     244       
     245        if (delta < 0)
     246        {
     247            Log(("XN intersection left %d right %d, diff %d\n",
     248                     paNewRects[iRect].left, paNewRects[iNextRect].right,
     249                     delta));
     250           
     251            paNewRects[iNextRect].left += delta;
     252            paNewRects[iNextRect].right += delta;
     253        }
     254    }
     255   
     256    /* Y positive (in the computer sence, top->down). */
     257    for (iRect = 0; iRect < nRects; iRect++)
     258    {
     259        /* Find the next adjacent original rect in y positive direction. */
     260        unsigned iNextRect = nextAdjacentRectYP (paRects, nRects, iRect);
     261        Log(("next %d -> %d\n", iRect, iNextRect));
     262       
     263        if (iNextRect == ~0 || iNextRect == iPrimary)
     264        {
     265            continue;
     266        }
     267       
     268        /* Check whether there is an Y intesection between these adjacent rects in the new rectangles
     269         * and fix the intersection if delta is "good".
     270         */
     271        int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top;
     272       
     273        if (delta > 0)
     274        {
     275            Log(("YP intersection bottom %d top %d, diff %d\n",
     276                     paNewRects[iRect].bottom, paNewRects[iNextRect].top,
     277                     delta));
     278           
     279            paNewRects[iNextRect].top += delta;
     280            paNewRects[iNextRect].bottom += delta;
     281        }
     282    }
     283   
     284    /* Y negative (in the computer sence, down->top). */
     285    for (iRect = 0; iRect < nRects; iRect++)
     286    {
     287        /* Find the next adjacent original rect in x negative direction. */
     288        unsigned iNextRect = nextAdjacentRectYN (paRects, nRects, iRect);
     289        Log(("next %d -> %d\n", iRect, iNextRect));
     290       
     291        if (iNextRect == ~0 || iNextRect == iPrimary)
     292        {
     293            continue;
     294        }
     295       
     296        /* Check whether there is an Y intesection between these adjacent rects in the new rectangles
     297         * and fix the intersection if delta is "good".
     298         */
     299        int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom;
     300       
     301        if (delta < 0)
     302        {
     303            Log(("YN intersection top %d bottom %d, diff %d\n",
     304                     paNewRects[iRect].top, paNewRects[iNextRect].bottom,
     305                     delta));
     306           
     307            paNewRects[iNextRect].top += delta;
     308            paNewRects[iNextRect].bottom += delta;
     309        }
     310    }
     311   
     312    memcpy (paRects, paNewRects, sizeof (RECTL) * nRects);
     313    return;
     314}
     315
     316/* Returns TRUE to try again. */
     317static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
     318{
     319    BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0);
     320   
     321    DISPLAY_DEVICE DisplayDevice;
     322
     323    ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
     324    DisplayDevice.cb = sizeof(DisplayDevice);
     325   
     326    /* Find out how many display devices the system has */
     327    DWORD NumDevices = 0;
     328    DWORD i = 0;
     329    while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
     330    {
     331        Log(("[%d] %s\n", i, DisplayDevice.DeviceName));
     332
     333        if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
     334        {
     335            Log(("Found primary device. err %d\n", GetLastError ()));
     336            NumDevices++;
     337        }
     338        else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
     339        {
     340           
     341            Log(("Found secondary device. err %d\n", GetLastError ()));
     342            NumDevices++;
     343        }
     344       
     345        ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
     346        DisplayDevice.cb = sizeof(DisplayDevice);
     347        i++;
     348    }
     349   
     350    Log(("Found total %d devices. err %d\n", NumDevices, GetLastError ()));
     351   
     352    if (NumDevices == 0 || Id >= NumDevices)
     353    {
     354        Log(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
     355        return FALSE;
     356    }
     357   
     358    DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
     359    DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
     360    RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
     361   
     362    /* Fetch information about current devices and modes. */
     363    DWORD DevNum = 0;
     364    DWORD DevPrimaryNum = 0;
     365   
     366    ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
     367    DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
     368   
     369    i = 0;
     370    while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
     371    {
     372        Log(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName));
     373       
     374        BOOL bFetchDevice = FALSE;
     375
     376        if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
     377        {
     378            Log(("Found primary device. err %d\n", GetLastError ()));
     379            DevPrimaryNum = DevNum;
     380            bFetchDevice = TRUE;
     381        }
     382        else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
     383        {
     384           
     385            Log(("Found secondary device. err %d\n", GetLastError ()));
     386            bFetchDevice = TRUE;
     387        }
     388       
     389        if (bFetchDevice)
     390        {
     391            if (DevNum >= NumDevices)
     392            {
     393                Log(("%d >= %d\n", NumDevices, DevNum));
     394                return FALSE;
     395            }
     396       
     397            paDisplayDevices[DevNum] = DisplayDevice;
     398           
     399            ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
     400            paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
     401            if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
     402                 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum]))
     403            {
     404                Log(("EnumDisplaySettings err %d\n", GetLastError ()));
     405                return FALSE;
     406            }
     407           
     408            Log(("%dx%d at %d,%d\n",
     409                    paDeviceModes[DevNum].dmPelsWidth,
     410                    paDeviceModes[DevNum].dmPelsHeight,
     411                    paDeviceModes[DevNum].dmPosition.x,
     412                    paDeviceModes[DevNum].dmPosition.y));
     413                   
     414            paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
     415            paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
     416            paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
     417            paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     418            DevNum++;
     419        }
     420       
     421        ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
     422        DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
     423        i++;
     424    }
     425   
     426    if (Width == 0)
     427    {
     428        Width = paRects[Id].right - paRects[Id].left;
     429    }
     430
     431    if (Height == 0)
     432    {
     433        Height = paRects[Id].bottom - paRects[Id].top;
     434    }
     435
     436    /* Check whether a mode reset or a change is requested. */
     437    if (   !fModeReset
     438        && paRects[Id].right - paRects[Id].left == Width
     439        && paRects[Id].bottom - paRects[Id].top == Height
     440        && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel)
     441    {
     442        Log(("VBoxDisplayThread : already at desired resolution.\n"));
     443        return FALSE;
     444    }
     445
     446    resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height);
     447#ifdef Log
     448    for (i = 0; i < NumDevices; i++)
     449    {
     450        Log(("[%d]: %d,%d %dx%d\n",
     451                i, paRects[i].left, paRects[i].top,
     452                paRects[i].right - paRects[i].left,
     453                paRects[i].bottom - paRects[i].top));
     454    }
     455#endif /* Log */
     456   
     457    /* Without this, Windows will not ask the miniport for its
     458     * mode table but uses an internal cache instead.
     459     */
     460    DEVMODE tempDevMode;
     461    ZeroMemory (&tempDevMode, sizeof (tempDevMode));
     462    tempDevMode.dmSize = sizeof(DEVMODE);
     463    EnumDisplaySettings(NULL, 0xffffff, &tempDevMode);
     464
     465    /* Assign the new rectangles to displays. */
     466    for (i = 0; i < NumDevices; i++)
     467    {
     468        paDeviceModes[i].dmPosition.x = paRects[i].left;
     469        paDeviceModes[i].dmPosition.y = paRects[i].top;
     470        paDeviceModes[i].dmPelsWidth  = paRects[i].right - paRects[i].left;
     471        paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
     472       
     473        paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH;
     474       
     475        if (   i == Id
     476            && BitsPerPixel != 0)
     477        {
     478            paDeviceModes[i].dmFields |= DM_BITSPERPEL;
     479            paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
     480        }
     481        Log(("calling pfnChangeDisplaySettingsEx %x\n", gpfnChangeDisplaySettingsEx));     
     482        gpfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
     483                 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
     484        Log(("ChangeDisplaySettings position err %d\n", GetLastError ()));
     485    }
     486   
     487    /* A second call to ChangeDisplaySettings updates the monitor. */
     488    LONG status = ChangeDisplaySettings(NULL, 0);
     489    Log(("ChangeDisplaySettings update status %d\n", status));
     490    if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE)
     491    {
     492        /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
     493        return FALSE;
     494    }
     495
     496    /* Retry the request. */
     497    return TRUE;
     498}
     499
     500int handleSetVideoMode(int argc, char *argv[])
     501{
     502    if (argc != 3 && argc != 4)
     503    {
     504        usage(SET_VIDEO_MODE);
     505        return 1;
     506    }
     507
     508    DWORD xres = atoi(argv[0]);
     509    DWORD yres = atoi(argv[1]);
     510    DWORD bpp  = atoi(argv[2]);
     511    DWORD scr  = 0;
     512
     513    if (argc == 4)
     514    {
     515        scr = atoi(argv[3]);
     516    }
     517
     518    HMODULE hUser = GetModuleHandle("USER32");
     519
     520    if (hUser)
     521    {
     522        *(uintptr_t *)&gpfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
     523        Log(("VBoxService: pChangeDisplaySettingsEx = %p\n", gpfnChangeDisplaySettingsEx));
     524       
     525        if (gpfnChangeDisplaySettingsEx)
     526        {
     527            /* The screen index is 0 based in the ResizeDisplayDevice call. */
     528            scr = scr > 0? scr - 1: 0;
     529           
     530            /* Horizontal resolution must be a multiple of 8, round down. */
     531            xres &= ~0x7;
     532
     533            ResizeDisplayDevice(scr, xres, yres, bpp);
     534        }
     535    }
     536    return 0;
     537}
     538
     539HKEY getVideoKey(bool writable)
     540{
     541    HKEY hkeyDeviceMap = 0;
     542    HKEY hkeyVideo = 0;
     543    LONG status;
     544
     545    status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap);
     546    if ((status != ERROR_SUCCESS) || !hkeyDeviceMap)
     547    {
     548        VBoxControlError("Error opening video device map registry key!\n");
     549        return 0;
     550    }
     551    char szVideoLocation[256];
     552    DWORD dwKeyType;
     553    szVideoLocation[0] = 0;
     554    DWORD len = sizeof(szVideoLocation);
     555    status = RegQueryValueExA(hkeyDeviceMap, "\\Device\\Video0", NULL, &dwKeyType, (LPBYTE)szVideoLocation, &len);
     556    /*
     557     * This value will start with a weird value: \REGISTRY\Machine
     558     * Make sure this is true.
     559     */
     560    if (   (status == ERROR_SUCCESS)
     561        && (dwKeyType == REG_SZ)
     562        && (_strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0))
     563    {
     564        /* open that branch */
     565        status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo);
     566    }
     567    else
     568    {
     569        VBoxControlError("Error opening registry key '%s'\n", &szVideoLocation[18]);
     570    }
     571    RegCloseKey(hkeyDeviceMap);
     572    return hkeyVideo;
     573}
     574
     575int handleGetVideoAcceleration(int argc, char *argv[])
     576{
     577    ULONG status;
     578    HKEY hkeyVideo = getVideoKey(false);
     579
     580    if (hkeyVideo)
     581    {
     582        /* query the actual value */
     583        DWORD fAcceleration = 1;
     584        DWORD len = sizeof(fAcceleration);
     585        DWORD dwKeyType;
     586        status = RegQueryValueExA(hkeyVideo, "EnableVideoAccel", NULL, &dwKeyType, (LPBYTE)&fAcceleration, &len);
     587        if (status != ERROR_SUCCESS)
     588            RTPrintf("Video acceleration: default\n");
     589        else
     590            RTPrintf("Video acceleration: %s\n", fAcceleration ? "on" : "off");
     591        RegCloseKey(hkeyVideo);
     592    }
     593    return 0;
     594}
     595
     596int handleSetVideoAcceleration(int argc, char *argv[])
     597{
     598    ULONG status;
     599    HKEY hkeyVideo;
     600
     601    /* must have exactly one argument: the new offset */
     602    if (   (argc != 1)
     603        || (   strcmp(argv[0], "on")
     604            && strcmp(argv[0], "off")))
     605    {
     606        usage(SET_VIDEO_ACCEL);
     607        return 1;
     608    }
     609
     610    hkeyVideo = getVideoKey(true);
     611
     612    if (hkeyVideo)
     613    {
     614        int fAccel = 0;
     615        if (!strcmp(argv[0], "on"))
     616            fAccel = 1;
     617        /* set a new value */
     618        status = RegSetValueExA(hkeyVideo, "EnableVideoAccel", 0, REG_DWORD, (LPBYTE)&fAccel, sizeof(fAccel));
     619        if (status != ERROR_SUCCESS)
     620        {
     621            VBoxControlError("Error %d writing video acceleration status!\n", status);
     622        }
     623        RegCloseKey(hkeyVideo);
     624    }
     625    return 0;
     626}
     627
     628#define MAX_CUSTOM_MODES 128
     629
     630/* the table of custom modes */
     631struct
     632{
     633    DWORD xres;
     634    DWORD yres;
     635    DWORD bpp;
     636} customModes[MAX_CUSTOM_MODES] = {0};
     637
     638void getCustomModes(HKEY hkeyVideo)
     639{
     640    ULONG status;
     641    int curMode = 0;
     642
     643    /* null out the table */
     644    memset(customModes, 0, sizeof(customModes));
     645
     646    do
     647    {
     648        char valueName[20];
     649        DWORD xres, yres, bpp = 0;
     650        DWORD dwType;
     651        DWORD dwLen = sizeof(DWORD);
     652
     653        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", curMode);
     654        status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&xres, &dwLen);
     655        if (status != ERROR_SUCCESS)
     656            break;
     657        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", curMode);
     658        status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&yres, &dwLen);
     659        if (status != ERROR_SUCCESS)
     660            break;
     661        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", curMode);
     662        status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&bpp, &dwLen);
     663        if (status != ERROR_SUCCESS)
     664            break;
     665
     666        /* check if the mode is OK */
     667        if (   (xres > (1 << 16))
     668            && (yres > (1 << 16))
     669            && (   (bpp != 16)
     670                || (bpp != 24)
     671                || (bpp != 32)))
     672            break;
     673
     674        /* add mode to table */
     675        customModes[curMode].xres = xres;
     676        customModes[curMode].yres = yres;
     677        customModes[curMode].bpp  = bpp;
     678
     679        ++curMode;
     680
     681        if (curMode >= MAX_CUSTOM_MODES)
     682            break;
     683    } while(1);
     684}
     685
     686void writeCustomModes(HKEY hkeyVideo)
     687{
     688    ULONG status;
     689    int tableIndex = 0;
     690    int modeIndex = 0;
     691
     692    /* first remove all values */
     693    for (int i = 0; i < MAX_CUSTOM_MODES; i++)
     694    {
     695        char valueName[20];
     696        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", i);
     697        RegDeleteValueA(hkeyVideo, valueName);
     698        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", i);
     699        RegDeleteValueA(hkeyVideo, valueName);
     700        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", i);
     701        RegDeleteValueA(hkeyVideo, valueName);
     702    }
     703
     704    do
     705    {
     706        if (tableIndex >= MAX_CUSTOM_MODES)
     707            break;
     708
     709        /* is the table entry present? */
     710        if (   (!customModes[tableIndex].xres)
     711            || (!customModes[tableIndex].yres)
     712            || (!customModes[tableIndex].bpp))
     713        {
     714            tableIndex++;
     715            continue;
     716        }
     717
     718        RTPrintf("writing mode %d (%dx%dx%d)\n", modeIndex, customModes[tableIndex].xres, customModes[tableIndex].yres, customModes[tableIndex].bpp);
     719        char valueName[20];
     720        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", modeIndex);
     721        status = RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].xres,
     722                                sizeof(customModes[tableIndex].xres));
     723        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", modeIndex);
     724        RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].yres,
     725                       sizeof(customModes[tableIndex].yres));
     726        RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", modeIndex);
     727        RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].bpp,
     728                       sizeof(customModes[tableIndex].bpp));
     729
     730        modeIndex++;
     731        tableIndex++;
     732
     733    } while(1);
     734
     735}
     736
     737int handleListCustomModes(int argc, char *argv[])
     738{
     739    if (argc != 0)
     740    {
     741        usage(LIST_CUST_MODES);
     742        return 1;
     743    }
     744
     745    HKEY hkeyVideo = getVideoKey(false);
     746
     747    if (hkeyVideo)
     748    {
     749        getCustomModes(hkeyVideo);
     750        for (int i = 0; i < (sizeof(customModes) / sizeof(customModes[0])); i++)
     751        {
     752            if (   !customModes[i].xres
     753                || !customModes[i].yres
     754                || !customModes[i].bpp)
     755                continue;
     756
     757            RTPrintf("Mode: %d x %d x %d\n",
     758                             customModes[i].xres, customModes[i].yres, customModes[i].bpp);
     759        }
     760        RegCloseKey(hkeyVideo);
     761    }
     762    return 0;
     763}
     764
     765int handleAddCustomMode(int argc, char *argv[])
     766{
     767    if (argc != 3)
     768    {
     769        usage(ADD_CUST_MODE);
     770        return 1;
     771    }
     772
     773    DWORD xres = atoi(argv[0]);
     774    DWORD yres = atoi(argv[1]);
     775    DWORD bpp  = atoi(argv[2]);
     776
     777    /** @todo better check including xres mod 8 = 0! */
     778    if (   (xres > (1 << 16))
     779        && (yres > (1 << 16))
     780        && (   (bpp != 16)
     781            || (bpp != 24)
     782            || (bpp != 32)))
     783    {
     784        VBoxControlError("Error: invalid mode specified!\n");
     785        return 1;
     786    }
     787
     788    HKEY hkeyVideo = getVideoKey(true);
     789
     790    if (hkeyVideo)
     791    {
     792        int i;
     793        int fModeExists = 0;
     794        getCustomModes(hkeyVideo);
     795        for (i = 0; i < MAX_CUSTOM_MODES; i++)
     796        {
     797            /* mode exists? */
     798            if (   customModes[i].xres == xres
     799                && customModes[i].yres == yres
     800                && customModes[i].bpp  == bpp
     801               )
     802            {
     803                fModeExists = 1;
     804            }
     805        }
     806        if (!fModeExists)
     807        {
     808            for (i = 0; i < MAX_CUSTOM_MODES; i++)
     809            {
     810                /* item free? */
     811                if (!customModes[i].xres)
     812                {
     813                    customModes[i].xres = xres;
     814                    customModes[i].yres = yres;
     815                    customModes[i].bpp  = bpp;
     816                    break;
     817                }
     818            }
     819            writeCustomModes(hkeyVideo);
     820        }
     821        RegCloseKey(hkeyVideo);
     822    }
     823    return 0;
     824}
     825
     826int handleRemoveCustomMode(int argc, char *argv[])
     827{
     828    if (argc != 3)
     829    {
     830        usage(REMOVE_CUST_MODE);
     831        return 1;
     832    }
     833
     834    DWORD xres = atoi(argv[0]);
     835    DWORD yres = atoi(argv[1]);
     836    DWORD bpp  = atoi(argv[2]);
     837
     838    HKEY hkeyVideo = getVideoKey(true);
     839
     840    if (hkeyVideo)
     841    {
     842        getCustomModes(hkeyVideo);
     843        for (int i = 0; i < MAX_CUSTOM_MODES; i++)
     844        {
     845            /* correct item? */
     846            if (   (customModes[i].xres == xres)
     847                && (customModes[i].yres == yres)
     848                && (customModes[i].bpp  == bpp))
     849            {
     850                RTPrintf("found mode at index %d\n", i);
     851                memset(&customModes[i], 0, sizeof(customModes[i]));
     852                break;
     853            }
     854        }
     855        writeCustomModes(hkeyVideo);
     856        RegCloseKey(hkeyVideo);
     857    }
     858}
     859
     860#endif /* RT_OS_WINDOWS */
     861
     862#ifdef VBOX_WITH_GUEST_PROPS
    104863/**
    105  * Retrieves a value from the host/guest configuration registry.
    106  * This is accessed through the "VBoxSharedInfoSvc" HGCM service.
     864 * Retrieves a value from the guest property store.
     865 * This is accessed through the "VBoxGuestPropSvc" HGCM service.
    107866 *
    108867 * @returns 0 on success, 1 on failure
    109  * @param   key  (string) the key which the value is stored under.
     868 * @param   name  (string) the name of the property.
    110869 */
    111870int getGuestProperty(int argc, char **argv)
    112871{
    113     using namespace svcInfo;
     872    using namespace guestProp;
     873
     874    if (argc != 1)
     875    {
     876        usage(GET_GUEST_PROP);
     877        return 1;
     878    }
    114879
    115880    uint32_t u32ClientID = 0;
    116881    int rc = VINF_SUCCESS;
    117     char *pszKey = NULL;
    118     char szValue[KEY_MAX_VALUE_LEN];
    119 
    120     if (argc != 1)
    121     {
    122         usage(GET_GUEST_PROP);
    123         return 1;
    124     }
    125     rc = RTStrCurrentCPToUtf8(&pszKey, argv[0]);
     882    char *pszName = argv[0];
     883    char *pszValue = NULL;
     884
     885    rc = VbglR3GuestPropConnect(&u32ClientID);
    126886    if (!RT_SUCCESS(rc))
    127         VBoxControlError("Failed to convert the key name to Utf8, error %Rrc\n", rc);
     887        VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc);
    128888    if (RT_SUCCESS(rc))
    129889    {
    130         rc = VbglR3InfoSvcConnect(&u32ClientID);
    131         if (!RT_SUCCESS(rc))
    132             VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc);
    133     }
    134     if (RT_SUCCESS(rc))
    135     {
    136         rc = VbglR3InfoSvcReadKey(u32ClientID, argv[0], szValue, sizeof(szValue), NULL);
     890        rc = VbglR3GuestPropReadValueAlloc(u32ClientID, pszName, &pszValue);
    137891        if (!RT_SUCCESS(rc) && (rc != VERR_NOT_FOUND))
    138892            VBoxControlError("Failed to retrieve the property value, error %Rrc\n", rc);
     
    141895        RTPrintf("No value set!\n");
    142896    if (RT_SUCCESS(rc))
    143         RTPrintf("Value: %S\n", szValue);
     897        RTPrintf("Value: %S\n", pszValue);
    144898    if (u32ClientID != 0)
    145         VbglR3InfoSvcDisconnect(u32ClientID);
    146     RTStrFree(pszKey);
     899        VbglR3GuestPropDisconnect(u32ClientID);
     900    VbglR3GuestPropReadValueFree(pszValue);
    147901    return RT_SUCCESS(rc) ? 0 : 1;
    148902}
     
    150904
    151905/**
    152  * Writes a value to the host/guest configuration registry.
    153  * This is accessed through the "VBoxSharedInfoSvc" HGCM service.
     906 * Writes a value to the guest property store.
     907 * This is accessed through the "VBoxGuestPropSvc" HGCM service.
    154908 *
    155909 * @returns 0 on success, 1 on failure
    156  * @param   key   (string) the key which the value is stored under.
    157  * @param   value (string) the value to write.  If empty, the key will be
     910 * @param   name  (string) the name of the property.
     911 * @param   value (string) the value to write.  If empty, the property will be
    158912 *                removed.
    159913 */
    160914static int setGuestProperty(int argc, char *argv[])
    161915{
     916    if (argc != 1 && argc != 2)
     917    {
     918        usage(SET_GUEST_PROP);
     919        return 1;
     920    }
     921
    162922    uint32_t u32ClientID = 0;
    163923    int rc = VINF_SUCCESS;
    164     char *pszKey = NULL;
     924    char *pszName = argv[0];
    165925    char *pszValue = NULL;
    166 
    167     if (argc != 1 && argc != 2)
    168     {
    169         usage();
    170         return 1;
    171     }
    172     rc = RTStrCurrentCPToUtf8(&pszKey, argv[0]);
     926    if (2 == argc)
     927        pszValue = argv[1];
     928
     929    rc = VbglR3GuestPropConnect(&u32ClientID);
    173930    if (!RT_SUCCESS(rc))
    174         VBoxControlError("Failed to convert the key name to Utf8, error %Rrc\n", rc);
    175     if (RT_SUCCESS(rc) && (2 == argc))
    176     {
    177         rc = RTStrCurrentCPToUtf8(&pszValue, argv[1]);
    178         if (!RT_SUCCESS(rc))
    179             VBoxControlError("Failed to convert the key value to Utf8, error %Rrc\n", rc);
    180     }
     931        VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc);
    181932    if (RT_SUCCESS(rc))
    182933    {
    183         rc = VbglR3InfoSvcConnect(&u32ClientID);
    184         if (!RT_SUCCESS(rc))
    185             VBoxControlError("Failed to connect to the host/guest registry service, error %Rrc\n", rc);
    186     }
    187     if (RT_SUCCESS(rc))
    188     {
    189         rc = VbglR3InfoSvcWriteKey(u32ClientID, argv[0], pszValue);
     934        rc = VbglR3GuestPropWriteValue(u32ClientID, pszName, pszValue);
    190935        if (!RT_SUCCESS(rc))
    191936            VBoxControlError("Failed to store the property value, error %Rrc\n", rc);
    192937    }
    193938    if (u32ClientID != 0)
    194         VbglR3InfoSvcDisconnect(u32ClientID);
    195     RTStrFree(pszKey);
    196     RTStrFree(pszValue);
     939        VbglR3GuestPropDisconnect(u32ClientID);
    197940    return RT_SUCCESS(rc) ? 0 : 1;
    198941}
     
    210953} g_commandHandlers[] =
    211954{
    212 #ifdef VBOX_WITH_INFO_SVC
     955#ifdef RT_OS_WINDOWS
     956    { "getvideoacceleration", handleGetVideoAcceleration },
     957    { "setvideoacceleration", handleSetVideoAcceleration },
     958    { "listcustommodes", handleListCustomModes },
     959    { "addcustommode", handleAddCustomMode },
     960    { "removecustommode", handleRemoveCustomMode },
     961    { "setvideomode", handleSetVideoMode },
     962#endif
     963#ifdef VBOX_WITH_GUEST_PROPS
    213964    { "getguestproperty", getGuestProperty },
    214965    { "setguestproperty", setGuestProperty },
     
    243994        if (   (0 == strcmp(argv[iArg], "-v"))
    244995            || (0 == strcmp(argv[iArg], "--version"))
     996            || (0 == strcmp(argv[iArg], "-version"))
     997            || (0 == strcmp(argv[iArg], "getversion"))
    245998           )
    246999            {
     
    3111064    if (!onlyinfo && (0 == rc))
    3121065    {
     1066        /*
     1067         * The input is in the guest OS'es codepage (NT guarantees ACP).
     1068         * For VBox we use UTF-8.  For simplicity, just convert the argv[] array
     1069         * here.
     1070         */
     1071        for (int i = iArg; i < argc; i++)
     1072        {
     1073            char *converted;
     1074            RTStrCurrentCPToUtf8(&converted, argv[i]);
     1075            argv[i] = converted;
     1076        }
     1077
    3131078        if (argc > iArg)
    3141079        {
     
    3401105            usage();
    3411106        }
     1107
     1108        /*
     1109         * Free converted argument vector
     1110         */
     1111        for (int i = iArg; i < argc; i++)
     1112            RTStrFree(argv[i]);
     1113
    3421114    }
    3431115
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette