VirtualBox

Ignore:
Timestamp:
Nov 8, 2011 11:06:20 AM (13 years ago)
Author:
vboxsync
Message:

GuestProperties: Added code for using RTStrSpace instead of std::list as property container - it's faster.

Location:
trunk/src/VBox/HostServices/GuestProperties
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r36529 r39228  
    6464struct Property
    6565{
     66//#define USE_STRSPACE - later.
     67#ifdef USE_STRSPACE
     68    /** The string space core record. */
     69    RTSTRSPACECORE mStrCore;
     70#endif
    6671    /** The name of the property */
    6772    std::string mName;
     
    7479
    7580    /** Default constructor */
    76     Property() : mTimestamp(0), mFlags(NILFLAG) {}
     81    Property() : mTimestamp(0), mFlags(NILFLAG)
     82    {
     83#ifdef USE_STRSPACE
     84        RT_ZERO(mStrCore);
     85#endif
     86    }
    7787    /** Constructor with const char * */
    7888    Property(const char *pcszName, const char *pcszValue,
    7989             uint64_t u64Timestamp, uint32_t u32Flags)
    8090        : mName(pcszName), mValue(pcszValue), mTimestamp(u64Timestamp),
    81           mFlags(u32Flags) {}
     91          mFlags(u32Flags)
     92    {
     93#ifdef USE_STRSPACE
     94        RT_ZERO(mStrCore);
     95        mStrCore.pszString = mName.c_str();
     96#endif
     97    }
    8298    /** Constructor with std::string */
    8399    Property(std::string name, std::string value, uint64_t u64Timestamp,
     
    156172    /** Global flags for the service */
    157173    ePropFlags meGlobalFlags;
     174#ifdef USE_STRSPACE
     175    /** The property string space handle. */
     176    RTSTRSPACE mhProperties;
     177    /** The number of properties. */
     178    unsigned mcProperties;
     179#else
    158180    /** The property list */
    159181    PropertyList mProperties;
     182#endif
    160183    /** The list of property changes for guest notifications */
    161184    PropertyList mGuestNotifications;
     
    248271    }
    249272
     273    /**
     274     * Gets a property.
     275     *
     276     * @returns Pointer to the property if found, NULL if not.
     277     *
     278     * @param   pszName     The name of the property to get.
     279     */
     280    Property *getPropertyInternal(const char *pszName)
     281    {
     282#ifdef USE_STRSPACE
     283        return (Property *)RTStrSpaceGet(&mhProperties, pszName);
     284#else
     285        for (PropertyList::iterator it = mProperties.begin();
     286              it != mProperties.end();
     287              ++it)
     288            if (it->mName.compare(pszName) == 0)
     289                return &*it; /* the wonders of stdandard C++... ;-) */
     290        return NULL;
     291#endif
     292    }
     293
    250294public:
    251295    explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
    252296        : mpHelpers(pHelpers)
    253297        , meGlobalFlags(NILFLAG)
     298#ifdef USE_STRSPACE
     299        , mhProperties(NULL)
     300        , mcProperties(0)
     301#endif
    254302        , mpfnHostCallback(NULL)
    255303        , mpvHostData(NULL)
     
    442490int Service::setPropertyBlock(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    443491{
    444     char **ppNames, **ppValues, **ppFlags;
    445     uint64_t *pTimestamps;
    446     uint32_t cbDummy;
    447     int rc = VINF_SUCCESS;
     492    const char **papszNames;
     493    const char **papszValues;
     494    const char **papszFlags;
     495    uint64_t    *pau64Timestamps;
     496    uint32_t     cbDummy;
     497    int          rc = VINF_SUCCESS;
    448498
    449499    /*
    450500     * Get and validate the parameters
    451501     */
    452     if (   (cParms != 4)
    453         || RT_FAILURE(paParms[0].getPointer ((void **) &ppNames, &cbDummy))
    454         || RT_FAILURE(paParms[1].getPointer ((void **) &ppValues, &cbDummy))
    455         || RT_FAILURE(paParms[2].getPointer ((void **) &pTimestamps, &cbDummy))
    456         || RT_FAILURE(paParms[3].getPointer ((void **) &ppFlags, &cbDummy))
     502    if (   cParms != 4
     503        || RT_FAILURE(paParms[0].getPointer((void **)&papszNames, &cbDummy))
     504        || RT_FAILURE(paParms[1].getPointer((void **)&papszValues, &cbDummy))
     505        || RT_FAILURE(paParms[2].getPointer((void **)&pau64Timestamps, &cbDummy))
     506        || RT_FAILURE(paParms[3].getPointer((void **)&papszFlags, &cbDummy))
    457507        )
    458508        rc = VERR_INVALID_PARAMETER;
    459 
     509    /** @todo validate the array sizes... */
     510
     511#ifdef USE_STRSPACE
     512    for (unsigned i = 0; RT_SUCCESS(rc) && papszNames[i] != NULL; ++i)
     513    {
     514        if (   !RT_VALID_PTR(papszNames[i])
     515            || !RT_VALID_PTR(papszValues[i])
     516            || !RT_VALID_PTR(papszFlags[i])
     517            )
     518            rc = VERR_INVALID_POINTER;
     519        else
     520        {
     521            uint32_t fFlagsIgn;
     522            rc = validateFlags(papszFlags[i], &fFlagsIgn);
     523        }
     524    }
     525
     526    if (RT_SUCCESS(rc))
     527    {
     528        /*
     529         * Add the properties.  No way to roll back here.
     530         */
     531        for (unsigned i = 0; papszNames[i] != NULL; ++i)
     532        {
     533            uint32_t fFlags;
     534            rc = validateFlags(papszFlags[i], &fFlags);
     535            AssertRCBreak(rc);
     536
     537            Property *pProp = getPropertyInternal(papszNames[i]);
     538            if (pProp)
     539            {
     540                /* Update existing property. */
     541                pProp->mValue     = papszValues[i];
     542                pProp->mTimestamp = pau64Timestamps[i];
     543                pProp->mFlags     = fFlags;
     544            }
     545            else
     546            {
     547                /* Create a new property */
     548                pProp = new Property(papszNames[i], papszValues[i], pau64Timestamps[i], fFlags);
     549                if (!pProp)
     550                {
     551                    rc = VERR_NO_MEMORY;
     552                    break;
     553                }
     554                if (RTStrSpaceInsert(&mhProperties, &pProp->mStrCore))
     555                    mcProperties++;
     556                else
     557                {
     558                    delete pProp;
     559                    rc = VERR_INTERNAL_ERROR_3;
     560                    AssertFailedBreak();
     561                }
     562            }
     563        }
     564    }
     565
     566#else  /* !USE_STRSPACE */
    460567    /*
    461568     * Add the properties to the end of the list.  If we succeed then we
     
    469576    try
    470577    {
    471         for (unsigned i = 0; RT_SUCCESS(rc) && ppNames[i] != NULL; ++i)
     578        for (unsigned i = 0; RT_SUCCESS(rc) && papszNames[i] != NULL; ++i)
    472579        {
    473580            uint32_t fFlags;
    474             if (   !VALID_PTR(ppNames[i])
    475                 || !VALID_PTR(ppValues[i])
    476                 || !VALID_PTR(ppFlags[i])
     581            if (   !VALID_PTR(papszNames[i])
     582                || !VALID_PTR(papszValues[i])
     583                || !VALID_PTR(papszFlags[i])
    477584              )
    478585                rc = VERR_INVALID_POINTER;
    479586            if (RT_SUCCESS(rc))
    480                 rc = validateFlags(ppFlags[i], &fFlags);
     587                rc = validateFlags(papszFlags[i], &fFlags);
    481588            if (RT_SUCCESS(rc))
    482                 mProperties.push_back(Property(ppNames[i], ppValues[i],
    483                                                pTimestamps[i], fFlags));
     589                mProperties.push_back(Property(papszNames[i], papszValues[i],
     590                                               pau64Timestamps[i], fFlags));
    484591        }
    485592    }
     
    495602    {
    496603        ++itEnd;
    497         for (unsigned i = 0; ppNames[i] != NULL; ++i)
     604        for (unsigned i = 0; papszNames[i] != NULL; ++i)
    498605            for (PropertyList::iterator it = mProperties.begin(); it != itEnd; ++it)
    499                 if (it->mName.compare(ppNames[i]) == 0)
     606                if (it->mName.compare(papszNames[i]) == 0)
    500607                {
    501608                    mProperties.erase(it);
     
    514621        mProperties.erase(itEnd, mProperties.end());
    515622    }
     623#endif /* !USE_STRSPACE */
    516624    return rc;
    517625}
     
    534642    const char *pcszName = NULL;        /* shut up gcc */
    535643    char *pchBuf;
    536     uint32_t cchName, cchBuf;
     644    uint32_t cbName, cchBuf;
    537645    char szFlags[MAX_FLAGS_LEN];
    538646
     
    542650    LogFlowThisFunc(("\n"));
    543651    if (   cParms != 4  /* Hardcoded value as the next lines depend on it. */
    544         || RT_FAILURE (paParms[0].getString(&pcszName, &cchName))  /* name */
    545         || RT_FAILURE (paParms[1].getBuffer((void **) &pchBuf, &cchBuf))  /* buffer */
     652        || RT_FAILURE(paParms[0].getString(&pcszName, &cbName))  /* name */
     653        || RT_FAILURE(paParms[1].getBuffer((void **)&pchBuf, &cchBuf))  /* buffer */
    546654       )
    547655        rc = VERR_INVALID_PARAMETER;
    548656    else
    549         rc = validateName(pcszName, cchName);
     657        rc = validateName(pcszName, cbName);
    550658
    551659    /*
     
    553661     */
    554662
     663#ifdef USE_STRSPACE
     664    /* Get the property. */
     665    Property *it = NULL;
     666    if (RT_SUCCESS(rc))
     667    {
     668        it = getPropertyInternal(pcszName);
     669        if (!it)
     670            rc = VERR_NOT_FOUND;
     671    }
     672
     673#else  /* !USE_STRSPACE */
    555674    /* Get the value size */
    556675    PropertyList::const_iterator it;
     
    565684            }
    566685    }
     686#endif /* !USE_STRSPACE */
    567687    if (RT_SUCCESS(rc))
    568688        rc = writeFlags(it->mFlags, szFlags);
     
    618738
    619739    LogFlowThisFunc(("\n"));
     740
     741#ifndef USE_STRSPACE /** @todo r=bird: This check is wrong as it will prevent updating
     742                      *        existing properties when the maximum is reached! */
    620743    /*
    621744     * First of all, make sure that we won't exceed the maximum number of properties.
     
    623746    if (mProperties.size() >= MAX_PROPS)
    624747        rc = VERR_TOO_MUCH_DATA;
     748#endif
    625749
    626750    /*
     
    656780         * to change it.
    657781         */
     782#ifdef USE_STRSPACE
     783        Property *it = getPropertyInternal(pcszName);
     784        bool found = it != NULL;
     785#else
    658786        PropertyList::iterator it;
    659787        bool found = false;
     
    664792                break;
    665793            }
     794#endif /* !USE_STRSPACE */
    666795
    667796        rc = checkPermission(found ? (ePropFlags)it->mFlags : NILFLAG,
     
    678807                it->mFlags = fFlags;
    679808            }
     809#ifdef USE_STRSPACE
     810            else if (mcProperties < MAX_PROPS)
     811            {
     812                /* Create a new string space record. */
     813                it = new Property(pcszName, pcszValue, u64TimeNano, fFlags);
     814                if (it)
     815                {
     816                    if (RTStrSpaceInsert(&mhProperties, &it->mStrCore))
     817                        mcProperties++;
     818                    else
     819                    {
     820                        AssertFailed();
     821                        delete it;
     822                        rc = VERR_INTERNAL_ERROR_3;
     823                    }
     824                }
     825                else
     826                    rc = VERR_NO_MEMORY;
     827            }
     828            else
     829                rc = VERR_TOO_MUCH_DATA;
     830#else
    680831            else  /* This can throw.  No problem as we have nothing to roll back. */
    681832                mProperties.push_back(Property(pcszName, pcszValue, u64TimeNano, fFlags));
     833#endif
    682834
    683835            /*
     
    729881         * to change it.
    730882         */
     883#ifdef USE_STRSPACE
     884        Property *it = getPropertyInternal(pcszName);
     885        bool found = it != NULL;
     886        if (it)
     887            rc = checkPermission((ePropFlags)it->mFlags, isGuest);
     888#else
    731889        PropertyList::iterator it;
    732890        bool found = false;
     
    738896                break;
    739897            }
     898#endif
    740899
    741900        /*
     
    745904        {
    746905            uint64_t u64Timestamp = getCurrentTimestamp();
     906#ifdef USE_STRSPACE
     907            bool fRc = RTStrSpaceRemove(&mhProperties, it->mStrCore.pszString);
     908            Assert(fRc); NOREF(fRc);
     909            mcProperties--;
     910            delete it;
     911#else
    747912            mProperties.erase(it);
     913#endif
    748914            // if (isGuest)  /* Notify the host even for properties that the host
    749915            //                * changed.  Less efficient, but ensures consistency. */
     
    755921    return rc;
    756922}
     923
     924#ifdef USE_STRSPACE
     925
     926/**
     927 * Enumeration data shared between enumPropsCallback and Service::enumProps.
     928 */
     929typedef struct EnumData
     930{
     931    const char *pszPattern; /**< The pattern to match properties against. */
     932    char       *pchCur;     /**< The current buffer postion. */
     933    size_t      cbLeft;     /**< The amount of available buffer space. */
     934    size_t      cbNeeded;   /**< The amount of needed buffer space. */
     935} EnumData;
     936
     937/**
     938 * @callback_method_impl{FNRTSTRSPACECALLBACK}
     939 */
     940static DECLCALLBACK(int) enumPropsCallback(PRTSTRSPACECORE pStr, void *pvUser)
     941{
     942    Property *pProp = (Property *)pStr;
     943    EnumData *pEnum = (EnumData *)pvUser;
     944
     945    /* Included in the enumeration? */
     946    if (!pProp->Matches(pEnum->pszPattern))
     947        return 0;
     948
     949    /* Convert the non-string members into strings. */
     950    char            szTimestamp[256];
     951    size_t const    cbTimestamp = RTStrFormatNumber(szTimestamp, pProp->mTimestamp, 10, 0, 0, 0) + 1;
     952
     953    char            szFlags[MAX_FLAGS_LEN];
     954    int rc = writeFlags(pProp->mFlags, szFlags);
     955    if (RT_FAILURE(rc))
     956        return rc;
     957    size_t const    cbFlags = strlen(szFlags) + 1;
     958
     959    /* Calculate the buffer space requirements. */
     960    size_t const    cbName     = pProp->mName.length() + 1;
     961    size_t const    cbValue    = pProp->mValue.length() + 1;
     962    size_t const    cbRequired = cbName + cbValue + cbTimestamp + cbFlags;
     963    pEnum->cbNeeded += cbRequired;
     964
     965    /* Sufficient buffer space? */
     966    if (cbRequired > pEnum->cbLeft)
     967    {
     968        pEnum->cbLeft = 0;
     969        return 0; /* don't quit */
     970    }
     971    pEnum->cbLeft -= cbRequired;
     972
     973    /* Append the property to the buffer. */
     974    char *pchCur = pEnum->pchCur;
     975    pEnum->pchCur += cbRequired;
     976
     977    memcpy(pchCur, pProp->mName.c_str(), cbName);
     978    pchCur += cbName;
     979
     980    memcpy(pchCur, pProp->mValue.c_str(), cbValue);
     981    pchCur += cbValue;
     982
     983    memcpy(pchCur, szTimestamp, cbTimestamp);
     984    pchCur += cbTimestamp;
     985
     986    memcpy(pchCur, szFlags, cbFlags);
     987    pchCur += cbFlags;
     988
     989    Assert(pchCur == pEnum->pchCur);
     990    return 0;
     991}
     992#endif /* USE_STRSPACE */
    757993
    758994/**
     
    7721008     * Get the HGCM function arguments.
    7731009     */
    774     char *pcchPatterns = NULL, *pchBuf = NULL;
    775     uint32_t cchPatterns = 0, cchBuf = 0;
     1010    char const *pchPatterns = NULL;
     1011    char *pchBuf = NULL;
     1012    uint32_t cbPatterns = 0;
     1013    uint32_t cchBuf = 0;
    7761014    LogFlowThisFunc(("\n"));
    7771015    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
    778         || RT_FAILURE(paParms[0].getString(&pcchPatterns, &cchPatterns))  /* patterns */
     1016        || RT_FAILURE(paParms[0].getString(&pchPatterns, &cbPatterns))  /* patterns */
    7791017        || RT_FAILURE(paParms[1].getBuffer((void **) &pchBuf, &cchBuf))  /* return buffer */
    7801018       )
    7811019        rc = VERR_INVALID_PARAMETER;
    782     if (RT_SUCCESS(rc) && cchPatterns > MAX_PATTERN_LEN)
     1020    if (RT_SUCCESS(rc) && cbPatterns > MAX_PATTERN_LEN)
    7831021        rc = VERR_TOO_MUCH_DATA;
    7841022
     
    7891027    if (RT_SUCCESS(rc))
    7901028    {
    791         for (unsigned i = 0; i < cchPatterns - 1; ++i)
    792             if (pcchPatterns[i] != '\0')
    793                 pszPatterns[i] = pcchPatterns[i];
     1029        for (unsigned i = 0; i < cbPatterns - 1; ++i)
     1030            if (pchPatterns[i] != '\0')
     1031                pszPatterns[i] = pchPatterns[i];
    7941032            else
    7951033                pszPatterns[i] = '|';
    796         pszPatterns[cchPatterns - 1] = '\0';
    797     }
    798 
     1034        pszPatterns[cbPatterns - 1] = '\0';
     1035    }
     1036
     1037#ifdef USE_STRSPACE
     1038    /*
     1039     * Next enumerate into the buffer.
     1040     */
     1041    if (RT_SUCCESS(rc))
     1042    {
     1043        EnumData EnumData;
     1044        EnumData.pszPattern = pszPatterns;
     1045        EnumData.pchCur     = pchBuf;
     1046        EnumData.cbLeft     = cchBuf;
     1047        EnumData.cbNeeded   = 0;
     1048        rc = RTStrSpaceEnumerate(&mhProperties, enumPropsCallback, &EnumData);
     1049        AssertRCSuccess(rc);
     1050        if (RT_SUCCESS(rc))
     1051        {
     1052            paParms[2].setUInt32((uint32_t)(EnumData.cbNeeded + 4));
     1053            if (EnumData.cbLeft >= 4)
     1054            {
     1055                /* The final terminators. */
     1056                EnumData.pchCur[0] = '\0';
     1057                EnumData.pchCur[1] = '\0';
     1058                EnumData.pchCur[2] = '\0';
     1059                EnumData.pchCur[3] = '\0';
     1060            }
     1061            else
     1062                rc = VERR_BUFFER_OVERFLOW;
     1063        }
     1064    }
     1065
     1066#else  /* !USE_STRSPACE */
    7991067    /*
    8001068     * Next enumerate into a temporary buffer.  This can throw, but this is
     
    8331101    if (RT_SUCCESS(rc))
    8341102    {
    835         paParms[2].setUInt32 ((uint32_t)buffer.size());
     1103        paParms[2].setUInt32((uint32_t)buffer.size());
    8361104        /* Copy the memory if it fits into the guest buffer */
    8371105        if (buffer.size() <= cchBuf)
     
    8401108            rc = VERR_BUFFER_OVERFLOW;
    8411109    }
     1110#endif /* !USE_STRSPACE */
    8421111    return rc;
    8431112}
     
    10001269    /* prop is currently a delete event for pszProperty */
    10011270    bool found = false;
     1271#ifdef USE_STRSPACE
     1272    if (RT_SUCCESS(rc))
     1273    {
     1274        Property *pProp = getPropertyInternal(pszProperty);
     1275        if (pProp)
     1276        {
     1277            found = true;
     1278            /* Make prop into a change event. */
     1279            prop.mValue = pProp->mValue;
     1280            prop.mFlags = pProp->mFlags;
     1281        }
     1282    }
     1283#else  /* !USE_STRSPACE */
    10021284    if (RT_SUCCESS(rc))
    10031285        for (PropertyList::const_iterator it = mProperties.begin();
     
    10101292                prop.mFlags = it->mFlags;
    10111293            }
    1012 
     1294#endif /* !USE_STRSPACE */
    10131295
    10141296    /* Release waiters if applicable and add the event to the queue for
     
    11151397{
    11161398    int rc = VINF_SUCCESS;
    1117     LogFlowFunc(("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
     1399    LogFlowFunc(("u32ClientID = %d, fn = %d, cParms = %d, pparms = %p\n",
    11181400                 u32ClientID, eFunction, cParms, paParms));
    11191401
     
    11831465    int rc = VINF_SUCCESS;
    11841466
    1185     LogFlowFunc(("fn = %d, cParms = %d, pparms = %d\n",
     1467    LogFlowFunc(("fn = %d, cParms = %d, pparms = %p\n",
    11861468                 eFunction, cParms, paParms));
    11871469
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r36412 r39228  
    2121*******************************************************************************/
    2222#include <VBox/HostServices/GuestPropertySvc.h>
    23 #include <iprt/initterm.h>
    24 #include <iprt/stream.h>
    2523#include <iprt/test.h>
     24#include <iprt/time.h>
     25
    2626
    2727/*******************************************************************************
     
    5454void initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
    5555{
    56     pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);
    57     pTable->u32Version = VBOX_HGCM_SVC_VERSION;
    58     pHelpers->pfnCallComplete = callComplete;
    59     pTable->pHelpers = pHelpers;
     56    pTable->cbSize              = sizeof (VBOXHGCMSVCFNTABLE);
     57    pTable->u32Version          = VBOX_HGCM_SVC_VERSION;
     58    pHelpers->pfnCallComplete   = callComplete;
     59    pTable->pHelpers            = pHelpers;
    6060}
    6161
     
    7272    const char *pcszOut;
    7373}
    74 g_validFlagStrings[] =
     74g_aValidFlagStrings[] =
    7575{
    7676    /* pcszIn,                                          pcszOut */
     
    9191 * functions should reject these.
    9292 */
    93 const char *g_invalidFlagStrings[] =
     93const char *g_apszInvalidFlagStrings[] =
    9494{
    9595    "RDONLYHOST,,",
     
    102102 * @note    prints its own diagnostic information to stdout.
    103103 */
    104 int testConvertFlags()
     104static void testConvertFlags(void)
    105105{
    106106    int rc = VINF_SUCCESS;
    107107    char *pszFlagBuffer = (char *)RTTestGuardedAllocTail(g_hTest, MAX_FLAGS_LEN);
    108108
    109     RTPrintf("tstGuestPropSvc: Testing conversion of valid flags strings.\n");
    110     for (unsigned i = 0; i < RT_ELEMENTS(g_validFlagStrings) && RT_SUCCESS(rc); ++i)
     109    RTTestISub("Conversion of valid flags strings");
     110    for (unsigned i = 0; i < RT_ELEMENTS(g_aValidFlagStrings) && RT_SUCCESS(rc); ++i)
    111111    {
    112112        uint32_t fFlags;
    113         rc = validateFlags(g_validFlagStrings[i].pcszIn, &fFlags);
     113        rc = validateFlags(g_aValidFlagStrings[i].pcszIn, &fFlags);
    114114        if (RT_FAILURE(rc))
    115             RTPrintf("tstGuestPropSvc: FAILURE - Failed to validate flag string '%s'.\n", g_validFlagStrings[i].pcszIn);
     115            RTTestIFailed("Failed to validate flag string '%s'", g_aValidFlagStrings[i].pcszIn);
    116116        if (RT_SUCCESS(rc))
    117117        {
    118118            rc = writeFlags(fFlags, pszFlagBuffer);
    119119            if (RT_FAILURE(rc))
    120                 RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string '%s' back to a string.\n",
    121                          g_validFlagStrings[i].pcszIn);
     120                RTTestIFailed("Failed to convert flag string '%s' back to a string.",
     121                              g_aValidFlagStrings[i].pcszIn);
    122122        }
    123123        if (RT_SUCCESS(rc) && (strlen(pszFlagBuffer) > MAX_FLAGS_LEN - 1))
    124124        {
    125             RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to a flag string which is too long.\n",
    126                      g_validFlagStrings[i].pcszIn);
     125            RTTestIFailed("String '%s' converts back to a flag string which is too long.\n",
     126                          g_aValidFlagStrings[i].pcszIn);
    127127            rc = VERR_TOO_MUCH_DATA;
    128128        }
    129         if (RT_SUCCESS(rc) && (strcmp(pszFlagBuffer, g_validFlagStrings[i].pcszOut) != 0))
    130         {
    131             RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to '%s' instead of to '%s'\n",
    132                      g_validFlagStrings[i].pcszIn, pszFlagBuffer,
    133                      g_validFlagStrings[i].pcszOut);
     129        if (RT_SUCCESS(rc) && (strcmp(pszFlagBuffer, g_aValidFlagStrings[i].pcszOut) != 0))
     130        {
     131            RTTestIFailed("String '%s' converts back to '%s' instead of to '%s'\n",
     132                          g_aValidFlagStrings[i].pcszIn, pszFlagBuffer,
     133                          g_aValidFlagStrings[i].pcszOut);
    134134            rc = VERR_PARSE_ERROR;
    135135        }
     
    137137    if (RT_SUCCESS(rc))
    138138    {
    139         RTPrintf("Testing rejection of invalid flags strings.\n");
    140         for (unsigned i = 0; i < RT_ELEMENTS(g_invalidFlagStrings) && RT_SUCCESS(rc); ++i)
     139        RTTestISub("Rejection of invalid flags strings");
     140        for (unsigned i = 0; i < RT_ELEMENTS(g_apszInvalidFlagStrings) && RT_SUCCESS(rc); ++i)
    141141        {
    142142            uint32_t fFlags;
    143143            /* This is required to fail. */
    144             if (RT_SUCCESS(validateFlags(g_invalidFlagStrings[i], &fFlags)))
     144            if (RT_SUCCESS(validateFlags(g_apszInvalidFlagStrings[i], &fFlags)))
    145145            {
    146                 RTPrintf("String '%s' was incorrectly accepted as a valid flag string.\n",
    147                          g_invalidFlagStrings[i]);
     146                RTTestIFailed("String '%s' was incorrectly accepted as a valid flag string.\n",
     147                              g_apszInvalidFlagStrings[i]);
    148148                rc = VERR_PARSE_ERROR;
    149149            }
     
    153153    {
    154154        uint32_t u32BadFlags = ALLFLAGS << 1;
    155         RTPrintf("Testing rejection of an invalid flags field.\n");
     155        RTTestISub("Rejection of an invalid flags field");
    156156        /* This is required to fail. */
    157157        if (RT_SUCCESS(writeFlags(u32BadFlags, pszFlagBuffer)))
    158158        {
    159             RTPrintf("Flags 0x%x were incorrectly written out as '%.*s'\n",
    160                      u32BadFlags, MAX_FLAGS_LEN, pszFlagBuffer);
     159            RTTestIFailed("Flags 0x%x were incorrectly written out as '%.*s'\n",
     160                          u32BadFlags, MAX_FLAGS_LEN, pszFlagBuffer);
    161161            rc = VERR_PARSE_ERROR;
    162162        }
     
    164164
    165165    RTTestGuardedFree(g_hTest, pszFlagBuffer);
    166     return rc;
    167166}
    168167
     
    170169 * List of property names for testSetPropsHost.
    171170 */
    172 const char *apcszNameBlock[] =
     171const char *g_apcszNameBlock[] =
    173172{
    174173    "test/name/",
     
    182181 * List of property values for testSetPropsHost.
    183182 */
    184 const char *apcszValueBlock[] =
     183const char *g_apcszValueBlock[] =
    185184{
    186185    "test/value/",
     
    194193 * List of property timestamps for testSetPropsHost.
    195194 */
    196 uint64_t au64TimestampBlock[] =
     195uint64_t g_au64TimestampBlock[] =
    197196{
    198197    0, 999, 999999, UINT64_C(999999999999), 0
     
    202201 * List of property flags for testSetPropsHost.
    203202 */
    204 const char *apcszFlagsBlock[] =
     203const char *g_apcszFlagsBlock[] =
    205204{
    206205    "",
     
    216215 * @note    prints its own diagnostic information to stdout.
    217216 */
    218 int testSetPropsHost(VBOXHGCMSVCFNTABLE *ptable)
    219 {
    220     int rc = VINF_SUCCESS;
    221     RTPrintf("Testing the SET_PROPS_HOST call.\n");
    222     if (!VALID_PTR(ptable->pfnHostCall))
    223     {
    224         RTPrintf("Invalid pfnHostCall() pointer\n");
    225         rc = VERR_INVALID_POINTER;
    226     }
    227     if (RT_SUCCESS(rc))
    228     {
    229         VBOXHGCMSVCPARM paParms[4];
    230         paParms[0].setPointer ((void *) apcszNameBlock, 0);
    231         paParms[1].setPointer ((void *) apcszValueBlock, 0);
    232         paParms[2].setPointer ((void *) au64TimestampBlock, 0);
    233         paParms[3].setPointer ((void *) apcszFlagsBlock, 0);
    234         rc = ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4,
    235                                  paParms);
    236         if (RT_FAILURE(rc))
    237             RTPrintf("SET_PROPS_HOST call failed with rc=%Rrc\n", rc);
    238     }
    239     return rc;
     217static void testSetPropsHost(VBOXHGCMSVCFNTABLE *ptable)
     218{
     219    RTTestISub("SET_PROPS_HOST");
     220    RTTESTI_CHECK_RETV(RT_VALID_PTR(ptable->pfnHostCall));
     221
     222    VBOXHGCMSVCPARM aParms[4];
     223    aParms[0].setPointer((void *)g_apcszNameBlock, 0);
     224    aParms[1].setPointer((void *)g_apcszValueBlock, 0);
     225    aParms[2].setPointer((void *)g_au64TimestampBlock, 0);
     226    aParms[3].setPointer((void *)g_apcszFlagsBlock, 0);
     227    RTTESTI_CHECK_RC(ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4, &aParms[0]), VINF_SUCCESS);
    240228}
    241229
    242230/** Result strings for zeroth enumeration test */
    243 static const char *pcchEnumResult0[] =
     231static const char *g_apchEnumResult0[] =
    244232{
    245233    "test/name/\0test/value/\0""0\0",
     
    251239
    252240/** Result string sizes for zeroth enumeration test */
    253 static const uint32_t cchEnumResult0[] =
     241static const uint32_t g_acbEnumResult0[] =
    254242{
    255243    sizeof("test/name/\0test/value/\0""0\0"),
     
    264252 * the - 1 at the end is because of the hidden zero terminator
    265253 */
    266 static const uint32_t cchEnumBuffer0 =
    267 sizeof("test/name/\0test/value/\0""0\0\0"
    268 "test name\0test value\0""999\0TRANSIENT, READONLY\0"
    269 "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
    270 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
     254static const uint32_t g_cbEnumBuffer0 =
     255    sizeof("test/name/\0test/value/\0""0\0\0"
     256           "test name\0test value\0""999\0TRANSIENT, READONLY\0"
     257           "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
     258           "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
    271259
    272260/** Result strings for first and second enumeration test */
    273 static const char *pcchEnumResult1[] =
     261static const char *g_apchEnumResult1[] =
    274262{
    275263    "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST",
     
    279267
    280268/** Result string sizes for first and second enumeration test */
    281 static const uint32_t cchEnumResult1[] =
     269static const uint32_t g_acbEnumResult1[] =
    282270{
    283271    sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST"),
     
    290278 * the - 1 at the end is because of the hidden zero terminator
    291279 */
    292 static const uint32_t cchEnumBuffer1 =
    293 sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
    294 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
     280static const uint32_t g_cbEnumBuffer1 =
     281    sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
     282           "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
    295283
    296284static const struct enumStringStruct
    297285{
    298286    /** The enumeration pattern to test */
    299     const char *pcszPatterns;
     287    const char     *pszPatterns;
    300288    /** The size of the pattern string */
    301     const uint32_t cchPatterns;
     289    const uint32_t  cchPatterns;
    302290    /** The expected enumeration output strings */
    303     const char **ppcchResult;
     291    const char    **papchResult;
    304292    /** The size of the output strings */
    305     const uint32_t *pcchResult;
     293    const uint32_t *pacchResult;
    306294    /** The size of the buffer needed for the enumeration */
    307     const uint32_t cchBuffer;
    308 }
    309 enumStrings[] =
     295    const uint32_t  cbBuffer;
     296}   g_aEnumStrings[] =
    310297{
    311298    {
    312299        "", sizeof(""),
    313         pcchEnumResult0,
    314         cchEnumResult0,
    315         cchEnumBuffer0
     300        g_apchEnumResult0,
     301        g_acbEnumResult0,
     302        g_cbEnumBuffer0
    316303    },
    317304    {
    318305        "/*\0?E*", sizeof("/*\0?E*"),
    319         pcchEnumResult1,
    320         cchEnumResult1,
    321         cchEnumBuffer1
     306        g_apchEnumResult1,
     307        g_acbEnumResult1,
     308        g_cbEnumBuffer1
    322309    },
    323310    {
    324311        "/*|?E*", sizeof("/*|?E*"),
    325         pcchEnumResult1,
    326         cchEnumResult1,
    327         cchEnumBuffer1
     312        g_apchEnumResult1,
     313        g_acbEnumResult1,
     314        g_cbEnumBuffer1
    328315    }
    329316};
     
    334321 * @note    prints its own diagnostic information to stdout.
    335322 */
    336 int testEnumPropsHost(VBOXHGCMSVCFNTABLE *ptable)
    337 {
    338     int rc = VINF_SUCCESS;
    339     RTPrintf("Testing the ENUM_PROPS_HOST call.\n");
    340     if (!VALID_PTR(ptable->pfnHostCall))
    341     {
    342         RTPrintf("Invalid pfnHostCall() pointer\n");
    343         rc = VERR_INVALID_POINTER;
    344     }
    345     for (unsigned i = 0; RT_SUCCESS(rc) && i < RT_ELEMENTS(enumStrings);
    346          ++i)
    347     {
    348         char buffer[2048];
    349         VBOXHGCMSVCPARM paParms[3];
    350         paParms[0].setPointer ((void *) enumStrings[i].pcszPatterns,
    351                                enumStrings[i].cchPatterns);
    352         paParms[1].setPointer ((void *) buffer,
    353                                enumStrings[i].cchBuffer - 1);
    354         AssertBreakStmt(sizeof(buffer) > enumStrings[i].cchBuffer,
    355                         rc = VERR_INTERNAL_ERROR);
    356         if (RT_SUCCESS(rc))
    357         {
    358             /* This should fail as the buffer is too small. */
    359             int rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST,
    360                                           3, paParms);
    361             if (rc2 != VERR_BUFFER_OVERFLOW)
     323static void testEnumPropsHost(VBOXHGCMSVCFNTABLE *ptable)
     324{
     325    RTTestISub("ENUM_PROPS_HOST");
     326    RTTESTI_CHECK_RETV(RT_VALID_PTR(ptable->pfnHostCall));
     327
     328    for (unsigned i = 0; i < RT_ELEMENTS(g_aEnumStrings); ++i)
     329    {
     330        VBOXHGCMSVCPARM aParms[3];
     331        char            abBuffer[2048];
     332        RTTESTI_CHECK_RETV(g_aEnumStrings[i].cbBuffer < sizeof(abBuffer));
     333
     334        /* Check that we get buffer overflow with a too small buffer. */
     335        aParms[0].setPointer((void *)g_aEnumStrings[i].pszPatterns, g_aEnumStrings[i].cchPatterns);
     336        aParms[1].setPointer((void *)abBuffer, g_aEnumStrings[i].cbBuffer - 1);
     337        int rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 3, aParms);
     338        if (rc2 == VERR_BUFFER_OVERFLOW)
     339        {
     340            uint32_t cbNeeded;
     341            RTTESTI_CHECK_RC(rc2 = aParms[2].getUInt32(&cbNeeded), VINF_SUCCESS);
     342            if (RT_SUCCESS(rc2))
     343                RTTESTI_CHECK_MSG(cbNeeded == g_aEnumStrings[i].cbBuffer,
     344                                  ("expected %u, got %u, pattern %d\n", g_aEnumStrings[i].cbBuffer, cbNeeded, i));
     345        }
     346        else
     347            RTTestIFailed("ENUM_PROPS_HOST returned %Rrc instead of VERR_BUFFER_OVERFLOW on too small buffer, pattern number %d.", rc2, i);
     348
     349        /* Make a successfull call. */
     350        aParms[0].setPointer((void *)g_aEnumStrings[i].pszPatterns, g_aEnumStrings[i].cchPatterns);
     351        aParms[1].setPointer((void *)abBuffer, g_aEnumStrings[i].cbBuffer);
     352        rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 3, aParms);
     353        if (rc2 == VINF_SUCCESS)
     354        {
     355            /* Look for each of the result strings in the buffer which was returned */
     356            for (unsigned j = 0; g_aEnumStrings[i].papchResult[j] != NULL; ++j)
    362357            {
    363                 RTPrintf("ENUM_PROPS_HOST returned %Rrc instead of VERR_BUFFER_OVERFLOW on too small buffer, pattern number %d\n", rc2, i);
    364                 rc = VERR_BUFFER_OVERFLOW;
     358                bool found = false;
     359                for (unsigned k = 0; !found && k <   g_aEnumStrings[i].cbBuffer
     360                                                   - g_aEnumStrings[i].pacchResult[j];
     361                     ++k)
     362                    if (memcmp(abBuffer + k, g_aEnumStrings[i].papchResult[j],
     363                        g_aEnumStrings[i].pacchResult[j]) == 0)
     364                        found = true;
     365                if (!found)
     366                    RTTestIFailed("ENUM_PROPS_HOST did not produce the expected output for pattern %d.", i);
    365367            }
    366             else
    367             {
    368                 uint32_t cchBufferActual;
    369                 rc = paParms[2].getUInt32 (&cchBufferActual);
    370                 if (RT_SUCCESS(rc) && cchBufferActual != enumStrings[i].cchBuffer)
    371                 {
    372                     RTPrintf("ENUM_PROPS_HOST requested a buffer size of %lu instead of %lu for pattern number %d\n", cchBufferActual, enumStrings[i].cchBuffer, i);
    373                     rc = VERR_OUT_OF_RANGE;
    374                 }
    375                 else if (RT_FAILURE(rc))
    376                     RTPrintf("ENUM_PROPS_HOST did not return the required buffer size properly for pattern %d\n", i);
    377             }
    378         }
    379         if (RT_SUCCESS(rc))
    380         {
    381             paParms[1].setPointer ((void *) buffer, enumStrings[i].cchBuffer);
    382             rc = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST,
    383                                       3, paParms);
    384             if (RT_FAILURE(rc))
    385                 RTPrintf("ENUM_PROPS_HOST call failed for pattern %d with rc=%Rrc\n", i, rc);
    386             else
    387                 /* Look for each of the result strings in the buffer which was returned */
    388                 for (unsigned j = 0; RT_SUCCESS(rc) && enumStrings[i].ppcchResult[j] != NULL;
    389                      ++j)
    390                 {
    391                     bool found = false;
    392                     for (unsigned k = 0; !found && k <   enumStrings[i].cchBuffer
    393                                                        - enumStrings[i].pcchResult[j];
    394                          ++k)
    395                         if (memcmp(buffer + k, enumStrings[i].ppcchResult[j],
    396                             enumStrings[i].pcchResult[j]) == 0)
    397                             found = true;
    398                     if (!found)
    399                     {
    400                         RTPrintf("ENUM_PROPS_HOST did not produce the expected output for pattern %d\n",
    401                                  i);
    402                         rc = VERR_UNRESOLVED_ERROR;
    403                     }
    404                 }
    405         }
    406     }
    407     return rc;
     368        }
     369        else
     370            RTTestIFailed("ENUM_PROPS_HOST returned %Rrc instead of VINF_SUCCESS, pattern number %d.", rc2, i);
     371    }
    408372}
    409373
     
    437401    else if (useSetProp)
    438402        command = SET_PROP;
    439     VBOXHGCMSVCPARM paParms[3];
     403    VBOXHGCMSVCPARM aParms[3];
    440404    /* Work around silly constant issues - we ought to allow passing
    441405     * constant strings in the hgcm parameters. */
     
    446410    RTStrPrintf(szValue, sizeof(szValue), "%s", pcszValue);
    447411    RTStrPrintf(szFlags, sizeof(szFlags), "%s", pcszFlags);
    448     paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
    449     paParms[1].setPointer (szValue, (uint32_t)strlen(szValue) + 1);
    450     paParms[2].setPointer (szFlags, (uint32_t)strlen(szFlags) + 1);
     412    aParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
     413    aParms[1].setPointer (szValue, (uint32_t)strlen(szValue) + 1);
     414    aParms[2].setPointer (szFlags, (uint32_t)strlen(szFlags) + 1);
    451415    if (isHost)
    452416        callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
    453                                             useSetProp ? 3 : 2, paParms);
     417                                            useSetProp ? 3 : 2, aParms);
    454418    else
    455419        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command,
    456                         useSetProp ? 3 : 2, paParms);
     420                        useSetProp ? 3 : 2, aParms);
    457421    return callHandle.rc;
    458422}
    459 
    460 
    461 /** Array of properties for testing SET_PROP_HOST and _GUEST. */
    462 static const struct
    463 {
    464     /** Property name */
    465     const char *pcszName;
    466     /** Property value */
    467     const char *pcszValue;
    468     /** Property flags */
    469     const char *pcszFlags;
    470     /** Should this be set as the host or the guest? */
    471     bool isHost;
    472     /** Should we use SET_PROP or SET_PROP_VALUE? */
    473     bool useSetProp;
    474     /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
    475     bool isAllowed;
    476 }
    477 setProperties[] =
    478 {
    479     { "Red", "Stop!", "transient", false, true, true },
    480     { "Amber", "Caution!", "", false, false, true },
    481     { "Green", "Go!", "readonly", true, true, true },
    482     { "Blue", "What on earth...?", "", true, false, true },
    483     { "/test/name", "test", "", false, true, false },
    484     { "TEST NAME", "test", "", true, true, false },
    485     { "Green", "gone out...", "", false, false, false },
    486     { "Green", "gone out...", "", true, false, false },
    487     { NULL, NULL, NULL, false, false, false }
    488 };
    489423
    490424/**
     
    494428 * @note    prints its own diagnostic information to stdout.
    495429 */
    496 int testSetProp(VBOXHGCMSVCFNTABLE *pTable)
    497 {
    498     int rc = VINF_SUCCESS;
    499     RTPrintf("Testing the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls.\n");
    500     for (unsigned i = 0; RT_SUCCESS(rc) && (setProperties[i].pcszName != NULL);
    501          ++i)
    502     {
    503         rc = doSetProperty(pTable, setProperties[i].pcszName,
    504                            setProperties[i].pcszValue,
    505                            setProperties[i].pcszFlags,
    506                            setProperties[i].isHost,
    507                            setProperties[i].useSetProp);
    508         if (setProperties[i].isAllowed && RT_FAILURE(rc))
    509             RTPrintf("Setting property '%s' failed with rc=%Rrc.\n",
    510                      setProperties[i].pcszName, rc);
    511         else if (   !setProperties[i].isAllowed
    512                  && (rc != VERR_PERMISSION_DENIED))
    513         {
    514             RTPrintf("Setting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
    515                      setProperties[i].pcszName, rc);
    516             rc = VERR_IPE_UNEXPECTED_STATUS;
    517         }
    518         else
    519             rc = VINF_SUCCESS;
    520     }
    521     return rc;
     430static void testSetProp(VBOXHGCMSVCFNTABLE *pTable)
     431{
     432    RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST, SET_PROP_VALUE_HOST");
     433
     434    /** Array of properties for testing SET_PROP_HOST and _GUEST. */
     435    static const struct
     436    {
     437        /** Property name */
     438        const char *pcszName;
     439        /** Property value */
     440        const char *pcszValue;
     441        /** Property flags */
     442        const char *pcszFlags;
     443        /** Should this be set as the host or the guest? */
     444        bool isHost;
     445        /** Should we use SET_PROP or SET_PROP_VALUE? */
     446        bool useSetProp;
     447        /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
     448        bool isAllowed;
     449    }
     450    s_aSetProperties[] =
     451    {
     452        { "Red", "Stop!", "transient", false, true, true },
     453        { "Amber", "Caution!", "", false, false, true },
     454        { "Green", "Go!", "readonly", true, true, true },
     455        { "Blue", "What on earth...?", "", true, false, true },
     456        { "/test/name", "test", "", false, true, false },
     457        { "TEST NAME", "test", "", true, true, false },
     458        { "Green", "gone out...", "", false, false, false },
     459        { "Green", "gone out...", "", true, false, false },
     460    };
     461
     462    for (unsigned i = 0; i < RT_ELEMENTS(s_aSetProperties); ++i)
     463    {
     464        int rc = doSetProperty(pTable,
     465                               s_aSetProperties[i].pcszName,
     466                               s_aSetProperties[i].pcszValue,
     467                               s_aSetProperties[i].pcszFlags,
     468                               s_aSetProperties[i].isHost,
     469                               s_aSetProperties[i].useSetProp);
     470        if (s_aSetProperties[i].isAllowed && RT_FAILURE(rc))
     471            RTTestIFailed("Setting property '%s' failed with rc=%Rrc.",
     472                          s_aSetProperties[i].pcszName, rc);
     473        else if (   !s_aSetProperties[i].isAllowed
     474                 && rc != VERR_PERMISSION_DENIED)
     475            RTTestIFailed("Setting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.",
     476                          s_aSetProperties[i].pcszName, rc);
     477    }
    522478}
    523479
     
    531487 *                    than the guest one
    532488 */
    533 int doDelProp(VBOXHGCMSVCFNTABLE *pTable, const char *pcszName, bool isHost)
     489static int doDelProp(VBOXHGCMSVCFNTABLE *pTable, const char *pcszName, bool isHost)
    534490{
    535491    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
     
    537493    if (isHost)
    538494        command = DEL_PROP_HOST;
    539     VBOXHGCMSVCPARM paParms[1];
     495    VBOXHGCMSVCPARM aParms[1];
    540496    /* Work around silly constant issues - we ought to allow passing
    541497     * constant strings in the hgcm parameters. */
    542498    char szName[MAX_NAME_LEN];
    543499    RTStrPrintf(szName, sizeof(szName), "%s", pcszName);
    544     paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
     500    aParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
    545501    if (isHost)
    546         callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
    547                                             1, paParms);
     502        callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, 1, aParms);
    548503    else
    549         pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command,
    550                         1, paParms);
     504        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command, 1, aParms);
    551505    return callHandle.rc;
    552506}
    553 
    554 /** Array of properties for testing DEL_PROP_HOST and _GUEST. */
    555 static const struct
    556 {
    557     /** Property name */
    558     const char *pcszName;
    559     /** Should this be set as the host or the guest? */
    560     bool isHost;
    561     /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
    562     bool isAllowed;
    563 }
    564 delProperties[] =
    565 {
    566     { "Red", false, true },
    567     { "Amber", true, true },
    568     { "Red2", false, true },
    569     { "Amber2", true, true },
    570     { "Green", false, false },
    571     { "Green", true, false },
    572     { "/test/name", false, false },
    573     { "TEST NAME", true, false },
    574     { NULL, false, false }
    575 };
    576507
    577508/**
     
    580511 * @note    prints its own diagnostic information to stdout.
    581512 */
    582 int testDelProp(VBOXHGCMSVCFNTABLE *pTable)
    583 {
    584     int rc = VINF_SUCCESS;
    585     RTPrintf("Testing the DEL_PROP and DEL_PROP_HOST calls.\n");
    586     for (unsigned i = 0; RT_SUCCESS(rc) && (delProperties[i].pcszName != NULL);
    587          ++i)
    588     {
    589         rc = doDelProp(pTable, delProperties[i].pcszName,
    590                        delProperties[i].isHost);
    591         if (delProperties[i].isAllowed && RT_FAILURE(rc))
    592             RTPrintf("Deleting property '%s' failed with rc=%Rrc.\n",
    593                      delProperties[i].pcszName, rc);
    594         else if (   !delProperties[i].isAllowed
    595                  && (rc != VERR_PERMISSION_DENIED)
    596                 )
    597         {
    598             RTPrintf("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
    599                      delProperties[i].pcszName, rc);
    600             rc = VERR_IPE_UNEXPECTED_STATUS;
    601         }
    602         else
    603             rc = VINF_SUCCESS;
    604     }
    605     return rc;
    606 }
    607 
    608 /** Array of properties for testing GET_PROP_HOST. */
    609 static const struct
    610 {
    611     /** Property name */
    612     const char *pcszName;
    613     /** What value/flags pattern do we expect back? */
    614     const char *pcchValue;
    615     /** What size should the value/flags array be? */
    616     uint32_t cchValue;
    617     /** Should this property exist? */
    618     bool exists;
    619     /** Do we expect a particular timestamp? */
    620     bool hasTimestamp;
    621     /** What timestamp if any do ex expect? */
    622     uint64_t u64Timestamp;
    623 }
    624 getProperties[] =
    625 {
    626     { "test/name/", "test/value/\0", sizeof("test/value/\0"), true, true, 0 },
    627     { "test name", "test value\0TRANSIENT, READONLY",
    628       sizeof("test value\0TRANSIENT, READONLY"), true, true, 999 },
    629     { "TEST NAME", "TEST VALUE\0RDONLYHOST", sizeof("TEST VALUE\0RDONLYHOST"),
    630       true, true, 999999 },
    631     { "/test/name", "/test/value\0RDONLYGUEST",
    632       sizeof("/test/value\0RDONLYGUEST"), true, true, UINT64_C(999999999999) },
    633     { "Green", "Go!\0READONLY", sizeof("Go!\0READONLY"), true, false, 0 },
    634     { "Blue", "What on earth...?\0", sizeof("What on earth...?\0"), true,
    635       false, 0 },
    636     { "Red", "", 0, false, false, 0 },
    637     { NULL, NULL, 0, false, false, 0 }
    638 };
     513static void testDelProp(VBOXHGCMSVCFNTABLE *pTable)
     514{
     515    RTTestISub("DEL_PROP, DEL_PROP_HOST");
     516
     517    /** Array of properties for testing DEL_PROP_HOST and _GUEST. */
     518    static const struct
     519    {
     520        /** Property name */
     521        const char *pcszName;
     522        /** Should this be set as the host or the guest? */
     523        bool isHost;
     524        /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
     525        bool isAllowed;
     526    }
     527    s_aDelProperties[] =
     528    {
     529        { "Red", false, true },
     530        { "Amber", true, true },
     531        { "Red2", false, true },
     532        { "Amber2", true, true },
     533        { "Green", false, false },
     534        { "Green", true, false },
     535        { "/test/name", false, false },
     536        { "TEST NAME", true, false },
     537    };
     538
     539    for (unsigned i = 0; i < RT_ELEMENTS(s_aDelProperties); ++i)
     540    {
     541        int rc = doDelProp(pTable, s_aDelProperties[i].pcszName,
     542                           s_aDelProperties[i].isHost);
     543        if (s_aDelProperties[i].isAllowed && RT_FAILURE(rc))
     544            RTTestIFailed("Deleting property '%s' failed with rc=%Rrc.",
     545                          s_aDelProperties[i].pcszName, rc);
     546        else if (   !s_aDelProperties[i].isAllowed
     547                 && rc != VERR_PERMISSION_DENIED )
     548            RTTestIFailed("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.",
     549                          s_aDelProperties[i].pcszName, rc);
     550    }
     551}
    639552
    640553/**
     
    643556 * @note    prints its own diagnostic information to stdout.
    644557 */
    645 int testGetProp(VBOXHGCMSVCFNTABLE *pTable)
    646 {
    647     int rc = VINF_SUCCESS, rc2 = VINF_SUCCESS;
    648     RTPrintf("Testing the GET_PROP_HOST call.\n");
    649     for (unsigned i = 0; RT_SUCCESS(rc) && (getProperties[i].pcszName != NULL);
    650          ++i)
    651     {
    652         VBOXHGCMSVCPARM paParms[4];
     558static void testGetProp(VBOXHGCMSVCFNTABLE *pTable)
     559{
     560    RTTestISub("GET_PROP_HOST");
     561
     562    /** Array of properties for testing GET_PROP_HOST. */
     563    static const struct
     564    {
     565        /** Property name */
     566        const char *pcszName;
     567        /** What value/flags pattern do we expect back? */
     568        const char *pchValue;
     569        /** What size should the value/flags array be? */
     570        uint32_t cchValue;
     571        /** Should this property exist? */
     572        bool exists;
     573        /** Do we expect a particular timestamp? */
     574        bool hasTimestamp;
     575        /** What timestamp if any do ex expect? */
     576        uint64_t u64Timestamp;
     577    }
     578    s_aGetProperties[] =
     579    {
     580        { "test/name/", "test/value/\0", sizeof("test/value/\0"), true, true, 0 },
     581        { "test name", "test value\0TRANSIENT, READONLY",
     582          sizeof("test value\0TRANSIENT, READONLY"), true, true, 999 },
     583        { "TEST NAME", "TEST VALUE\0RDONLYHOST", sizeof("TEST VALUE\0RDONLYHOST"),
     584          true, true, 999999 },
     585        { "/test/name", "/test/value\0RDONLYGUEST",
     586          sizeof("/test/value\0RDONLYGUEST"), true, true, UINT64_C(999999999999) },
     587        { "Green", "Go!\0READONLY", sizeof("Go!\0READONLY"), true, false, 0 },
     588        { "Blue", "What on earth...?\0", sizeof("What on earth...?\0"), true,
     589          false, 0 },
     590        { "Red", "", 0, false, false, 0 },
     591    };
     592
     593    for (unsigned i = 0; i < RT_ELEMENTS(s_aGetProperties); ++i)
     594    {
     595        VBOXHGCMSVCPARM aParms[4];
    653596        /* Work around silly constant issues - we ought to allow passing
    654597         * constant strings in the hgcm parameters. */
    655598        char szName[MAX_NAME_LEN] = "";
    656599        char szBuffer[MAX_VALUE_LEN + MAX_FLAGS_LEN];
    657         AssertBreakStmt(sizeof(szBuffer) >= getProperties[i].cchValue,
    658                         rc = VERR_INTERNAL_ERROR);
    659         RTStrPrintf(szName, sizeof(szName), "%s", getProperties[i].pcszName);
    660         paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
    661         paParms[1].setPointer (szBuffer, sizeof(szBuffer));
    662         rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4,
    663                                   paParms);
    664         if (getProperties[i].exists && RT_FAILURE(rc2))
    665         {
    666             RTPrintf("Getting property '%s' failed with rc=%Rrc.\n",
    667                      getProperties[i].pcszName, rc2);
    668             rc = rc2;
    669         }
    670         else if (!getProperties[i].exists && (rc2 != VERR_NOT_FOUND))
    671         {
    672             RTPrintf("Getting property '%s' returned %Rrc instead of VERR_NOT_FOUND.\n",
    673                      getProperties[i].pcszName, rc2);
    674             rc = VERR_IPE_UNEXPECTED_STATUS;
    675         }
    676         if (RT_SUCCESS(rc) && getProperties[i].exists)
    677         {
    678             uint32_t u32ValueLen;
    679             rc = paParms[3].getUInt32 (&u32ValueLen);
    680             if (RT_FAILURE(rc))
    681                 RTPrintf("Failed to get the size of the output buffer for property '%s'\n",
    682                          getProperties[i].pcszName);
    683             if (   RT_SUCCESS(rc)
    684                 && (memcmp(szBuffer, getProperties[i].pcchValue,
    685                            getProperties[i].cchValue) != 0)
    686                )
     600        RTTESTI_CHECK_RETV(s_aGetProperties[i].cchValue < sizeof(szBuffer));
     601        RTTESTI_CHECK_RETV(strlen(s_aGetProperties[i].pcszName) < sizeof(szName));
     602
     603        strcpy(szName, s_aGetProperties[i].pcszName);
     604        aParms[0].setPointer(szName, (uint32_t)(strlen(szName) + 1));
     605        aParms[1].setPointer(szBuffer, sizeof(szBuffer));
     606        int rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4, aParms);
     607
     608        if (s_aGetProperties[i].exists && RT_FAILURE(rc2))
     609        {
     610            RTTestIFailed("Getting property '%s' failed with rc=%Rrc.",
     611                          s_aGetProperties[i].pcszName, rc2);
     612            continue;
     613        }
     614
     615        if (!s_aGetProperties[i].exists && rc2 != VERR_NOT_FOUND)
     616        {
     617            RTTestIFailed("Getting property '%s' returned %Rrc instead of VERR_NOT_FOUND.",
     618                          s_aGetProperties[i].pcszName, rc2);
     619            continue;
     620        }
     621
     622        if (s_aGetProperties[i].exists)
     623        {
     624            AssertRC(rc2);
     625
     626            uint32_t u32ValueLen = UINT32_MAX;
     627            RTTESTI_CHECK_RC(rc2 = aParms[3].getUInt32(&u32ValueLen), VINF_SUCCESS);
     628            if (RT_SUCCESS(rc2))
    687629            {
    688                 RTPrintf("Unexpected result '%.*s' for property '%s', expected '%.*s'.\n",
    689                          u32ValueLen, szBuffer, getProperties[i].pcszName,
    690                          getProperties[i].cchValue, getProperties[i].pcchValue);
    691                 rc = VERR_UNRESOLVED_ERROR;
     630                RTTESTI_CHECK_MSG(u32ValueLen <= sizeof(szBuffer), ("u32ValueLen=%d", u32ValueLen));
     631                if (memcmp(szBuffer, s_aGetProperties[i].pchValue, s_aGetProperties[i].cchValue) != 0)
     632                    RTTestIFailed("Unexpected result '%.*s' for property '%s', expected '%.*s'.",
     633                                  u32ValueLen, szBuffer, s_aGetProperties[i].pcszName,
     634                                  s_aGetProperties[i].cchValue, s_aGetProperties[i].pchValue);
    692635            }
    693             if (RT_SUCCESS(rc) && getProperties[i].hasTimestamp)
     636
     637            if (s_aGetProperties[i].hasTimestamp)
    694638            {
    695                 uint64_t u64Timestamp;
    696                 rc = paParms[2].getUInt64 (&u64Timestamp);
    697                 if (RT_FAILURE(rc))
    698                     RTPrintf("Failed to get the timestamp for property '%s'\n",
    699                              getProperties[i].pcszName);
    700                 if (   RT_SUCCESS(rc)
    701                     && (u64Timestamp != getProperties[i].u64Timestamp)
    702                    )
    703                 {
    704                     RTPrintf("Bad timestamp %llu for property '%s', expected %llu.\n",
    705                              u64Timestamp, getProperties[i].pcszName,
    706                              getProperties[i].u64Timestamp);
    707                     rc = VERR_UNRESOLVED_ERROR;
    708                 }
     639                uint64_t u64Timestamp = UINT64_MAX;
     640                RTTESTI_CHECK_RC(rc2 = aParms[2].getUInt64(&u64Timestamp), VINF_SUCCESS);
     641                if (u64Timestamp != s_aGetProperties[i].u64Timestamp)
     642                    RTTestIFailed("Bad timestamp %llu for property '%s', expected %llu.",
     643                                  u64Timestamp, s_aGetProperties[i].pcszName,
     644                                  s_aGetProperties[i].u64Timestamp);
    709645            }
    710646        }
    711647    }
    712     return rc;
    713648}
    714649
     
    719654    const char *pchBuffer;
    720655    /** What size should the buffer be? */
    721     uint32_t cchBuffer;
    722 }
    723 getNotifications[] =
     656    uint32_t cbBuffer;
     657}
     658g_aGetNotifications[] =
    724659{
    725660    { "Red\0Stop!\0TRANSIENT", sizeof("Red\0Stop!\0TRANSIENT") },
     
    729664    { "Red\0\0", sizeof("Red\0\0") },
    730665    { "Amber\0\0", sizeof("Amber\0\0") },
    731     { NULL, 0 }
    732666};
    733667
     
    737671 * @note    prints its own diagnostic information to stdout.
    738672 */
    739 int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
    740 {
    741     int rc = VINF_SUCCESS;
    742     VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
    743     char achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
    744     static char szPattern[] = "";
    745 
    746     RTPrintf("Testing the GET_NOTIFICATION call.\n");
    747     uint64_t u64Timestamp;
    748     uint32_t u32Size = 0;
    749     VBOXHGCMSVCPARM paParms[4];
     673static void testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
     674{
     675    RTTestISub("GET_NOTIFICATION");
    750676
    751677    /* Test "buffer too small" */
    752     u64Timestamp = 1;
    753     paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
    754     paParms[1].setUInt64 (u64Timestamp);
    755     paParms[2].setPointer ((void *) achBuffer, getNotifications[0].cchBuffer - 1);
    756     pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
    757                     GET_NOTIFICATION, 4, paParms);
     678    char                        achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
     679    static char                 s_szPattern[] = "";
     680    VBOXHGCMCALLHANDLE_TYPEDEF  callHandle = { VINF_SUCCESS };
     681    VBOXHGCMSVCPARM             aParms[4];
     682    aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern));
     683    aParms[1].setUInt64(1);
     684    aParms[2].setPointer((void *)achBuffer, g_aGetNotifications[0].cbBuffer - 1);
     685    pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, GET_NOTIFICATION, 4, aParms);
     686
     687    uint32_t cbRetNeeded;
    758688    if (   callHandle.rc != VERR_BUFFER_OVERFLOW
    759         || RT_FAILURE(paParms[3].getUInt32 (&u32Size))
    760         || u32Size != getNotifications[0].cchBuffer
     689        || RT_FAILURE(aParms[3].getUInt32(&cbRetNeeded))
     690        || cbRetNeeded != g_aGetNotifications[0].cbBuffer
    761691       )
    762692    {
    763         RTPrintf("Getting notification for property '%s' with a too small buffer did not fail correctly.\n",
    764                  getNotifications[0].pchBuffer);
    765         rc = VERR_UNRESOLVED_ERROR;
     693        RTTestIFailed("Getting notification for property '%s' with a too small buffer did not fail correctly.",
     694                      g_aGetNotifications[0].pchBuffer);
     695        return;
    766696    }
    767697
    768698    /* Test successful notification queries.  Start with an unknown timestamp
    769699     * to get the oldest available notification. */
    770     u64Timestamp = 1;
    771     for (unsigned i = 0; RT_SUCCESS(rc) && (getNotifications[i].pchBuffer != NULL);
    772          ++i)
    773     {
    774         paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
    775         paParms[1].setUInt64 (u64Timestamp);
    776         paParms[2].setPointer ((void *) achBuffer, sizeof(achBuffer));
    777         pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
    778                         GET_NOTIFICATION, 4, paParms);
     700    uint64_t u64Timestamp = 1;
     701    for (unsigned i = 0; i < RT_ELEMENTS(g_aGetNotifications); ++i)
     702    {
     703        aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern));
     704        aParms[1].setUInt64(u64Timestamp);
     705        aParms[2].setPointer((void *)achBuffer, sizeof(achBuffer));
     706        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, GET_NOTIFICATION, 4, aParms);
    779707        if (   RT_FAILURE(callHandle.rc)
    780708            || (i == 0 && callHandle.rc != VWRN_NOT_FOUND)
    781             || RT_FAILURE(paParms[1].getUInt64 (&u64Timestamp))
    782             || RT_FAILURE(paParms[3].getUInt32 (&u32Size))
    783             || u32Size != getNotifications[i].cchBuffer
    784             || memcmp(achBuffer, getNotifications[i].pchBuffer, u32Size) != 0
     709            || RT_FAILURE(aParms[1].getUInt64(&u64Timestamp))
     710            || RT_FAILURE(aParms[3].getUInt32(&cbRetNeeded))
     711            || cbRetNeeded != g_aGetNotifications[i].cbBuffer
     712            || memcmp(achBuffer, g_aGetNotifications[i].pchBuffer, cbRetNeeded) != 0
    785713           )
    786714        {
    787             RTPrintf("Failed to get notification for property '%s' (rc=%Rrc).\n",
    788                      getNotifications[i].pchBuffer, rc);
    789             rc = VERR_UNRESOLVED_ERROR;
    790         }
    791     }
    792     return rc;
     715            RTTestIFailed("Failed to get notification for property '%s' (rc=%Rrc).",
     716                          g_aGetNotifications[i].pchBuffer, callHandle.rc);
     717        }
     718    }
    793719}
    794720
     
    799725    VBOXHGCMSVCPARM aParms[4];
    800726    /** Result buffer */
    801     char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
     727    char abBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
    802728    /** Return value */
    803729    VBOXHGCMCALLHANDLE_TYPEDEF callHandle;
    804 } asyncNotification;
     730} g_AsyncNotification;
    805731
    806732/**
    807733 * Set up the test for the asynchronous GET_NOTIFICATION function.
    808  * @returns iprt status value to indicate whether the test went as expected.
    809  * @note    prints its own diagnostic information to stdout.
    810  */
    811 int setupAsyncNotification(VBOXHGCMSVCFNTABLE *pTable)
    812 {
    813     int rc = VINF_SUCCESS;
    814 
    815     RTPrintf("Testing the asynchronous GET_NOTIFICATION call with no notifications are available.\n");
    816     uint64_t u64Timestamp = 0;
    817     uint32_t u32Size = 0;
    818     static char szPattern[] = "";
    819 
    820     asyncNotification.aParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
    821     asyncNotification.aParms[1].setUInt64 (u64Timestamp);
    822     asyncNotification.aParms[2].setPointer ((void *) asyncNotification.chBuffer,
    823                                             sizeof(asyncNotification.chBuffer));
    824     asyncNotification.callHandle.rc = VINF_HGCM_ASYNC_EXECUTE;
    825     pTable->pfnCall(pTable->pvService, &asyncNotification.callHandle, 0, NULL,
    826                     GET_NOTIFICATION, 4, asyncNotification.aParms);
    827     if (RT_FAILURE(asyncNotification.callHandle.rc))
    828     {
    829         RTPrintf("GET_NOTIFICATION call failed, rc=%Rrc.\n", asyncNotification.callHandle.rc);
    830         rc = VERR_UNRESOLVED_ERROR;
    831     }
    832     else if (asyncNotification.callHandle.rc != VINF_HGCM_ASYNC_EXECUTE)
    833     {
    834         RTPrintf("GET_NOTIFICATION call completed when no new notifications should be available.\n");
    835         rc = VERR_UNRESOLVED_ERROR;
    836     }
    837     return rc;
     734 */
     735static void setupAsyncNotification(VBOXHGCMSVCFNTABLE *pTable)
     736{
     737    RTTestISub("Asynchronous GET_NOTIFICATION call with no notifications are available");
     738    static char s_szPattern[] = "";
     739
     740    g_AsyncNotification.aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern));
     741    g_AsyncNotification.aParms[1].setUInt64(0);
     742    g_AsyncNotification.aParms[2].setPointer((void *)g_AsyncNotification.abBuffer,
     743                                             sizeof(g_AsyncNotification.abBuffer));
     744    g_AsyncNotification.callHandle.rc = VINF_HGCM_ASYNC_EXECUTE;
     745    pTable->pfnCall(pTable->pvService, &g_AsyncNotification.callHandle, 0, NULL,
     746                    GET_NOTIFICATION, 4, g_AsyncNotification.aParms);
     747    if (RT_FAILURE(g_AsyncNotification.callHandle.rc))
     748        RTTestIFailed("GET_NOTIFICATION call failed, rc=%Rrc.", g_AsyncNotification.callHandle.rc);
     749    else if (g_AsyncNotification.callHandle.rc != VINF_HGCM_ASYNC_EXECUTE)
     750        RTTestIFailed("GET_NOTIFICATION call completed when no new notifications should be available.");
    838751}
    839752
    840753/**
    841754 * Test the asynchronous GET_NOTIFICATION function.
    842  * @returns iprt status value to indicate whether the test went as expected.
    843  * @note    prints its own diagnostic information to stdout.
    844  */
    845 int testAsyncNotification(VBOXHGCMSVCFNTABLE *pTable)
    846 {
    847     int rc = VINF_SUCCESS;
     755 */
     756static void testAsyncNotification(VBOXHGCMSVCFNTABLE *pTable)
     757{
    848758    uint64_t u64Timestamp;
    849759    uint32_t u32Size;
    850     if (   asyncNotification.callHandle.rc != VINF_SUCCESS
    851         || RT_FAILURE(asyncNotification.aParms[1].getUInt64 (&u64Timestamp))
    852         || RT_FAILURE(asyncNotification.aParms[3].getUInt32 (&u32Size))
    853         || u32Size != getNotifications[0].cchBuffer
    854         || memcmp(asyncNotification.chBuffer, getNotifications[0].pchBuffer, u32Size) != 0
     760    if (   g_AsyncNotification.callHandle.rc != VINF_SUCCESS
     761        || RT_FAILURE(g_AsyncNotification.aParms[1].getUInt64(&u64Timestamp))
     762        || RT_FAILURE(g_AsyncNotification.aParms[3].getUInt32(&u32Size))
     763        || u32Size != g_aGetNotifications[0].cbBuffer
     764        || memcmp(g_AsyncNotification.abBuffer, g_aGetNotifications[0].pchBuffer, u32Size) != 0
    855765       )
    856766    {
    857         RTPrintf("Asynchronous GET_NOTIFICATION call did not complete as expected, rc=%Rrc\n",
    858                  asyncNotification.callHandle.rc);
    859         rc = VERR_UNRESOLVED_ERROR;
    860     }
    861     return rc;
    862 }
    863 
    864 /** Array of properties for testing SET_PROP_HOST and _GUEST with the
    865  * READONLYGUEST global flag set. */
    866 static const struct
    867 {
    868     /** Property name */
    869     const char *pcszName;
    870     /** Property value */
    871     const char *pcszValue;
    872     /** Property flags */
    873     const char *pcszFlags;
    874     /** Should this be set as the host or the guest? */
    875     bool isHost;
    876     /** Should we use SET_PROP or SET_PROP_VALUE? */
    877     bool useSetProp;
    878     /** Should this succeed or be rejected with VERR_ (NOT VINF_!)
    879      * PERMISSION_DENIED?  The global check is done after the property one. */
    880     bool isAllowed;
    881 }
    882 setPropertiesROGuest[] =
    883 {
    884     { "Red", "Stop!", "transient", false, true, true },
    885     { "Amber", "Caution!", "", false, false, true },
    886     { "Green", "Go!", "readonly", true, true, true },
    887     { "Blue", "What on earth...?", "", true, false, true },
    888     { "/test/name", "test", "", false, true, true },
    889     { "TEST NAME", "test", "", true, true, true },
    890     { "Green", "gone out...", "", false, false, false },
    891     { "Green", "gone out....", "", true, false, false },
    892     { NULL, NULL, NULL, false, false, true }
    893 };
     767        RTTestIFailed("Asynchronous GET_NOTIFICATION call did not complete as expected, rc=%Rrc.",
     768                      g_AsyncNotification.callHandle.rc);
     769    }
     770}
     771
     772
     773static void test2(void)
     774{
     775    VBOXHGCMSVCFNTABLE  svcTable;
     776    VBOXHGCMSVCHELPERS  svcHelpers;
     777    initTable(&svcTable, &svcHelpers);
     778
     779    /* The function is inside the service, not HGCM. */
     780    RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(&svcTable));
     781
     782    testSetPropsHost(&svcTable);
     783    testEnumPropsHost(&svcTable);
     784
     785    /* Set up the asynchronous notification test */
     786    setupAsyncNotification(&svcTable);
     787    testSetProp(&svcTable);
     788    RTTestISub("Checking the data returned by the asynchronous notification call");
     789    testAsyncNotification(&svcTable); /* Our previous notification call should have completed by now. */
     790
     791    testDelProp(&svcTable);
     792    testGetProp(&svcTable);
     793    testGetNotification(&svcTable);
     794
     795    /* Cleanup */
     796    RTTESTI_CHECK_RC_OK(svcTable.pfnUnload(svcTable.pvService));
     797}
    894798
    895799/**
     
    900804 * @param   eFlags  the flags to set
    901805 */
    902 int doSetGlobalFlags(VBOXHGCMSVCFNTABLE *pTable, ePropFlags eFlags)
     806static int doSetGlobalFlags(VBOXHGCMSVCFNTABLE *pTable, ePropFlags eFlags)
    903807{
    904808    VBOXHGCMSVCPARM paParm;
    905809    paParm.setUInt32(eFlags);
    906     int rc = pTable->pfnHostCall(pTable->pvService, SET_GLOBAL_FLAGS_HOST,
    907                                  1, &paParm);
     810    int rc = pTable->pfnHostCall(pTable->pvService, SET_GLOBAL_FLAGS_HOST, 1, &paParm);
    908811    if (RT_FAILURE(rc))
    909812    {
    910813        char szFlags[MAX_FLAGS_LEN];
    911814        if (RT_FAILURE(writeFlags(eFlags, szFlags)))
    912             RTPrintf("Failed to set the global flags.\n");
     815            RTTestIFailed("Failed to set the global flags.");
    913816        else
    914             RTPrintf("Failed to set the global flags \"%s\".\n",
    915                      szFlags);
     817            RTTestIFailed("Failed to set the global flags \"%s\".", szFlags);
    916818    }
    917819    return rc;
     
    924826 * @note    prints its own diagnostic information to stdout.
    925827 */
    926 int testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable)
    927 {
    928     int rc = VINF_SUCCESS;
    929     RTPrintf("Testing the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls with READONLYGUEST set globally.\n");
    930     rc = VBoxHGCMSvcLoad(pTable);
    931     if (RT_FAILURE(rc))
    932         RTPrintf("Failed to start the HGCM service.\n");
     828static void testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable)
     829{
     830    RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls with READONLYGUEST set globally");
     831
     832    /** Array of properties for testing SET_PROP_HOST and _GUEST with the
     833     * READONLYGUEST global flag set. */
     834    static const struct
     835    {
     836        /** Property name */
     837        const char *pcszName;
     838        /** Property value */
     839        const char *pcszValue;
     840        /** Property flags */
     841        const char *pcszFlags;
     842        /** Should this be set as the host or the guest? */
     843        bool isHost;
     844        /** Should we use SET_PROP or SET_PROP_VALUE? */
     845        bool useSetProp;
     846        /** Should this succeed or be rejected with VERR_ (NOT VINF_!)
     847         * PERMISSION_DENIED?  The global check is done after the property one. */
     848        bool isAllowed;
     849    }
     850    s_aSetPropertiesROGuest[] =
     851    {
     852        { "Red", "Stop!", "transient", false, true, true },
     853        { "Amber", "Caution!", "", false, false, true },
     854        { "Green", "Go!", "readonly", true, true, true },
     855        { "Blue", "What on earth...?", "", true, false, true },
     856        { "/test/name", "test", "", false, true, true },
     857        { "TEST NAME", "test", "", true, true, true },
     858        { "Green", "gone out...", "", false, false, false },
     859        { "Green", "gone out....", "", true, false, false },
     860    };
     861
     862    RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(pTable));
     863    int rc = doSetGlobalFlags(pTable, RDONLYGUEST);
    933864    if (RT_SUCCESS(rc))
    934         rc = doSetGlobalFlags(pTable, RDONLYGUEST);
    935     for (unsigned i = 0; RT_SUCCESS(rc) && (setPropertiesROGuest[i].pcszName != NULL);
    936          ++i)
    937     {
    938         rc = doSetProperty(pTable, setPropertiesROGuest[i].pcszName,
    939                            setPropertiesROGuest[i].pcszValue,
    940                            setPropertiesROGuest[i].pcszFlags,
    941                            setPropertiesROGuest[i].isHost,
    942                            setPropertiesROGuest[i].useSetProp);
    943         if (setPropertiesROGuest[i].isAllowed && RT_FAILURE(rc))
    944             RTPrintf("Setting property '%s' to '%s' failed with rc=%Rrc.\n",
    945                      setPropertiesROGuest[i].pcszName,
    946                      setPropertiesROGuest[i].pcszValue, rc);
    947         else if (   !setPropertiesROGuest[i].isAllowed
    948                  && (rc != VERR_PERMISSION_DENIED))
    949         {
    950             RTPrintf("Setting property '%s' to '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
    951                      setPropertiesROGuest[i].pcszName,
    952                      setPropertiesROGuest[i].pcszValue, rc);
    953             rc = VERR_IPE_UNEXPECTED_STATUS;
    954         }
    955         else if (   !setPropertiesROGuest[i].isHost
    956                  && setPropertiesROGuest[i].isAllowed
    957                  && (rc != VINF_PERMISSION_DENIED))
    958         {
    959             RTPrintf("Setting property '%s' to '%s' returned %Rrc instead of VINF_PERMISSION_DENIED.\n",
    960                      setPropertiesROGuest[i].pcszName,
    961                      setPropertiesROGuest[i].pcszValue, rc);
    962             rc = VERR_IPE_UNEXPECTED_STATUS;
    963         }
    964         else
    965             rc = VINF_SUCCESS;
    966     }
    967     if (RT_FAILURE(pTable->pfnUnload(pTable->pvService)))
    968         RTPrintf("Failed to unload the HGCM service.\n");
    969     return rc;
    970 }
    971 
    972 /** Array of properties for testing DEL_PROP_HOST and _GUEST with
    973  * READONLYGUEST set globally. */
    974 static const struct
    975 {
    976     /** Property name */
    977     const char *pcszName;
    978     /** Should this be deleted as the host (or the guest)? */
    979     bool isHost;
    980     /** Should this property be created first?  (As host, obviously) */
    981     bool shouldCreate;
    982     /** And with what flags? */
    983     const char *pcszFlags;
    984     /** Should this succeed or be rejected with VERR_ (NOT VINF_!)
    985      * PERMISSION_DENIED?  The global check is done after the property one. */
    986     bool isAllowed;
    987 }
    988 delPropertiesROGuest[] =
    989 {
    990     { "Red", true, true, "", true },
    991     { "Amber", false, true, "", true },
    992     { "Red2", true, false, "", true },
    993     { "Amber2", false, false, "", true },
    994     { "Red3", true, true, "READONLY", false },
    995     { "Amber3", false, true, "READONLY", false },
    996     { "Red4", true, true, "RDONLYHOST", false },
    997     { "Amber4", false, true, "RDONLYHOST", true },
    998     { NULL, false, false, "", false }
    999 };
     865    {
     866        for (unsigned i = 0; i < RT_ELEMENTS(s_aSetPropertiesROGuest); ++i)
     867        {
     868            rc = doSetProperty(pTable, s_aSetPropertiesROGuest[i].pcszName,
     869                               s_aSetPropertiesROGuest[i].pcszValue,
     870                               s_aSetPropertiesROGuest[i].pcszFlags,
     871                               s_aSetPropertiesROGuest[i].isHost,
     872                               s_aSetPropertiesROGuest[i].useSetProp);
     873            if (s_aSetPropertiesROGuest[i].isAllowed && RT_FAILURE(rc))
     874                RTTestIFailed("Setting property '%s' to '%s' failed with rc=%Rrc.",
     875                              s_aSetPropertiesROGuest[i].pcszName,
     876                              s_aSetPropertiesROGuest[i].pcszValue, rc);
     877            else if (   !s_aSetPropertiesROGuest[i].isAllowed
     878                     && rc != VERR_PERMISSION_DENIED)
     879                RTTestIFailed("Setting property '%s' to '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
     880                              s_aSetPropertiesROGuest[i].pcszName,
     881                              s_aSetPropertiesROGuest[i].pcszValue, rc);
     882            else if (   !s_aSetPropertiesROGuest[i].isHost
     883                     && s_aSetPropertiesROGuest[i].isAllowed
     884                     && rc != VINF_PERMISSION_DENIED)
     885                RTTestIFailed("Setting property '%s' to '%s' returned %Rrc instead of VINF_PERMISSION_DENIED.\n",
     886                              s_aSetPropertiesROGuest[i].pcszName,
     887                              s_aSetPropertiesROGuest[i].pcszValue, rc);
     888        }
     889    }
     890    RTTESTI_CHECK_RC_OK(pTable->pfnUnload(pTable->pvService));
     891}
    1000892
    1001893/**
     
    1004896 * @note    prints its own diagnostic information to stdout.
    1005897 */
    1006 int testDelPropROGuest(VBOXHGCMSVCFNTABLE *pTable)
    1007 {
    1008     int rc = VINF_SUCCESS;
    1009     RTPrintf("Testing the DEL_PROP and DEL_PROP_HOST calls with RDONLYGUEST set globally.\n");
    1010     rc = VBoxHGCMSvcLoad(pTable);
    1011     if (RT_FAILURE(rc))
    1012         RTPrintf("Failed to start the HGCM service.\n");
     898static void testDelPropROGuest(VBOXHGCMSVCFNTABLE *pTable)
     899{
     900    RTTestISub("DEL_PROP and DEL_PROP_HOST calls with RDONLYGUEST set globally");
     901
     902    /** Array of properties for testing DEL_PROP_HOST and _GUEST with
     903     * READONLYGUEST set globally. */
     904    static const struct
     905    {
     906        /** Property name */
     907        const char *pcszName;
     908        /** Should this be deleted as the host (or the guest)? */
     909        bool isHost;
     910        /** Should this property be created first?  (As host, obviously) */
     911        bool shouldCreate;
     912        /** And with what flags? */
     913        const char *pcszFlags;
     914        /** Should this succeed or be rejected with VERR_ (NOT VINF_!)
     915         * PERMISSION_DENIED?  The global check is done after the property one. */
     916        bool isAllowed;
     917    }
     918    s_aDelPropertiesROGuest[] =
     919    {
     920        { "Red", true, true, "", true },
     921        { "Amber", false, true, "", true },
     922        { "Red2", true, false, "", true },
     923        { "Amber2", false, false, "", true },
     924        { "Red3", true, true, "READONLY", false },
     925        { "Amber3", false, true, "READONLY", false },
     926        { "Red4", true, true, "RDONLYHOST", false },
     927        { "Amber4", false, true, "RDONLYHOST", true },
     928    };
     929
     930    RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(pTable));
     931    int rc = doSetGlobalFlags(pTable, RDONLYGUEST);
    1013932    if (RT_SUCCESS(rc))
    1014         rc = doSetGlobalFlags(pTable, RDONLYGUEST);
    1015     for (unsigned i = 0;    RT_SUCCESS(rc)
    1016                          && (delPropertiesROGuest[i].pcszName != NULL); ++i)
    1017     {
    1018         if (RT_SUCCESS(rc) && delPropertiesROGuest[i].shouldCreate)
    1019             rc = doSetProperty(pTable, delPropertiesROGuest[i].pcszName,
    1020                                "none", delPropertiesROGuest[i].pcszFlags,
    1021                                true, true);
    1022         rc = doDelProp(pTable, delPropertiesROGuest[i].pcszName,
    1023                        delPropertiesROGuest[i].isHost);
    1024         if (delPropertiesROGuest[i].isAllowed && RT_FAILURE(rc))
    1025             RTPrintf("Deleting property '%s' failed with rc=%Rrc.\n",
    1026                      delPropertiesROGuest[i].pcszName, rc);
    1027         else if (   !delPropertiesROGuest[i].isAllowed
    1028                  && (rc != VERR_PERMISSION_DENIED)
    1029                 )
    1030         {
    1031             RTPrintf("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
    1032                      delPropertiesROGuest[i].pcszName, rc);
    1033             rc = VERR_IPE_UNEXPECTED_STATUS;
    1034         }
    1035         else if (   !delPropertiesROGuest[i].isHost
    1036                  && delPropertiesROGuest[i].shouldCreate
    1037                  && delPropertiesROGuest[i].isAllowed
    1038                  && (rc != VINF_PERMISSION_DENIED))
    1039         {
    1040             RTPrintf("Deleting property '%s' as guest returned %Rrc instead of VINF_PERMISSION_DENIED.\n",
    1041                      delPropertiesROGuest[i].pcszName, rc);
    1042             rc = VERR_IPE_UNEXPECTED_STATUS;
    1043         }
    1044         else
    1045             rc = VINF_SUCCESS;
    1046     }
    1047     if (RT_FAILURE(pTable->pfnUnload(pTable->pvService)))
    1048         RTPrintf("Failed to unload the HGCM service.\n");
    1049     return rc;
    1050 }
    1051 
    1052 int main(int argc, char **argv)
     933    {
     934        for (unsigned i = 0; i < RT_ELEMENTS(s_aDelPropertiesROGuest); ++i)
     935        {
     936            if (s_aDelPropertiesROGuest[i].shouldCreate)
     937                rc = doSetProperty(pTable, s_aDelPropertiesROGuest[i].pcszName,
     938                                   "none", s_aDelPropertiesROGuest[i].pcszFlags,
     939                                   true, true);
     940            rc = doDelProp(pTable, s_aDelPropertiesROGuest[i].pcszName,
     941                           s_aDelPropertiesROGuest[i].isHost);
     942            if (s_aDelPropertiesROGuest[i].isAllowed && RT_FAILURE(rc))
     943                RTTestIFailed("Deleting property '%s' failed with rc=%Rrc.",
     944                              s_aDelPropertiesROGuest[i].pcszName, rc);
     945            else if (   !s_aDelPropertiesROGuest[i].isAllowed
     946                     && rc != VERR_PERMISSION_DENIED)
     947                RTTestIFailed("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.",
     948                              s_aDelPropertiesROGuest[i].pcszName, rc);
     949            else if (   !s_aDelPropertiesROGuest[i].isHost
     950                     && s_aDelPropertiesROGuest[i].shouldCreate
     951                     && s_aDelPropertiesROGuest[i].isAllowed
     952                     && rc != VINF_PERMISSION_DENIED)
     953                RTTestIFailed("Deleting property '%s' as guest returned %Rrc instead of VINF_PERMISSION_DENIED.",
     954                              s_aDelPropertiesROGuest[i].pcszName, rc);
     955        }
     956    }
     957    RTTESTI_CHECK_RC_OK(pTable->pfnUnload(pTable->pvService));
     958}
     959
     960static void test3(void)
    1053961{
    1054962    VBOXHGCMSVCFNTABLE  svcTable;
    1055963    VBOXHGCMSVCHELPERS  svcHelpers;
    1056     RTEXITCODE          rcExit;
    1057 
    1058     rcExit  = RTTestInitAndCreate("tstGuestPropSvc", &g_hTest);
     964    initTable(&svcTable, &svcHelpers);
     965    testSetPropROGuest(&svcTable);
     966    testDelPropROGuest(&svcTable);
     967}
     968
     969
     970static void test4(void)
     971{
     972    RTTestISub("Max properties");
     973
     974    VBOXHGCMSVCFNTABLE  svcTable;
     975    VBOXHGCMSVCHELPERS  svcHelpers;
     976    initTable(&svcTable, &svcHelpers);
     977    RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(&svcTable));
     978
     979    /* Insert the max number of properties. */
     980    static char const   s_szPropFmt[] = "/MyProperties/Sub/Sub/Sub/Sub/Sub/Sub/Sub/PropertyNo#%u";
     981    char                szProp[80];
     982    unsigned            cProps = 0;
     983    for (;;)
     984    {
     985        RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, cProps);
     986        int rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, true);
     987        if (rc == VERR_TOO_MUCH_DATA)
     988            break;
     989        if (RT_FAILURE(rc))
     990        {
     991            RTTestIFailed("Unexpected error %Rrc setting property number %u", rc, cProps);
     992            break;
     993        }
     994        cProps++;
     995    }
     996    RTTestIValue("Max Properties", cProps, RTTESTUNIT_OCCURRENCES);
     997
     998    /* Touch them all again. */
     999    for (unsigned iProp = 0; iProp < cProps; iProp++)
     1000    {
     1001        RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, iProp);
     1002        int rc;
     1003        RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, true)) == VINF_SUCCESS,
     1004                          ("%Rrc - #%u\n", rc, iProp));
     1005        RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, false)) == VINF_SUCCESS,
     1006                          ("%Rrc - #%u\n", rc, iProp));
     1007        RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", false, true)) == VINF_SUCCESS,
     1008                          ("%Rrc - #%u\n", rc, iProp));
     1009        RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", false, false)) == VINF_SUCCESS,
     1010                          ("%Rrc - #%u\n", rc, iProp));
     1011    }
     1012
     1013    /* Benchmark. */
     1014    uint64_t cNsMax = 0;
     1015    uint64_t cNsMin = UINT64_MAX;
     1016    uint64_t cNsAvg = 0;
     1017    for (unsigned iProp = 0; iProp < cProps; iProp++)
     1018    {
     1019        size_t cchProp = RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, iProp);
     1020
     1021        uint64_t cNsElapsed = RTTimeNanoTS();
     1022        unsigned iCall;
     1023        for (iCall = 0; iCall < 1000; iCall++)
     1024        {
     1025            VBOXHGCMSVCPARM aParms[4];
     1026            char            szBuffer[256];
     1027            aParms[0].setPointer(szProp, cchProp + 1);
     1028            aParms[1].setPointer(szBuffer, sizeof(szBuffer));
     1029            RTTESTI_CHECK_RC_BREAK(svcTable.pfnHostCall(svcTable.pvService, GET_PROP_HOST, 4, aParms), VINF_SUCCESS);
     1030        }
     1031        cNsElapsed = RTTimeNanoTS() - cNsElapsed;
     1032        if (iCall)
     1033        {
     1034            uint64_t cNsPerCall = cNsElapsed / iCall;
     1035            cNsAvg += cNsPerCall;
     1036            if (cNsPerCall < cNsMin)
     1037                cNsMin = cNsPerCall;
     1038            if (cNsPerCall > cNsMax)
     1039                cNsMax = cNsPerCall;
     1040        }
     1041    }
     1042    if (cProps)
     1043        cNsAvg /= cProps;
     1044    RTTestIValue("GET_PROP_HOST Min", cNsMin, RTTESTUNIT_NS_PER_CALL);
     1045    RTTestIValue("GET_PROP_HOST Avg", cNsAvg, RTTESTUNIT_NS_PER_CALL);
     1046    RTTestIValue("GET_PROP_HOST Max", cNsMax, RTTESTUNIT_NS_PER_CALL);
     1047
     1048    /* Done. */
     1049    RTTESTI_CHECK_RC_OK(svcTable.pfnUnload(svcTable.pvService));
     1050}
     1051
     1052
     1053int main(int argc, char **argv)
     1054{
     1055    RTEXITCODE rcExit = RTTestInitAndCreate("tstGuestPropSvc", &g_hTest);
    10591056    if (rcExit != RTEXITCODE_SUCCESS)
    10601057        return rcExit;
    10611058    RTTestBanner(g_hTest);
    10621059
    1063 /** @todo convert the rest of this testcase. */
    1064     initTable(&svcTable, &svcHelpers);
    1065 
    1066     if (RT_FAILURE(testConvertFlags()))
    1067         return 1;
    1068     /* The function is inside the service, not HGCM. */
    1069     if (RT_FAILURE(VBoxHGCMSvcLoad(&svcTable)))
    1070     {
    1071         RTPrintf("Failed to start the HGCM service.\n");
    1072         return 1;
    1073     }
    1074     if (RT_FAILURE(testSetPropsHost(&svcTable)))
    1075         return 1;
    1076     if (RT_FAILURE(testEnumPropsHost(&svcTable)))
    1077         return 1;
    1078     /* Set up the asynchronous notification test */
    1079     if (RT_FAILURE(setupAsyncNotification(&svcTable)))
    1080         return 1;
    1081     if (RT_FAILURE(testSetProp(&svcTable)))
    1082         return 1;
    1083     RTPrintf("Checking the data returned by the asynchronous notification call.\n");
    1084     /* Our previous notification call should have completed by now. */
    1085     if (RT_FAILURE(testAsyncNotification(&svcTable)))
    1086         return 1;
    1087     if (RT_FAILURE(testDelProp(&svcTable)))
    1088         return 1;
    1089     if (RT_FAILURE(testGetProp(&svcTable)))
    1090         return 1;
    1091     if (RT_FAILURE(testGetNotification(&svcTable)))
    1092         return 1;
    1093     if (RT_FAILURE(svcTable.pfnUnload(svcTable.pvService)))
    1094     {
    1095         RTPrintf("Failed to unload the HGCM service.\n");
    1096         return 1;
    1097     }
    1098     if (RT_FAILURE(testSetPropROGuest(&svcTable)))
    1099         return 1;
    1100     if (RT_FAILURE(testDelPropROGuest(&svcTable)))
    1101         return 1;
     1060    testConvertFlags();
     1061    test2();
     1062    test3();
     1063    test4();
    11021064
    11031065    return RTTestSummaryAndDestroy(g_hTest);
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