VirtualBox

Ignore:
Timestamp:
Nov 6, 2008 1:48:05 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38926
Message:

HostServices/GuestProperties: added guest notification querying

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/Makefile.kmk

    r13574 r13916  
    3737        $(PATH_TOOL_$(VBOX_VCC_TOOL)_ATLMFC_INC) \
    3838        $(VBOX_PATH_SDK)
     39# For now!
     40VBoxGuestPropSvc_CXXFLAGS.win = -EHsc
    3941
    4042VBoxGuestPropSvc_SOURCES = \
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r13837 r13916  
    4646#include <VBox/HostServices/GuestPropertySvc.h>
    4747
    48 #include <memory>  /* for auto_ptr */
    49 #include <string>
    50 #include <list>
    51 
     48#include <VBox/log.h>
    5249#include <iprt/err.h>
    5350#include <iprt/assert.h>
     
    5956#include <iprt/req.h>
    6057#include <iprt/thread.h>
    61 #include <VBox/log.h>
    62 
    63 /*******************************************************************************
    64 *   Internal functions                                                         *
    65 *******************************************************************************/
    66 /** Extract a pointer value from an HGCM parameter structure */
    67 static int VBoxHGCMParmPtrGet (VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
    68 {
    69     if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
    70     {
    71         *ppv = pParm->u.pointer.addr;
    72         *pcb = pParm->u.pointer.size;
    73         return VINF_SUCCESS;
    74     }
    75 
    76     return VERR_INVALID_PARAMETER;
    77 }
    78 
    79 /** Extract a constant pointer value from an HGCM parameter structure */
    80 static int VBoxHGCMParmPtrConstGet (VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb)
    81 {
    82     if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
    83     {
    84         *ppv = pParm->u.pointer.addr;
    85         *pcb = pParm->u.pointer.size;
    86         return VINF_SUCCESS;
    87     }
    88 
    89     return VERR_INVALID_PARAMETER;
    90 }
    91 
    92 /** Set a uint32_t value to an HGCM parameter structure */
    93 static void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32)
    94 {
    95     pParm->type = VBOX_HGCM_SVC_PARM_32BIT;
    96     pParm->u.uint32 = u32;
    97 }
    98 
    99 /** Set a uint64_t value to an HGCM parameter structure */
    100 static void VBoxHGCMParmUInt64Set (VBOXHGCMSVCPARM *pParm, uint64_t u64)
    101 {
    102     pParm->type = VBOX_HGCM_SVC_PARM_64BIT;
    103     pParm->u.uint64 = u64;
    104 }
    105 
    106 /** Set a pointer value to an HGCM parameter structure */
    107 static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
    108 {
    109     pParm->type = VBOX_HGCM_SVC_PARM_PTR;
    110     pParm->u.pointer.addr = pv;
    111     pParm->u.pointer.size = cb;
    112 }
     58
     59#include <memory>  /* for auto_ptr */
     60#include <string>
     61#include <list>
    11362
    11463namespace guestProp {
     
    13584        /** The property flags */
    13685        uint32_t mFlags;
     86
     87        /** Default constructor */
     88        Property() : mName(""), mValue(""), mTimestamp(0), mFlags(NILFLAG) {}
    13789        /** Constructor with const char * */
    13890        Property(const char *pcszName, const char *pcszValue,
     
    150102    /** The property list */
    151103    PropertyList mProperties;
     104    /** The list of property changes for guest notifications */
     105    PropertyList mGuestNotifications;
    152106    /** @todo we should have classes for thread and request handler thread */
    153107    /** Queue of outstanding property change notifications */
     
    259213    int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest);
    260214    int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    261     void notifyHost(const char *pszProperty);
     215    int getNotification(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     216    void doNotifications(const char *pszProperty, uint64_t u64Timestamp);
    262217    static DECLCALLBACK(int) reqNotify(PFNHGCMSVCEXT pfnCallback,
    263218                                       void *pvData, char *pszName,
     
    310265     * a string terminator.
    311266     */
    312     int rc = RTStrValidateEncodingEx(pszName, RT_MIN(cbName, (uint32_t) MAX_NAME_LEN),
    313                                      RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     267    int rc = VINF_SUCCESS;
    314268    if (RT_SUCCESS(rc) && (cbName < 2))
    315269        rc = VERR_INVALID_PARAMETER;
     270    if (RT_SUCCESS(rc))
     271        rc = RTStrValidateEncodingEx(pszName, RT_MIN(cbName, (uint32_t) MAX_NAME_LEN),
     272                                     RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
    316273
    317274    LogFlowFunc(("returning %Rrc\n", rc));
     
    335292    /*
    336293     * Validate the value, checking that it's proper UTF-8 and has
    337      * a string terminator. Don't pass a 0 length request to the
    338      * validator since it won't find any '\0' then.
    339      */
    340     int rc = VINF_SUCCESS;
    341     if (cbValue)
     294     * a string terminator.
     295     */
     296    int rc = VINF_SUCCESS;
     297    if (RT_SUCCESS(rc) && (cbValue < 2))
     298        rc = VERR_INVALID_PARAMETER;
     299    if (RT_SUCCESS(rc))
    342300        rc = RTStrValidateEncodingEx(pszValue, RT_MIN(cbValue, (uint32_t) MAX_VALUE_LEN),
    343301                                     RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     
    368326     */
    369327    if (   (cParms != 4)
    370         || RT_FAILURE(VBoxHGCMParmPtrGet (&paParms[0], (void **) &ppNames, &cbDummy))
    371         || RT_FAILURE(VBoxHGCMParmPtrGet (&paParms[1], (void **) &ppValues, &cbDummy))
    372         || RT_FAILURE(VBoxHGCMParmPtrGet (&paParms[2], (void **) &pTimestamps, &cbDummy))
    373         || RT_FAILURE(VBoxHGCMParmPtrGet (&paParms[3], (void **) &ppFlags, &cbDummy))
     328        || RT_FAILURE(paParms[0].getPointer ((void **) &ppNames, &cbDummy))
     329        || RT_FAILURE(paParms[1].getPointer ((void **) &ppValues, &cbDummy))
     330        || RT_FAILURE(paParms[2].getPointer ((void **) &pTimestamps, &cbDummy))
     331        || RT_FAILURE(paParms[3].getPointer ((void **) &ppFlags, &cbDummy))
    374332        )
    375333        rc = VERR_INVALID_PARAMETER;
     
    464422     */
    465423    LogFlowThisFunc(("\n"));
    466     if (   (cParms != 4)  /* Hardcoded value as the next lines depend on it. */
    467         || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)    /* name */
    468         || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR)    /* buffer */
     424    if (   cParms != 4  /* Hardcoded value as the next lines depend on it. */
     425        || RT_FAILURE (paParms[0].getPointer ((const void **) &pcszName, &cchName))    /* name */
     426        || RT_FAILURE (paParms[1].getPointer ((void **) &pchBuf, &cchBuf))    /* buffer */
    469427       )
    470428        rc = VERR_INVALID_PARAMETER;
    471     if (RT_SUCCESS(rc))
    472         rc = VBoxHGCMParmPtrConstGet(&paParms[0], (const void **) &pcszName, &cchName);
    473     if (RT_SUCCESS(rc))
    474         rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf);
    475429    if (RT_SUCCESS(rc))
    476430        rc = validateName(pcszName, cchName);
     
    500454    {
    501455        cchBufActual = it->mValue.size() + 1 + cchFlags;
    502         VBoxHGCMParmUInt32Set(&paParms[3], cchBufActual);
     456        paParms[3].setUInt32 (cchBufActual);
    503457    }
    504458    if (RT_SUCCESS(rc) && (cchBufActual > cchBuf))
     
    510464        pchBuf[it->mValue.size()] = '\0'; /* Terminate the value */
    511465        strcpy(pchBuf + it->mValue.size() + 1, szFlags);
    512         VBoxHGCMParmUInt64Set(&paParms[2], it->mTimestamp);
     466        paParms[2].setUInt64 (it->mTimestamp);
    513467    }
    514468
     
    540494    uint32_t cchName, cchValue, cchFlags = 0;
    541495    uint32_t fFlags = NILFLAG;
     496    RTTIMESPEC time;
     497    uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time));
    542498
    543499    LogFlowThisFunc(("\n"));
     
    553509    if (   RT_SUCCESS(rc)
    554510        && (   (cParms < 2) || (cParms > 3)  /* Hardcoded value as the next lines depend on it. */
    555             || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[0],
    556                    (const void **) &pcszName, &cchName)) /* name */
    557             || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[1],
    558                    (const void **) &pcszValue, &cchValue)) /* value */
     511            || RT_FAILURE(paParms[0].getPointer ((const void **) &pcszName,
     512                                                 &cchName)) /* name */
     513            || RT_FAILURE(paParms[1].getPointer ((const void **) &pcszValue,
     514                                                 &cchValue)) /* value */
    559515            || (   (3 == cParms)
    560                 && RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[2],
    561                        (const void **) &pcszFlags, &cchFlags)) /* flags */
     516                && RT_FAILURE(paParms[2].getPointer ((const void **) &pcszFlags,
     517                                                     &cchFlags)) /* flags */
    562518               )
    563519           )
     
    602558    if (RT_SUCCESS(rc))
    603559    {
    604         RTTIMESPEC time;
    605         uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time));
    606560        if (found)
    607561        {
     
    621575        // if (isGuest)  /* Notify the host even for properties that the host
    622576        //                * changed.  Less efficient, but ensures consistency. */
    623             notifyHost(pcszName);
     577            doNotifications(pcszName, u64TimeNano);
    624578        Log2(("Set string %s, rc=%Rrc, value=%s\n", pcszName, rc, pcszValue));
    625579    }
     
    651605     */
    652606    if (   (cParms != 1)  /* Hardcoded value as the next lines depend on it. */
    653         || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[0],
    654                (const void **) &pcszName, &cbName))  /* name */
     607        || RT_FAILURE(paParms[0].getPointer ((const void **) &pcszName,
     608                                             &cbName))  /* name */
    655609       )
    656610        rc = VERR_INVALID_PARAMETER;
     
    682636    if (RT_SUCCESS(rc) && found)
    683637    {
     638        RTTIMESPEC time;
     639        uint64_t u64Timestamp = RTTimeSpecGetNano(RTTimeNow(&time));
    684640        mProperties.erase(it);
    685641        // if (isGuest)  /* Notify the host even for properties that the host
    686642        //                * changed.  Less efficient, but ensures consistency. */
    687             notifyHost(pcszName);
     643            doNotifications(pcszName, u64Timestamp);
    688644    }
    689645    LogFlowThisFunc(("rc = %Rrc\n", rc));
     
    711667    LogFlowThisFunc(("\n"));
    712668    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
    713         || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[0],
    714                (const void **) &pcchPatterns, &cchPatterns))  /* patterns */
    715         || RT_FAILURE(VBoxHGCMParmPtrGet(&paParms[1],
    716                (void **) &pchBuf, &cchBuf))  /* return buffer */
     669        || RT_FAILURE(paParms[0].getPointer ((const void **) &pcchPatterns,
     670                                             &cchPatterns))  /* patterns */
     671        || RT_FAILURE(paParms[1].getPointer ((void **) &pchBuf, &cchBuf))  /* return buffer */
    717672       )
    718673        rc = VERR_INVALID_PARAMETER;
     
    777732    if (RT_SUCCESS(rc))
    778733    {
    779         VBoxHGCMParmUInt32Set(&paParms[2], buffer.size());
     734        paParms[2].setUInt32 (buffer.size());
    780735        /* Copy the memory if it fits into the guest buffer */
    781736        if (buffer.size() <= cchBuf)
     
    788743
    789744/**
    790  * Notify the service owner that a property has been added/deleted/changed
    791  * @param pszProperty the name of the property which has changed
     745 * Get the next guest notification.
     746 *
     747 * @returns iprt status value
     748 * @param   cParms  the number of HGCM parameters supplied
     749 * @param   paParms the array of HGCM parameters
     750 * @thread  HGCM
     751 */
     752int Service::getNotification(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     753{
     754    int rc = VINF_SUCCESS;
     755    char *pchBuf;
     756    uint32_t cchBuf = 0;
     757    uint64_t u64Timestamp;
     758    bool warn = false;
     759
     760    /*
     761     * Get the HGCM function arguments and perform basic verification.
     762     */
     763    LogFlowThisFunc(("\n"));
     764    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
     765        || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp))  /* timestamp */
     766        || RT_FAILURE(paParms[1].getPointer ((void **) &pchBuf, &cchBuf))  /* return buffer */
     767        || cchBuf < 1
     768       )
     769        rc = VERR_INVALID_PARAMETER;
     770
     771    /*
     772     * Find the change to notify of.
     773     */
     774    Property next;
     775    /* Return the oldest notification if no timestamp was specified. */
     776    if (RT_SUCCESS(rc) && !mGuestNotifications.empty() && u64Timestamp == 0)
     777        next = mGuestNotifications.front();
     778    /* Only search if the guest hasn't seen the most recent notification. */
     779    else if (   RT_SUCCESS(rc)
     780             && !mGuestNotifications.empty()
     781             && mGuestNotifications.back().mTimestamp != u64Timestamp)
     782    {
     783        /* We count backwards, as the guest should normally be querying the
     784         * most recent events. */
     785        PropertyList::const_reverse_iterator it = mGuestNotifications.rbegin();
     786        for ( ;    it != mGuestNotifications.rend()
     787                && it->mTimestamp != u64Timestamp;
     788             ++it
     789            ) {}
     790        /* Warn if the timestamp was not found. */
     791        if (it == mGuestNotifications.rend())
     792            warn = true;
     793        /* This is a reverse iterator, so --it goes up the list. */
     794        --it;
     795        next = *it;
     796    }
     797
     798    /*
     799     * Format the data to write to the buffer.
     800     */
     801    std::string buffer;
     802    if (RT_SUCCESS(rc))
     803    {
     804        char szFlags[MAX_FLAGS_LEN];
     805        rc = writeFlags(next.mFlags, szFlags);
     806        if (RT_SUCCESS(rc))
     807        {
     808            buffer += next.mName;
     809            buffer += '\0';
     810            buffer += next.mValue;
     811            buffer += '\0';
     812            buffer += szFlags;
     813            buffer += '\0';
     814            u64Timestamp = next.mTimestamp;
     815        }
     816    }
     817
     818    /*
     819     * Write out the data.
     820     */
     821    paParms[0].setUInt64(u64Timestamp);
     822    paParms[2].setUInt32(buffer.size());
     823    if (RT_SUCCESS(rc) && buffer.size() <= cchBuf)
     824        buffer.copy(pchBuf, cchBuf);
     825    else if (RT_SUCCESS(rc))
     826        rc = VERR_BUFFER_OVERFLOW;
     827    if (RT_SUCCESS(rc) && warn)
     828        rc = VWRN_NOT_FOUND;
     829    return rc;
     830}
     831
     832/**
     833 * Notify the service owner and the guest that a property has been
     834 * added/deleted/changed
     835 * @param pszProperty  the name of the property which has changed
     836 * @param u64Timestamp the time at which the change took place
    792837 * @note this call allocates memory which the reqNotify request is expected to
    793838 *       free again, using RTStrFree().
     
    795840 * @thread  HGCM service
    796841 */
    797 void Service::notifyHost(const char *pszProperty)
    798 {
    799 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     842void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp)
     843{
    800844    char szFlags[MAX_FLAGS_LEN];
    801845    char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
    802846    int rc = VINF_SUCCESS;
    803847
    804     if (NULL == mpfnHostCallback)
    805         return;  /* Nothing to do. */
     848    AssertPtrReturnVoid(pszProperty);
    806849    PropertyList::const_iterator it;
    807850    bool found = false;
     
    814857            }
    815858    /*
    816      * First case: if the property exists then send the host its current value
    817      */
    818     if (found)
    819     {
     859     * First case: if the property exists then send its current value
     860     */
     861    if (found && mpfnHostCallback != NULL)
     862    {
     863#ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     864        /* Send out a host notification */
    820865        rc = writeFlags(it->mFlags, szFlags);
    821866        if (RT_SUCCESS(rc))
     
    831876                             (uint32_t) RT_HIDWORD(it->mTimestamp),
    832877                             (uint32_t) RT_LODWORD(it->mTimestamp), pszFlags);
    833     }
    834     else
     878#endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
     879    }
     880    if (found)
     881    {
     882        /* Add the change to the queue for guest notifications */
     883        if (RT_SUCCESS(rc))
     884        {
     885            try
     886            {
     887                mGuestNotifications.push_back(*it);
     888            }
     889            catch (std::bad_alloc)
     890            {
     891                rc = VERR_NO_MEMORY;
     892            }
     893        }
     894    }
     895
    835896    /*
    836897     * Second case: if the property does not exist then send the host an empty
    837898     * value
    838899     */
    839     {
     900    if (!found && mpfnHostCallback != NULL)
     901    {
     902#ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     903        /* Send out a host notification */
    840904        rc = RTStrDupEx(&pszName, pszProperty);
    841905        if (RT_SUCCESS(rc))
    842906            rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT,
    843907                             (PFNRT)Service::reqNotify, 7, mpfnHostCallback,
    844                              mpvHostData, pszName, NULL, 0, 0, NULL);
    845     }
     908                             mpvHostData, pszName, NULL,
     909                             RT_HIDWORD(u64Timestamp),
     910                             RT_LODWORD(u64Timestamp), NULL);
     911#endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
     912    }
     913    if (!found)
     914    {
     915        /* Add the change to the queue for guest notifications */
     916        if (RT_SUCCESS(rc))
     917        {
     918            try
     919            {
     920                mGuestNotifications.push_back(Property(pszProperty, "",
     921                                                       u64Timestamp, NILFLAG)
     922                                             );
     923            }
     924            catch (std::bad_alloc)
     925            {
     926                rc = VERR_NO_MEMORY;
     927            }
     928        }
     929    }
     930    if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS)
     931        mGuestNotifications.pop_front();
    846932    if (RT_FAILURE(rc)) /* clean up if we failed somewhere */
    847933    {
     
    850936        RTStrFree(pszFlags);
    851937    }
    852 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    853938}
    854939
     
    9321017                LogFlowFunc(("ENUM_PROPS\n"));
    9331018                rc = enumProps(cParms, paParms);
     1019                break;
     1020
     1021            /* The guest wishes to get the next property notification */
     1022            case GET_NOTIFICATION:
     1023                LogFlowFunc(("GET_NOTIFICATION\n"));
     1024                rc = getNotification(cParms, paParms);
    9341025                break;
    9351026
  • trunk/src/VBox/HostServices/GuestProperties/testcase/Makefile.kmk

    r13779 r13916  
    4242  OTHERS += $(PATH_tstGuestPropSvc)/tstGuestPropSvc.run
    4343$$(PATH_tstGuestPropSvc)/tstGuestPropSvc.run: $$(INSTARGET_tstGuestPropSvc)
    44         $(INSTARGET_tstGuestPropSvc) quiet
     44        export VBOX_LOG_DEST=nofile; $(INSTARGET_tstGuestPropSvc) quiet
    4545        $(QUIET)$(APPEND) -t "$@" "done"
    4646 endif
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r13781 r13916  
    3232extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
    3333
    34 /** Set a pointer value to an HGCM parameter structure */
    35 static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
    36 {
    37     pParm->type = VBOX_HGCM_SVC_PARM_PTR;
    38     pParm->u.pointer.addr = pv;
    39     pParm->u.pointer.size = cb;
    40 }
    41 
    42 /** Extract a uint64_t value from an HGCM parameter structure */
    43 static int VBoxHGCMParmUInt32Get (VBOXHGCMSVCPARM *pParm, uint32_t *pu32Value)
    44 {
    45     if (pParm->type == VBOX_HGCM_SVC_PARM_32BIT)
    46     {
    47         *pu32Value = pParm->u.uint32;
    48         return VINF_SUCCESS;
    49     }
    50 
    51     return VERR_INVALID_PARAMETER;
    52 }
    53 
    54 /** Extract a uint64_t value from an HGCM parameter structure */
    55 static int VBoxHGCMParmUInt64Get (VBOXHGCMSVCPARM *pParm, uint64_t *pu64Value)
    56 {
    57     if (pParm->type == VBOX_HGCM_SVC_PARM_64BIT)
    58     {
    59         *pu64Value = pParm->u.uint64;
    60         return VINF_SUCCESS;
    61     }
    62 
    63     return VERR_INVALID_PARAMETER;
    64 }
    65 
    6634/** Simple call handle structure for the guest call completion callback */
    6735struct VBOXHGCMCALLHANDLE_TYPEDEF
     
    250218    {
    251219        VBOXHGCMSVCPARM paParms[4];
    252         VBoxHGCMParmPtrSet(&paParms[0], (void *) apcszNameBlock, 0);
    253         VBoxHGCMParmPtrSet(&paParms[1], (void *) apcszValueBlock, 0);
    254         VBoxHGCMParmPtrSet(&paParms[2], (void *) au64TimestampBlock, 0);
    255         VBoxHGCMParmPtrSet(&paParms[3], (void *) apcszFlagsBlock, 0);
     220        paParms[0].setPointer ((void *) apcszNameBlock, 0);
     221        paParms[1].setPointer ((void *) apcszValueBlock, 0);
     222        paParms[2].setPointer ((void *) au64TimestampBlock, 0);
     223        paParms[3].setPointer ((void *) apcszFlagsBlock, 0);
    256224        rc = ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4,
    257225                                 paParms);
     
    370338        char buffer[2048];
    371339        VBOXHGCMSVCPARM paParms[3];
    372         VBoxHGCMParmPtrSet(&paParms[0],
    373                            (void *) enumStrings[i].pcszPatterns,
    374                            enumStrings[i].cchPatterns);
    375         VBoxHGCMParmPtrSet(&paParms[1],
    376                            (void *) buffer,
    377                            enumStrings[i].cchBuffer - 1);
     340        paParms[0].setPointer ((void *) enumStrings[i].pcszPatterns,
     341                               enumStrings[i].cchPatterns);
     342        paParms[1].setPointer ((void *) buffer,
     343                               enumStrings[i].cchBuffer - 1);
    378344        AssertBreakStmt(sizeof(buffer) > enumStrings[i].cchBuffer,
    379345                        rc = VERR_INTERNAL_ERROR);
     
    391357            {
    392358                uint32_t cchBufferActual;
    393                 rc = VBoxHGCMParmUInt32Get(&paParms[2], &cchBufferActual);
     359                rc = paParms[2].getUInt32 (&cchBufferActual);
    394360                if (RT_SUCCESS(rc) && cchBufferActual != enumStrings[i].cchBuffer)
    395361                {
     
    403369        if (RT_SUCCESS(rc))
    404370        {
    405             VBoxHGCMParmPtrSet(&paParms[1], (void *) buffer,
    406                                enumStrings[i].cchBuffer);
     371            paParms[1].setPointer ((void *) buffer, enumStrings[i].cchBuffer);
    407372            rc = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST,
    408373                                      3, paParms);
     
    495460        strncat(szValue, setProperties[i].pcszValue, sizeof(szValue));
    496461        strncat(szFlags, setProperties[i].pcszFlags, sizeof(szFlags));
    497         VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
    498         VBoxHGCMParmPtrSet(&paParms[1], szValue, strlen(szValue) + 1);
    499         VBoxHGCMParmPtrSet(&paParms[2], szFlags, strlen(szFlags) + 1);
     462        paParms[0].setPointer (szName, strlen(szName) + 1);
     463        paParms[1].setPointer (szValue, strlen(szValue) + 1);
     464        paParms[2].setPointer (szFlags, strlen(szFlags) + 1);
    500465        if (setProperties[i].isHost)
    501466            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     
    567532        char szName[MAX_NAME_LEN] = "";
    568533        strncat(szName, delProperties[i].pcszName, sizeof(szName));
    569         VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
     534        paParms[0].setPointer (szName, strlen(szName) + 1);
    570535        if (delProperties[i].isHost)
    571536            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     
    644609                        rc = VERR_INTERNAL_ERROR);
    645610        strncat(szName, getProperties[i].pcszName, sizeof(szName));
    646         VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
    647         VBoxHGCMParmPtrSet(&paParms[1], szBuffer, sizeof(szBuffer));
     611        paParms[0].setPointer (szName, strlen(szName) + 1);
     612        paParms[1].setPointer (szBuffer, sizeof(szBuffer));
    648613        rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4,
    649614                                  paParms);
     
    663628        {
    664629            uint32_t u32ValueLen;
    665             rc = VBoxHGCMParmUInt32Get(&paParms[3], &u32ValueLen);
     630            rc = paParms[3].getUInt32 (&u32ValueLen);
    666631            if (RT_FAILURE(rc))
    667632                RTPrintf("Failed to get the size of the output buffer for property '%s'\n",
     
    680645            {
    681646                uint64_t u64Timestamp;
    682                 rc = VBoxHGCMParmUInt64Get(&paParms[2], &u64Timestamp);
     647                rc = paParms[2].getUInt64 (&u64Timestamp);
    683648                if (RT_FAILURE(rc))
    684649                    RTPrintf("Failed to get the timestamp for property '%s'\n",
     
    699664}
    700665
     666/** Array of properties for testing GET_PROP_HOST. */
     667static const struct
     668{
     669    /** Buffer returned */
     670    const char *pchBuffer;
     671    /** What size should the buffer be? */
     672    uint32_t cchBuffer;
     673}
     674getNotifications[] =
     675{
     676    { "Red\0Stop!\0TRANSIENT", sizeof("Red\0Stop!\0TRANSIENT") },
     677    { "Amber\0Caution!\0", sizeof("Amber\0Caution!\0") },
     678    { "Green\0Go!\0READONLY", sizeof("Green\0Go!\0READONLY") },
     679    { "Blue\0What on earth...?\0", sizeof("Blue\0What on earth...?\0") },
     680    { "Red\0\0", sizeof("Red\0\0") },
     681    { "Amber\0\0", sizeof("Amber\0\0") },
     682    { NULL, 0 }
     683};
     684
     685/**
     686 * Test the GET_NOTIFICATION function.
     687 * @returns iprt status value to indicate whether the test went as expected.
     688 * @note    prints its own diagnostic information to stdout.
     689 */
     690int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
     691{
     692    int rc = VINF_SUCCESS;
     693    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
     694    char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
     695
     696    RTPrintf("Testing the GET_NOTIFICATION call.\n");
     697    uint64_t u64Timestamp = 0;
     698    uint32_t u32Size = 0;
     699    VBOXHGCMSVCPARM paParms[3];
     700
     701    /* Test "buffer too small" */
     702    paParms[0].setUInt64 (u64Timestamp);
     703    paParms[1].setPointer ((void *) chBuffer, getNotifications[0].cchBuffer - 1);
     704    pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
     705                    GET_NOTIFICATION, 3, paParms);
     706    if (   callHandle.rc != VERR_BUFFER_OVERFLOW
     707        || RT_FAILURE(paParms[2].getUInt32 (&u32Size))
     708        || u32Size != getNotifications[0].cchBuffer
     709       )
     710    {
     711        RTPrintf("Getting notification for property '%s' with a too small buffer did not fail correctly.\n",
     712                 getNotifications[0].pchBuffer);
     713        rc = VERR_UNRESOLVED_ERROR;
     714    }
     715
     716    /* Test successful notification queries */
     717    for (unsigned i = 0; RT_SUCCESS(rc) && (getNotifications[i].pchBuffer != NULL);
     718         ++i)
     719    {
     720        paParms[0].setUInt64 (u64Timestamp);
     721        paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer));
     722        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
     723                        GET_NOTIFICATION, 3, paParms);
     724        if (   RT_FAILURE(callHandle.rc)
     725            || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp))
     726            || RT_FAILURE(paParms[2].getUInt32 (&u32Size))
     727            || u32Size != getNotifications[i].cchBuffer
     728            || memcmp(chBuffer, getNotifications[i].pchBuffer, u32Size) != 0
     729           )
     730        {
     731            RTPrintf("Failed to get notification for property '%s'.\n",
     732                     getNotifications[i].pchBuffer);
     733            rc = VERR_UNRESOLVED_ERROR;
     734        }
     735    }
     736
     737    /* Test when no new events are available */
     738    pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
     739                    GET_NOTIFICATION, 3, paParms);
     740    if (   RT_FAILURE(callHandle.rc)
     741        || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp))
     742        || u64Timestamp != 0
     743       )
     744    {
     745        RTPrintf("Failed to signal properly that no new notifications are available.\n");
     746        rc = VERR_UNRESOLVED_ERROR;
     747    }
     748
     749    /* Test a query with an unknown timestamp */
     750    paParms[0].setUInt64 (1);
     751    paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer));
     752    if (RT_SUCCESS(rc))
     753        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
     754                        GET_NOTIFICATION, 3, paParms);
     755    if (   RT_SUCCESS(rc)
     756        && (   callHandle.rc != VWRN_NOT_FOUND
     757            || RT_FAILURE(callHandle.rc)
     758            || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp))
     759            || RT_FAILURE(paParms[2].getUInt32 (&u32Size))
     760            || u32Size != getNotifications[0].cchBuffer
     761            || memcmp(chBuffer, getNotifications[0].pchBuffer, u32Size) != 0
     762           )
     763       )
     764    {
     765        RTPrintf("Problem getting notification for property '%s' with unknown timestamp, rc=%Rrc.\n",
     766                 getNotifications[0].pchBuffer, callHandle.rc);
     767        rc = VERR_UNRESOLVED_ERROR;
     768    }
     769    return rc;
     770}
     771
     772/**
     773 * Test the GET_NOTIFICATION function when no notifications are available.
     774 * @returns iprt status value to indicate whether the test went as expected.
     775 * @note    prints its own diagnostic information to stdout.
     776 */
     777int testNoNotifications(VBOXHGCMSVCFNTABLE *pTable)
     778{
     779    int rc = VINF_SUCCESS;
     780    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
     781    char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
     782
     783    RTPrintf("Testing the GET_NOTIFICATION call when no notifications are available.\n");
     784    uint64_t u64Timestamp = 0;
     785    uint32_t u32Size = 0;
     786    VBOXHGCMSVCPARM paParms[3];
     787
     788    paParms[0].setUInt64 (u64Timestamp);
     789    paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer));
     790    pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
     791                    GET_NOTIFICATION, 3, paParms);
     792    if (   RT_FAILURE(callHandle.rc)
     793        || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp))
     794        || u64Timestamp != 0
     795       )
     796    {
     797        RTPrintf("Failed to signal properly that no new notifications are available.\n");
     798        rc = VERR_UNRESOLVED_ERROR;
     799    }
     800    return rc;
     801}
     802
    701803int main(int argc, char **argv)
    702804{
     
    717819    if (RT_FAILURE(testEnumPropsHost(&svcTable)))
    718820        return 1;
     821    if (RT_FAILURE(testNoNotifications(&svcTable)))
     822        return 1;
    719823    if (RT_FAILURE(testSetProp(&svcTable)))
    720824        return 1;
     
    723827    if (RT_FAILURE(testGetProp(&svcTable)))
    724828        return 1;
     829    if (RT_FAILURE(testGetNotification(&svcTable)))
     830        return 1;
    725831    RTPrintf("tstGuestPropSvc: SUCCEEDED.\n");
    726832    return 0;
Note: See TracChangeset for help on using the changeset viewer.

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