VirtualBox

Changeset 10929 in vbox


Ignore:
Timestamp:
Jul 29, 2008 1:23:40 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33777
Message:

HostServices/GuestProperties: added a guest enumeration interface to the service

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestPropertySvc.h

    r10797 r10929  
    199199     * Null-separated array of patterns to match the properties against.
    200200     * (IN pointer)
    201      * If no patterns are given then return all.
     201     * If no patterns are given then return all.  The list is terminated by an
     202     * empty string.
    202203     */
    203204    HGCMFunctionParameter patterns;
    204205    /**
    205      * Null-separated array of strings in which the properties are returned.
    206      * (OUT pointer)
     206     * On success, null-separated array of strings in which the properties are
     207     * returned.  (OUT pointer)
    207208     * The number of strings in the array is always a multiple of four,
    208209     * and in sequences of name, value, timestamp (hexadecimal string) and the
    209      * flags as a comma-separated list in the format "name=value"
     210     * flags as a comma-separated list in the format "name=value".  The list
     211     * is terminated by four empty strings.
    210212     */
    211213    HGCMFunctionParameter strings;
     214    /**
     215     * On success, the size of the returned data.  If the buffer provided is
     216     * too small, the size of buffer needed.  (OUT uint32_t)
     217     */
     218    HGCMFunctionParameter size;
    212219} EnumProperties;
    213220#pragma pack ()
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r10814 r10929  
    5353#include <iprt/assert.h>
    5454#include <iprt/string.h>
     55#include <iprt/mem.h>
     56#include <iprt/autores>
    5557#include <VBox/log.h>
    5658
     
    170172    int setKey(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    171173    int delKey(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     174    int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    172175    void call (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
    173176               void *pvClient, uint32_t eFunction, uint32_t cParms,
     
    178181
    179182/**
     183 * Calculate the length of a string in bytes, excluding the terminator.
     184 * @returns VINF_SUCCESS on success and the length in @a pcch
     185 * @returns VERR_BUFFFER_OVERFLOW if no terminator is found in the first @a cch
     186 *          bytes of the string
     187 * @param   pszString  the string to count
     188 * @param   cch        the maximum length of the string, including terminator
     189 * @param   pcch       where to store the string length on success
     190 * @todo move this into IPRT
     191 */
     192static int svcStrLenEx(const char *pszString, size_t cch, size_t *pcch)
     193{
     194    int rc = VINF_SUCCESS;
     195    void *pvTerm = memchr(pszString, 0, cch);
     196    if (NULL == pvTerm)
     197    {
     198        *pcch = 0;
     199        rc = VERR_BUFFER_OVERFLOW;
     200    }
     201    else
     202        *pcch = reinterpret_cast<char *>(pvTerm) - pszString;
     203    return rc;
     204}
     205
     206
     207/**
    180208 * Checking that the key passed by the guest fits our criteria for a
    181209 * configuration key
     
    198226    rc = RTStrValidateEncodingEx(pszKey, cbKey - 1, 0);
    199227    if (RT_SUCCESS(rc))
    200         /* We want the byte length, not the Utf8 length */
    201         count = strlen(pszKey);
    202     if (RT_SUCCESS(rc) && (count > MAX_NAME_LEN))
    203         rc = VERR_INVALID_PARAMETER;
     228        /* We want to check the byte length, not the Utf8 length */
     229        rc = svcStrLenEx(pszKey, MAX_NAME_LEN + 1, &count);
    204230
    205231    LogFlowFunc(("returning %Rrc\n", rc));
     
    228254    rc = RTStrValidateEncodingEx(pszValue, cbValue - 1, 0);
    229255    if (RT_SUCCESS(rc))
    230         /* We want the byte length, not the Utf8 length */
    231         count = strlen(pszValue);
    232     if (RT_SUCCESS(rc) && (count > MAX_VALUE_LEN))
    233         rc = VERR_INVALID_PARAMETER;
     256        /* We want to check the byte length, not the Utf8 length */
     257        rc = svcStrLenEx(pszValue, MAX_VALUE_LEN + 1, &count);
    234258
    235259    if (RT_SUCCESS(rc))
     
    428452}
    429453
     454/**
     455 * Matches a sample name against a pattern.
     456 *
     457 * @returns True if matches, false if not.
     458 * @param   pszPat      Pattern.
     459 * @param   pszName     Name to match against the pattern.
     460 * @todo move this into IPRT
     461 */
     462static bool matchesSinglePattern(const char *pszPat, const char *pszName)
     463{
     464    /* ASSUMES ASCII */
     465    for (;;)
     466    {
     467        char chPat = *pszPat;
     468        switch (chPat)
     469        {
     470            default:
     471                if (*pszName != chPat)
     472                    return false;
     473                break;
     474
     475            case '*':
     476            {
     477                while ((chPat = *++pszPat) == '*' || chPat == '?')
     478                    /* nothing */;
     479
     480                for (;;)
     481                {
     482                    char ch = *pszName++;
     483                    if (    ch == chPat
     484                        &&  (   !chPat
     485                             || matchesSinglePattern(pszPat + 1, pszName)))
     486                        return true;
     487                    if (!ch)
     488                        return false;
     489                }
     490                /* won't ever get here */
     491                break;
     492            }
     493
     494            case '?':
     495                if (!*pszName)
     496                    return false;
     497                break;
     498
     499            case '\0':
     500                return !*pszName;
     501        }
     502        pszName++;
     503        pszPat++;
     504    }
     505    return true;
     506}
     507
     508
     509/* Checks to see if the given string matches against one of the patterns in
     510 * the list. */
     511static bool matchesPattern(const char *paszPatterns, size_t cchPatterns,
     512                           const char *pszString)
     513{
     514    size_t iOffs = 0;
     515    /* If the first pattern in the list is empty, treat it as "match all". */
     516    bool matched = (cchPatterns > 0) && (0 == *paszPatterns) ? true : false;
     517    while ((iOffs < cchPatterns) && !matched)
     518    {
     519        size_t cchCurrent;
     520        if (   RT_SUCCESS(svcStrLenEx(paszPatterns + iOffs,
     521                                      cchPatterns - iOffs, &cchCurrent))
     522            && (cchCurrent > 0)
     523           )
     524        {
     525            matched = matchesSinglePattern(paszPatterns + iOffs, pszString);
     526            iOffs += cchCurrent + 1;
     527        }
     528        else
     529            iOffs = cchPatterns;
     530    }
     531    return matched;
     532}
     533
     534
     535/**
     536 * Enumerate guest properties by mask, checking the validity
     537 * of the arguments passed.
     538 *
     539 * @returns iprt status value
     540 * @param   cParms  the number of HGCM parameters supplied
     541 * @param   paParms the array of HGCM parameters
     542 * @thread  HGCM
     543 */
     544int Service::enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     545{
     546    /* We reallocate the temporary buffer in which we build up our array in
     547     * increments of size BLOCK: */
     548    enum { BLOCKINCR = (MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN + 2048) % 1024 };
     549    int rc = VINF_SUCCESS;
     550   
     551/*
     552 * Get the HGCM function arguments.
     553 */
     554    char *paszPatterns = NULL, *pchBuf = NULL;
     555    uint32_t cchPatterns, cchBuf;
     556    LogFlowThisFunc(("\n"));
     557    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
     558        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* patterns */
     559        || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR)   /* return buffer */
     560       )
     561        rc = VERR_INVALID_PARAMETER;
     562    if (RT_SUCCESS(rc))
     563        rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &paszPatterns, &cchPatterns);
     564    if (RT_SUCCESS(rc))
     565        rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf);
     566
     567/*
     568 * Start by enumerating all values in the current node into a temporary buffer.
     569 */
     570    RTMemAutoPtr<char> pchTmpBuf;
     571    uint32_t cchTmpBuf = 0, iTmpBuf = 0;
     572    PCFGMLEAF pLeaf = CFGMR3GetFirstValue(mpNode);
     573    while ((pLeaf != NULL) && RT_SUCCESS(rc))
     574    {
     575        /* Reallocate the buffer if it has got too tight */
     576        if (iTmpBuf + BLOCKINCR > cchTmpBuf)
     577        {
     578            cchTmpBuf += BLOCKINCR;
     579            if (!pchTmpBuf.realloc<RTMemRealloc>(cchTmpBuf))
     580                rc = VERR_NO_MEMORY;
     581        }
     582        /* Fetch the name into the buffer and if it matches one of the
     583         * patterns, add its value and an empty timestamp and flags.  If it
     584         * doesn't match, we simply overwrite it in the buffer. */
     585        if (RT_SUCCESS(rc))
     586            rc = CFGMR3GetValueName(pLeaf, pchTmpBuf.get() + iTmpBuf, cchTmpBuf - iTmpBuf);
     587        if (   RT_SUCCESS(rc)
     588            && matchesPattern(paszPatterns, cchPatterns, pchTmpBuf.get() + iTmpBuf)
     589           )
     590        {
     591            int cchName = CFGMR3GetValueNameLen(pLeaf);
     592            rc = CFGMR3QueryString(mpNode, pchTmpBuf.get() + iTmpBuf /* Name */,
     593                                   pchTmpBuf.get() + iTmpBuf + cchName,
     594                                   cchTmpBuf - iTmpBuf - cchName);
     595            if (RT_SUCCESS(rc))
     596            {
     597                /* Only increment if the name matches, otherwise we overwrite
     598                 * it next iteration. */
     599                iTmpBuf += cchName;
     600                int cchValue = strlen(pchTmpBuf.get() + iTmpBuf) + 1;
     601                /* We *do* have enough space left */
     602                *(pchTmpBuf.get() + iTmpBuf + cchValue) = '0';  /* Timestamp */
     603                *(pchTmpBuf.get() + iTmpBuf + cchValue + 1) = 0;
     604                *(pchTmpBuf.get() + iTmpBuf + cchValue + 2) = 0;  /* empty flags */
     605                iTmpBuf += cchValue + 3;
     606            }
     607        }
     608        if (RT_SUCCESS(rc))
     609            pLeaf = CFGMR3GetNextValue(pLeaf);
     610    }
     611    if (RT_SUCCESS(rc))
     612    {
     613        /* The terminator.  We *do* have space left for this. */
     614        *(pchTmpBuf.get() + iTmpBuf) = 0;
     615        *(pchTmpBuf.get() + iTmpBuf + 1) = 0;
     616        *(pchTmpBuf.get() + iTmpBuf + 2) = 0;
     617        *(pchTmpBuf.get() + iTmpBuf + 3) = 0;
     618        iTmpBuf += 4;
     619        VBoxHGCMParmUInt32Set(&paParms[2], iTmpBuf);
     620        /* Copy the memory if it fits into the guest buffer */
     621        if (iTmpBuf <= cchBuf)
     622            memcpy(pchBuf, pchTmpBuf.get(), iTmpBuf);
     623        else
     624            rc = VERR_BUFFER_OVERFLOW;
     625    }
     626    return rc;
     627}
     628
    430629
    431630/**
     
    474673            break;
    475674
     675        case ENUM_PROPS:
     676            LogFlowFunc(("ENUM_PROPS\n"));
     677            rc = enumProps(cParms, paParms);
     678            break;
    476679        default:
    477680            rc = VERR_NOT_IMPLEMENTED;
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