VirtualBox

Changeset 10797 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Jul 22, 2008 8:12:42 AM (17 years ago)
Author:
vboxsync
Message:

Guest properties: initial commit of new interface

Location:
trunk/src/VBox/Additions/common
Files:
1 added
6 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/Makefile.kmk

    r10130 r10797  
    3030# Include sub-makefile.
    3131include $(PATH_SUB_CURRENT)/VBoxGuestLib/Makefile.kmk
    32 if1of ($(KBUILD_TARGET), freebsd linux os2 solaris)
    3332include $(PATH_SUB_CURRENT)/VBoxControl/Makefile.kmk
    34 endif
    3533if1of ($(KBUILD_TARGET), freebsd os2 solaris)
    3634include $(PATH_SUB_CURRENT)/VBoxGuest/Makefile.kmk
  • trunk/src/VBox/Additions/common/VBoxControl/Makefile.kmk

    r10127 r10797  
    3333PROGRAMS += VBoxControl
    3434VBoxControl_TEMPLATE = VBOXGUESTR3EXE
    35 ifdef VBOX_WITH_INFO_SVC
    36  VBoxControl_DEFS += VBOX_HGCM VBOX_WITH_INFO_SVC
     35ifeq ($(KBUILD_TARGET),win)
     36 ifdef VBOX_SIGN_ADDITIONS # (See the main Windows Additions makefile.)
     37  VBoxControl_NOINST  = true
     38 endif
    3739endif
     40VBoxControl_DEFS     += \
     41        $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS VBOX_HGCM,)
    3842VBoxControl_SOURCES = \
    3943        VBoxControl.cpp \
    4044        VBoxControlSVN.cpp
     45VBoxControl_SOURCES.win = \
     46        VBoxControl.rc
    4147VBoxControl_LIBS = \
    4248        $(VBOX_LIB_IPRT_GUEST_R3) \
  • 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
  • trunk/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk

    r10719 r10797  
    8686VBoxGuestR3Lib_DEFS        = \
    8787        VBOX_HGCM \
    88         $(if $(VBOX_WITH_INFO_SVC),VBOX_WITH_INFO_SVC,)
     88        $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,)
    8989VBoxGuestR3Lib_SOURCES     = \
    9090        VBoxGuestR3Lib.cpp \
     
    9292        VBoxGuestR3LibDaemonize.cpp \
    9393        VBoxGuestR3LibGR.cpp \
    94         $(if $(VBOX_WITH_INFO_SVC),VBoxGuestR3LibInfoSvc.cpp,) \
     94        $(if $(VBOX_WITH_GUEST_PROPS),VBoxGuestR3LibGuestProp.cpp,) \
    9595        VBoxGuestR3LibMouse.cpp \
    9696        VBoxGuestR3LibMisc.cpp \
     
    102102        VBoxGuestR3Lib.cpp \
    103103        VBoxGuestR3LibGR.cpp \
    104         $(if $(VBOX_WITH_INFO_SVC),VBoxGuestR3LibInfoSvc.cpp,) \
     104        $(if $(VBOX_WITH_GUEST_PROPS),VBoxGuestR3LibGuestProp.cpp,) \
    105105        VBoxGuestR3LibMisc.cpp 
    106106endif
     
    124124VBoxGuestR3LibXFree86_DEFS     = \
    125125        VBOX_HGCM VBOX_VBGLR3_XFREE86 \
    126         $(if $(VBOX_WITH_INFO_SVC),VBOX_WITH_INFO_SVC,)
     126        $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,)
    127127VBoxGuestR3LibXFree86_SOURCES  = \
    128128        VBoxGuestR3Lib.cpp \
    129129        VBoxGuestR3LibGR.cpp \
    130         $(if $(VBOX_WITH_INFO_SVC),VBoxGuestR3LibInfoSvc.cpp,) \
     130        $(if $(VBOX_WITH_GUEST_PROPS),VBoxGuestR3LibGuestProp.cpp,) \
    131131        VBoxGuestR3LibMouse.cpp \
    132132        VBoxGuestR3LibMisc.cpp \
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBGLR3Internal.h

    r9536 r10797  
    5656
    5757
     58DECLINLINE(void) VbglHGCMParmUInt64Set(HGCMFunctionParameter *pParm, uint64_t u64)
     59{
     60    pParm->type      = VMMDevHGCMParmType_64bit;
     61    pParm->u.value64 = u64;
     62}
     63
     64
     65DECLINLINE(int) VbglHGCMParmUInt64Get(HGCMFunctionParameter *pParm, uint64_t *pu64)
     66{
     67    if (pParm->type == VMMDevHGCMParmType_64bit)
     68    {
     69        *pu64 = pParm->u.value64;
     70        return VINF_SUCCESS;
     71    }
     72    return VERR_INVALID_PARAMETER;
     73}
     74
     75
    5876DECLINLINE(void) VbglHGCMParmPtrSet(HGCMFunctionParameter *pParm, void *pv, uint32_t cb)
    5977{
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp

    r10683 r10797  
    11/* $Id$ */
    22/** @file
    3  * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, information service.
     3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions,
     4 * guest properties.
    45 */
    56
     
    2829#include <iprt/assert.h>
    2930#include <VBox/log.h>
    30 #include <VBox/HostServices/VBoxInfoSvc.h>  /* For Save and RetrieveVideoMode */
     31#include <VBox/HostServices/GuestPropertySvc.h>
    3132
    3233#include "VBGLR3Internal.h"
    3334
    34 using namespace svcInfo;
    35 
    36 /**
    37  * Connects to the information service.
     35using namespace guestProp;
     36
     37/**
     38 * Connects to the guest property service.
    3839 *
    3940 * @returns VBox status code
     
    4142 *                          must be passed to all the other calls to the service.
    4243 */
    43 VBGLR3DECL(int) VbglR3InfoSvcConnect(uint32_t *pu32ClientId)
     44VBGLR3DECL(int) VbglR3GuestPropConnect(uint32_t *pu32ClientId)
    4445{
    4546    VBoxGuestHGCMConnectInfo Info;
     
    4748    Info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
    4849    memset(&Info.Loc.u, 0, sizeof(Info.Loc.u));
    49     strcpy(Info.Loc.u.host.achName, "VBoxSharedInfoSvc");
     50    strcpy(Info.Loc.u.host.achName, "VBoxGuestPropSvc");
    5051    Info.u32ClientID = UINT32_MAX;  /* try make valgrid shut up. */
    5152
     
    6263
    6364/**
    64  * Disconnect from the information service.
     65 * Disconnect from the guest property service.
    6566 *
    6667 * @returns VBox status code.
    6768 * @param   u32ClientId     The client id returned by VbglR3InfoSvcConnect().
    6869 */
    69 VBGLR3DECL(int) VbglR3InfoSvcDisconnect(uint32_t u32ClientId)
     70VBGLR3DECL(int) VbglR3GuestPropDisconnect(uint32_t u32ClientId)
    7071{
    7172    VBoxGuestHGCMDisconnectInfo Info;
     
    8182
    8283/**
    83  * Write a key value.
     84 * Write a property value.
    8485 *
    8586 * @returns VBox status code.
    8687 * @param   u32ClientId     The client id returned by VbglR3InvsSvcConnect().
    87  * @param   pszKey          The key to save to.  Utf8
     88 * @param   pszName         The property to save to.  Utf8
    8889 * @param   pszValue        The value to store.  Utf8.  If this is NULL then
    89  *                          the key will be removed.
    90  */
    91 VBGLR3DECL(int) VbglR3InfoSvcWriteKey(uint32_t u32ClientId, char *pszKey, char *pszValue)
     90 *                          the property will be removed.
     91 * @param   pszFlags        The flags for the property
     92 */
     93VBGLR3DECL(int) VbglR3GuestPropWrite(uint32_t u32ClientId, char *pszName, char *pszValue, char *pszFlags)
    9294{
    9395    int rc;
     
    9597    if (pszValue != NULL)
    9698    {
    97         SetConfigKey Msg;
     99        SetProperty Msg;
    98100
    99101        Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
    100102        Msg.hdr.u32ClientID = u32ClientId;
    101         Msg.hdr.u32Function = SET_CONFIG_KEY;
     103        Msg.hdr.u32Function = SET_PROP_VALUE;
    102104        Msg.hdr.cParms = 2;
    103         VbglHGCMParmPtrSet(&Msg.key, pszKey, strlen(pszKey) + 1);
     105        VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
     106        VbglHGCMParmPtrSet(&Msg.value, pszValue, strlen(pszValue) + 1);
     107        VbglHGCMParmPtrSet(&Msg.flags, pszFlags, strlen(pszFlags) + 1);
     108        rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     109        if (RT_SUCCESS(rc))
     110            rc = Msg.hdr.result;
     111    }
     112    else
     113    {
     114        DelProperty Msg;
     115
     116        Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
     117        Msg.hdr.u32ClientID = u32ClientId;
     118        Msg.hdr.u32Function = DEL_PROP;
     119        Msg.hdr.cParms = 1;
     120        VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
     121        rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     122        if (RT_SUCCESS(rc))
     123            rc = Msg.hdr.result;
     124    }
     125    return rc;
     126}
     127
     128
     129/**
     130 * Write a property value.
     131 *
     132 * @returns VBox status code.
     133 * @param   u32ClientId     The client id returned by VbglR3InvsSvcConnect().
     134 * @param   pszName         The property to save to.  Utf8
     135 * @param   pszValue        The value to store.  Utf8.  If this is NULL then
     136 *                          the property will be removed.
     137 * @note  if the property already exists and pszValue is not NULL then the
     138 *        property's flags field will be left unchanged
     139 */
     140VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, char *pszName, char *pszValue)
     141{
     142    int rc;
     143
     144    if (pszValue != NULL)
     145    {
     146        SetPropertyValue Msg;
     147
     148        Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
     149        Msg.hdr.u32ClientID = u32ClientId;
     150        Msg.hdr.u32Function = SET_PROP_VALUE;
     151        Msg.hdr.cParms = 2;
     152        VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
    104153        VbglHGCMParmPtrSet(&Msg.value, pszValue, strlen(pszValue) + 1);
    105154        rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     
    109158    else
    110159    {
    111         DelConfigKey Msg;
     160        DelProperty Msg;
    112161
    113162        Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
    114163        Msg.hdr.u32ClientID = u32ClientId;
    115         Msg.hdr.u32Function = DEL_CONFIG_KEY;
     164        Msg.hdr.u32Function = DEL_PROP;
    116165        Msg.hdr.cParms = 1;
    117         VbglHGCMParmPtrSet(&Msg.key, pszKey, strlen(pszKey) + 1);
     166        VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
    118167        rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
    119168        if (RT_SUCCESS(rc))
     
    125174
    126175/**
    127  * Retrieve a key value.
    128  *
    129  * @returns VBox status code.
    130  * @retval  VINF_SUCCESS on success, pszValue and pcbActual containing valid data.
    131  * @retval  VERR_BUFFER_OVERFLOW if the buffer is too small, pcbActual will contain
    132  *          the require buffer size. Note race condition here when retrying wrt
    133  *          someone updating it.
     176 * Retrieve a property.
     177 *
     178 * @returns VBox status code.
     179 * @retval  VINF_SUCCESS on success, pszValue, pu64Timestamp and pszFlags
     180 *          containing valid data.
     181 * @retval  VERR_BUFFER_OVERFLOW if the scratch buffer @a pcBuf is not large
     182 *          enough.  In this case the size needed will be placed in
     183 *          @a pcbBufActual if it is not NULL.
    134184 * @retval  VERR_NOT_FOUND if the key wasn't found.
    135185 *
    136186 * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
    137  * @param   pszKey          The key to read.  Utf8
    138  * @param   pszValue        Where to store the value retrieved.  Utf8.
    139  * @param   cbValue         The size of the buffer pszValue points to.
    140  * @param   pcbActual       Where to store the required buffer size if cbValue
    141  *                          is too small.  On success this contains the
    142  *                          actual size of the value retrieved.  Optional.
    143  */
    144 VBGLR3DECL(int) VbglR3InfoSvcReadKey(uint32_t u32ClientId, char *pszKey,
    145                                      char *pszValue, uint32_t cbValue, uint32_t *pcbActual)
    146 {
    147     GetConfigKey Msg;
     187 * @param   pszName         The value to read.  Utf8
     188 * @param   pcBuf           A scratch buffer to store the data retrieved into.
     189 *                          The returned data is only valid for it's lifetime.
     190 * @param   cbBuf           The size of @a pcBuf
     191 * @param   pszValue        Where to store the pointer to the value retrieved.
     192 * @param   pu64Timestamp   Where to store the timestamp.  Optional.
     193 * @param   pszFlags        Where to store the pointer to the flags.  Optional.
     194 * @param   pcbBufActual    If @a pcBuf is not large enough, the size needed.
     195 *                          Optional.
     196 */
     197VBGLR3DECL(int) VbglR3GuestPropRead(uint32_t u32ClientId, const char *pszName,
     198                                    void *pvBuf, uint32_t cbBuf,
     199                                    char **ppszValue, uint64_t *pu64Timestamp,
     200                                    char **ppszFlags,
     201                                    uint32_t *pcbBufActual)
     202{
     203    GetProperty Msg;
    148204
    149205    Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER;  /** @todo drop the cast when the result type has been fixed! */
    150206    Msg.hdr.u32ClientID = u32ClientId;
    151     Msg.hdr.u32Function = GET_CONFIG_KEY;
    152     Msg.hdr.cParms = 3;
    153     VbglHGCMParmPtrSet(&Msg.key, pszKey, strlen(pszKey) + 1);
    154     VbglHGCMParmPtrSet(&Msg.value, pszValue, cbValue);
     207    Msg.hdr.u32Function = GET_PROP;
     208    Msg.hdr.cParms = 4;
     209    VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName),
     210                       strlen(pszName) + 1);
     211    VbglHGCMParmPtrSet(&Msg.buffer, pvBuf, cbBuf);
     212    VbglHGCMParmUInt64Set(&Msg.timestamp, 0);
    155213    VbglHGCMParmUInt32Set(&Msg.size, 0);
    156214
     
    158216    if (RT_SUCCESS(rc))
    159217        rc = Msg.hdr.result;
    160     uint32_t cbActual;
    161     if (RT_SUCCESS(rc) || (VERR_BUFFER_OVERFLOW == rc))
    162     {
    163         int rc2 = VbglHGCMParmUInt32Get(&Msg.size, &cbActual);
    164         if (RT_SUCCESS(rc2))
     218    if ((VERR_BUFFER_OVERFLOW == rc) && (pcbBufActual != NULL))
     219    {
     220        int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
     221        if (!RT_SUCCESS(rc2))
     222            rc = rc2;
     223    }
     224    if (RT_SUCCESS(rc) && (pu64Timestamp != NULL))
     225        rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp);
     226    if (RT_SUCCESS(rc))
     227        *ppszValue = reinterpret_cast<char *>(pvBuf);
     228    if (RT_SUCCESS(rc) && (ppszFlags != NULL))
     229    {
     230        bool found = false;
     231        size_t i = 0;
     232        char *pcBuf = reinterpret_cast<char *>(pvBuf);
     233        for (; i < cbBuf && !found; ++i)
     234            if (0 == pcBuf[i])
     235                found = true;
     236        if (!found)
     237            /* To my mind this is an internal error, but whatever */
     238            rc = VERR_TOO_MUCH_DATA;
     239        else
     240            *ppszFlags = pcBuf + i;
     241    }
     242    return rc;
     243}
     244
     245
     246/**
     247 * Retrieve a property value, allocating space for it.
     248 *
     249 * @returns VBox status code.
     250 * @retval  VINF_SUCCESS on success, pszValue containing valid data.
     251 * @retval  VERR_NOT_FOUND if the key wasn't found.
     252 *
     253 * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
     254 * @param   pszName         The value to read.  Utf8
     255 * @param   ppszValue       Where to store the pointer to the value returned.
     256 */
     257VBGLR3DECL(int) VbglR3GuestPropReadValueAlloc(uint32_t u32ClientId,
     258                                              const char *pszName,
     259                                              char **ppszValue)
     260{
     261    int rc = VINF_SUCCESS;
     262    uint32_t cchBuf = 1024;
     263    void *pvBuf = RTMemAlloc(cchBuf);
     264    char *pszValue = NULL;
     265    if (NULL == pvBuf)
     266        rc = VERR_NO_MEMORY;
     267    if (RT_SUCCESS(rc))
     268    {
     269        rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
     270                                 &pszValue, NULL, NULL, &cchBuf);
     271        if (VERR_BUFFER_OVERFLOW == rc)
    165272        {
    166             if (pcbActual != NULL)
    167                 *pcbActual = cbActual;
     273            /** @todo how should we handle the race condition here? */
     274            pvBuf = RTMemRealloc(pvBuf, cchBuf);
     275            if (pvBuf != NULL)
     276                rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
     277                                         &pszValue, NULL, NULL, NULL);
     278            else
     279                rc = VERR_NO_MEMORY;
     280            if (VERR_BUFFER_OVERFLOW == rc)
     281                /* VERR_BUFFER_OVERFLOW has a different meaning here as a
     282                 * return code */
     283                rc = VERR_TOO_MUCH_DATA;
    168284        }
    169         else
    170             rc = rc2;
    171     }
    172     return rc;
    173 }
     285    }
     286    if (RT_SUCCESS(rc))
     287        *ppszValue = pszValue;
     288    return rc;
     289}
     290
     291/**
     292 * Free the memory used by VbglR3GuestPropReadValueAlloc for returning a
     293 * value.
     294 *
     295 * @param pszValue   the memory to be freed.  NULL pointers will be ignored.
     296 */
     297VBGLR3DECL(void) VbglR3GuestPropReadValueFree(char *pszValue)
     298{
     299    RTMemFree(pszValue);
     300}
     301
     302
     303/**
     304 * Retrieve a property value, using a user-provided buffer to store it.
     305 *
     306 * @returns VBox status code.
     307 * @retval  VINF_SUCCESS on success, pszValue containing valid data.
     308 * @retval  VERR_BUFFER_OVERFLOW and the size needed in pcchValueActual if the
     309 *          buffer provided was too small
     310 * @retval  VERR_NOT_FOUND if the key wasn't found.
     311 *
     312 * @note    There is a race here between obtaining the size of the buffer
     313 *          needed to hold the value and the value being updated.
     314 *
     315 * @param   u32ClientId     The client id returned by VbglR3ClipboardConnect().
     316 * @param   pszName         The value to read.  Utf8
     317 * @param   pszValue        Where to store the value retrieved.
     318 * @param   cchValue        The size of the buffer pointed to by @a pszValue
     319 * @param   pcchValueActual Where to store the size of the buffer needed if
     320 *                          the buffer supplied is too small.  Optional.
     321 */
     322VBGLR3DECL(int) VbglR3GuestPropReadValue(uint32_t u32ClientId, const char *pszName,
     323                                         char *pszValue, uint32_t cchValue,
     324                                         uint32_t *pcchValueActual)
     325{
     326    char *pcBuf = NULL;
     327    int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, pszName, &pcBuf);
     328    if (RT_SUCCESS(rc))
     329    {
     330        uint32_t cchValueActual = strlen(pcBuf) + 1;
     331        if (cchValueActual > cchValue)
     332        {
     333            if (pcchValueActual != NULL)
     334                *pcchValueActual = cchValueActual;
     335            rc = VERR_BUFFER_OVERFLOW;
     336        }
     337        if (RT_SUCCESS(rc))
     338            strcpy(pszValue, pcBuf);
     339    }
     340    VbglR3GuestPropReadValueFree(pcBuf);
     341    return rc;
     342}
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibVideo.cpp

    r10236 r10797  
    2828#include <iprt/assert.h>
    2929#include <VBox/log.h>
    30 #include <VBox/HostServices/VBoxInfoSvc.h>  /* For Save and RetrieveVideoMode */
     30#include <VBox/HostServices/GuestPropertySvc.h>  /* For Save and RetrieveVideoMode */
    3131
    3232#include "VBGLR3Internal.h"
    3333
     34#define VIDEO_PROP_PREFIX "/VirtualBox/GuestAdd/Vbgl/Video/"
    3435
    3536/**
     
    228229    if (RT_SUCCESS(rc) && RT_SUCCESS(req.header.rc))
    229230        fRc = req.fSupported;
    230     else
    231         LogRelFunc(("error querying video mode supported status from VMMDev."
    232                     "rc = %Vrc, VMMDev rc = %Vrc\n", rc, req.header.rc));
    233231    return fRc;
    234232}
     
    245243VBGLR3DECL(int) VbglR3SaveVideoMode(const char *pszName, uint32_t cx, uint32_t cy, uint32_t cBits)
    246244{
    247 #ifdef VBOX_WITH_INFO_SVC
    248     using namespace svcInfo;
    249 
    250     char szModeName[KEY_MAX_LEN];
    251     char szModeParms[KEY_MAX_VALUE_LEN];
     245#ifdef VBOX_WITH_GUEST_PROPS
     246    using namespace guestProp;
     247
     248    char szModeName[MAX_NAME_LEN];
     249    char szModeParms[MAX_VALUE_LEN];
    252250    uint32_t u32ClientId = 0;
    253     RTStrPrintf(szModeName, sizeof(szModeName), "VideoMode/%s", pszName);
     251    RTStrPrintf(szModeName, sizeof(szModeName), VIDEO_PROP_PREFIX"%s", pszName);
    254252    RTStrPrintf(szModeParms, sizeof(szModeParms), "%dx%dx%d", cx, cy, cBits);
    255     int rc = VbglR3InfoSvcConnect(&u32ClientId);
    256     if (RT_SUCCESS(rc))
    257         rc = VbglR3InfoSvcWriteKey(u32ClientId, szModeName, szModeParms);
     253    int rc = VbglR3GuestPropConnect(&u32ClientId);
     254    if (RT_SUCCESS(rc))
     255        rc = VbglR3GuestPropWriteValue(u32ClientId, szModeName, szModeParms);
    258256    if (u32ClientId != 0)
    259         VbglR3InfoSvcDisconnect(u32ClientId);  /* Return value ignored, because what can we do anyway? */
    260     return rc;
    261 #else /* VBOX_WITH_INFO_SVC not defined */
     257        VbglR3GuestPropDisconnect(u32ClientId);  /* Return value ignored, because what can we do anyway? */
     258    return rc;
     259#else /* VBOX_WITH_GUEST_PROPS not defined */
    262260    return VERR_NOT_IMPLEMENTED;
    263 #endif /* VBOX_WITH_INFO_SVC not defined */
    264 }
    265 
    266 
    267 /**
    268  * Retrieve video mode parameters from the registry.
     261#endif /* VBOX_WITH_GUEST_PROPS not defined */
     262}
     263
     264
     265/**
     266 * Retrieve video mode parameters from the guest property store.
    269267 *
    270268 * @returns iprt status value
     
    276274VBGLR3DECL(int) VbglR3RetrieveVideoMode(const char *pszName, uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits)
    277275{
    278 #ifdef VBOX_WITH_INFO_SVC
    279     using namespace svcInfo;
    280 
    281     char szModeParms[KEY_MAX_VALUE_LEN];
    282     char *pszNext;
     276#ifdef VBOX_WITH_GUEST_PROPS
     277    using namespace guestProp;
     278
     279/*
     280 * First we retreive the video mode which is saved as a string in the
     281 * guest property store.
     282 */
     283    /* The buffer for VbglR3GuestPropReadValue.  If this is too small then
     284     * something is wrong with the data stored in the property. */
     285    char szModeParms[1024];
    283286    uint32_t u32ClientId = 0;
    284287    uint32_t cx, cy, cBits;
    285288
    286     int rc = VbglR3InfoSvcConnect(&u32ClientId);
    287     if (RT_SUCCESS(rc))
    288     {
    289         char szModeName[KEY_MAX_LEN];
    290         RTStrPrintf(szModeName, sizeof(szModeName), "VideoMode/%s", pszName);
    291         rc = VbglR3InfoSvcReadKey(u32ClientId, szModeName, szModeParms,
    292                                   sizeof(szModeParms), NULL); /** @todo add a VbglR3InfoSvcReadKeyF/FV that does the RTStrPrintf for you. */
    293     }
     289    int rc = VbglR3GuestPropConnect(&u32ClientId);
     290    if (RT_SUCCESS(rc))
     291    {
     292        char szModeName[MAX_NAME_LEN];
     293        RTStrPrintf(szModeName, sizeof(szModeName), VIDEO_PROP_PREFIX"%s", pszName);
     294        /** @todo add a VbglR3GuestPropReadValueF/FV that does the RTStrPrintf for you. */
     295        rc = VbglR3GuestPropReadValue(u32ClientId, szModeName, szModeParms,
     296                                      sizeof(szModeParms), NULL);
     297    }
     298
     299/*
     300 * Now we convert the string returned to numeric values.
     301 */
     302    char *pszNext;
    294303    if (RT_SUCCESS(rc))
    295304        /* Extract the width from the string */
     
    299308    if (RT_SUCCESS(rc))
    300309    {
     310        /* Extract the height from the string */
    301311        ++pszNext;
    302312        rc = RTStrToUInt32Ex(pszNext, &pszNext, 10, &cy);
     
    306316    if (RT_SUCCESS(rc))
    307317    {
     318        /* Extract the bpp from the string */
    308319        ++pszNext;
    309320        rc = RTStrToUInt32Full(pszNext, 10, &cBits);
     
    311322    if (rc != VINF_SUCCESS)
    312323        rc = VERR_PARSE_ERROR;
     324
     325/*
     326 * And clean up and return the values if we successfully obtained them.
     327 */
    313328    if (u32ClientId != 0)
    314         VbglR3InfoSvcDisconnect(u32ClientId);  /* Return value ignored, because what can we do anyway? */
     329        VbglR3GuestPropDisconnect(u32ClientId);  /* Return value ignored, because what can we do anyway? */
    315330    if (RT_SUCCESS(rc))
    316331    {
     
    320335    }
    321336    return rc;
    322 #else /* VBOX_WITH_INFO_SVC not defined */
     337#else /* VBOX_WITH_GUEST_PROPS not defined */
    323338    return VERR_NOT_IMPLEMENTED;
    324 #endif /* VBOX_WITH_INFO_SVC not defined */
    325 }
     339#endif /* VBOX_WITH_GUEST_PROPS not defined */
     340}
Note: See TracChangeset for help on using the changeset viewer.

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