VirtualBox

Changeset 13293

Show
Ignore:
Timestamp:
10/15/08 18:19:36 (3 months ago)
Author:
vboxsync
Message:

HostServices/GuestProperties? and Main: support property flags - the values are not yet checked

Files:

Legend:

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

    r13159 r13293  
    3535#include <VBox/VBoxGuest.h> 
    3636#include <VBox/hgcmsvc.h> 
     37#include <VBox/log.h> 
     38#include <iprt/assert.h> 
     39 
     40#include <string.h> 
     41 
     42#ifdef RT_OS_WINDOWS 
     43# define strncasecmp strnicmp 
     44#endif 
    3745 
    3846/** Everything defined in this file lives in this namespace. */ 
    3947namespace guestProp { 
     48 
     49/****************************************************************************** 
     50* Typedefs, constants and inlines                                             * 
     51******************************************************************************/ 
     52 
     53/** Maximum length for property names */ 
     54enum { MAX_NAME_LEN = 64 }; 
     55/** Maximum length for property values */ 
     56enum { MAX_VALUE_LEN = 128 }; 
     57/** Maximum number of properties per guest */ 
     58enum { MAX_PROPS = 256 }; 
     59 
     60/** 
     61 * The guest property flag values which are currently accepted. 
     62 */ 
     63enum ePropFlags 
     64{ 
     65    NILFLAG    = 0, 
     66    TRANSIENT  = RT_BIT(1), 
     67    HOSTWRITE  = RT_BIT(2), 
     68    GUESTWRITE = RT_BIT(3), 
     69    READONLY   = RT_BIT(4) 
     70}; 
     71 
     72/** 
     73 * A structure to map the guest property flag values to names. I know it is 
     74 * ugly to have constants inline, but it has to be accessible in different 
     75 * modules and it does not seem reasonable to put it into its own library. 
     76 */ 
     77const struct 
     78{ 
     79    /** The flag value */ 
     80    uint32_t fFlag; 
     81    /** And the name of the flag */ 
     82    const char *pcszName; 
     83} flagNames[] = 
     84{ 
     85    { TRANSIENT,  "TRANSIENT" }, 
     86    { HOSTWRITE,  "HOSTWRITE" }, 
     87    { GUESTWRITE, "GUESTWRITE" }, 
     88    { READONLY,   "READONLY" }, 
     89    { NILFLAG,    NULL } 
     90}; 
     91 
     92/** Maximum length for the property flags field */ 
     93enum { MAX_FLAGS_LEN =   sizeof(flagNames[0]) + 2  /* + 2 for ", " */ 
     94                       + sizeof(flagNames[1]) + 2 
     95                       + sizeof(flagNames[2]) + 2 
     96                       + sizeof(flagNames[3]) 
     97     }; 
     98 
     99/** 
     100 * Parse a guest properties flags string for the flags in flagNames. 
     101 * @returns  IPRT status code 
     102 * @returns  VERR_INVALID_PARAM if the flag string is not valid 
     103 * @param    pcszFlags  the flag string to parse 
     104 * @param    pfFlags    where to store the parse result.  May not be NULL. 
     105 * @note     This function is also inline because it must be accessible from 
     106 *           several modules and it does not seem reasonable to put it into 
     107 *           its own library. 
     108 */ 
     109DECLINLINE(int) validateFlags(const char *pcszFlags, uint32_t *pfFlags) 
     110{ 
     111    const char *pcszNext = pcszFlags; 
     112    int rc = VINF_SUCCESS; 
     113    uint32_t fFlags = 0; 
     114    AssertLogRelReturn(VALID_PTR(pfFlags), VERR_INVALID_POINTER); 
     115    AssertLogRelReturn(VALID_PTR(pcszFlags), VERR_INVALID_POINTER); 
     116    while (' ' == *pcszNext) 
     117        ++pcszNext; 
     118    while ((*pcszNext != '\0') && RT_SUCCESS(rc)) 
     119    { 
     120        int i = 0; 
     121        for (; flagNames[i].fFlag != NILFLAG; ++i) 
     122            if (strncasecmp(pcszNext, flagNames[i].pcszName, 
     123                            strlen(flagNames[i].pcszName)) == 0) 
     124                break; 
     125        if (NILFLAG == flagNames[i].fFlag) 
     126            rc = VERR_INVALID_PARAMETER; 
     127        else 
     128        { 
     129            fFlags |= flagNames[i].fFlag; 
     130            pcszNext += strlen(flagNames[i].pcszName); 
     131        } 
     132        while (' ' == *pcszNext) 
     133            ++pcszNext; 
     134        if (',' == *pcszNext) 
     135            ++pcszNext; 
     136        while (' ' == *pcszNext) 
     137            ++pcszNext; 
     138    } 
     139    if (RT_SUCCESS(rc)) 
     140        *pfFlags = fFlags; 
     141    return rc; 
     142} 
     143 
     144/** 
     145 * Write out flags to a string. 
     146 * @returns  IPRT status code 
     147 * @param    fFlags    the flags to write out 
     148 * @param    pszFlags  where to write the flags string.  This must point to 
     149 *                     a buffer of size (at least) MAX_FLAGS_LEN + 1. 
     150 */ 
     151DECLINLINE(int) writeFlags(uint32_t fFlags, char *pszFlags) 
     152{ 
     153    char *pszNext = pszFlags; 
     154    int rc = VINF_SUCCESS; 
     155    AssertLogRelReturn(VALID_PTR(pszFlags), VERR_INVALID_POINTER); 
     156    int i = 0; 
     157    for (; flagNames[i].fFlag != NILFLAG; ++i) 
     158    { 
     159        if (fFlags & flagNames[i].fFlag) 
     160        { 
     161            strcpy(pszNext, flagNames[i].pcszName); 
     162            pszNext += strlen(flagNames[i].pcszName); 
     163            fFlags &= ~flagNames[i].fFlag; 
     164            if ((flagNames[i + 1].fFlag != NILFLAG) && (fFlags != NILFLAG)) 
     165            { 
     166                strcpy(pszNext, ", "); 
     167                pszNext += 2; 
     168            } 
     169        } 
     170    } 
     171    *pszNext = '\0'; 
     172    if (fFlags != NILFLAG) 
     173        rc = VERR_INVALID_PARAMETER;  /* But pszFlags will still be set right. */ 
     174    return rc; 
     175} 
    40176 
    41177/* 
     
    111247}; 
    112248 
    113 /** Maximum length for property names */ 
    114 enum { MAX_NAME_LEN = 64 }; 
    115 /** Maximum length for property values */ 
    116 enum { MAX_VALUE_LEN = 128 }; 
    117 /** Maximum length for the property flags field */ 
    118 enum { MAX_FLAGS_LEN = 128 }; 
    119 /** Maximum number of properties per guest */ 
    120 enum { MAX_PROPS = 256 }; 
    121  
    122249/** 
    123250 * HGCM parameter structures.  Packing is explicitly defined as this is a wire format. 
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r13212 r13293  
    327327 
    328328    LogFlowThisFunc(("\n")); 
     329    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */ 
    329330    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */ 
    330331        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* name */ 
     
    373374    uint32_t cchName, cchBuf; 
    374375    size_t cchValue, cchFlags, cchBufActual; 
     376    char szFlags[MAX_FLAGS_LEN + 1]; 
     377    uint32_t fFlags; 
    375378 
    376379    /* 
     
    378381     */ 
    379382    LogFlowThisFunc(("\n")); 
     383    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */ 
    380384    if (   (cParms != 4)  /* Hardcoded value as the next lines depend on it. */ 
    381385        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)    /* name */ 
     
    389393    if (RT_SUCCESS(rc)) 
    390394        rc = validateName(pszName, cchName); 
    391     /* Get the value size */ 
    392     if (RT_SUCCESS(rc)) 
    393         rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue); 
    394395 
    395396    /* 
    396397     * Read and set the values we will return 
    397398     */ 
    398     /* Get the flags size */ 
    399     cchFlags = 1;  /* Empty string if no flags set. */ 
    400     if (RT_SUCCESS(rc) && (mpFlagsNode != NULL)) 
    401         CFGMR3QuerySize(mpFlagsNode, pszName, &cchFlags);  /* Ignore failure. */ 
     399 
     400    /* Get the value size */ 
     401    if (RT_SUCCESS(rc)) 
     402        rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue); 
     403    /* Get the flags and their size */ 
     404    if (RT_SUCCESS(rc)) 
     405        CFGMR3QueryU32(mpFlagsNode, pszName, (uint32_t *)&fFlags); 
     406    if (RT_SUCCESS(rc)) 
     407        rc = writeFlags(fFlags, szFlags); 
     408    if (RT_SUCCESS(rc)) 
     409        cchFlags = strlen(szFlags); 
    402410    /* Check that the buffer is big enough */ 
    403411    if (RT_SUCCESS(rc)) 
     
    411419    if (RT_SUCCESS(rc)) 
    412420        rc = CFGMR3QueryString(mpValueNode, pszName, pchBuf, cchBuf); 
    413     /* Write the flags if there are any */ 
    414     if (RT_SUCCESS(rc)) 
    415         pchBuf[cchValue] = '\0';  /* In case there aren't */ 
    416     if (RT_SUCCESS(rc) && (mpFlagsNode != NULL) && (cchFlags != 1)) 
    417         CFGMR3QueryString(mpFlagsNode, pszName, pchBuf + cchValue, 
    418                           cchBuf - cchValue); 
     421    /* Write the flags */ 
     422    if (RT_SUCCESS(rc)) 
     423        strcpy(pchBuf + cchValue, szFlags); 
    419424    /* Timestamp */ 
    420425    uint64_t u64Timestamp = 0; 
    421     if (RT_SUCCESS(rc) && (mpTimestampNode != NULL)
     426    if (RT_SUCCESS(rc)
    422427        CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 
    423428    VBoxHGCMParmUInt64Set(&paParms[2], u64Timestamp); 
     
    449454{ 
    450455    int rc = VINF_SUCCESS; 
    451     char *pszName, *pszValue, *pszFlags; 
    452     uint32_t cchName, cchValue, cchFlags = 0; 
     456    char *pszName, *pszValue; 
     457    uint32_t cchName, cchValue; 
     458    uint32_t fFlags = NILFLAG; 
    453459 
    454460    LogFlowThisFunc(("\n")); 
     461    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */ 
    455462    /* 
    456463     * First of all, make sure that we won't exceed the maximum number of properties. 
     
    485492    if (RT_SUCCESS(rc)) 
    486493        rc = validateValue(pszValue, cchValue); 
    487     /* For now, we do not support any flags */ 
    488     if (RT_SUCCESS(rc) && (3 == cParms)) 
    489     { 
    490         rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags); 
    491         for (size_t i = 0; (i < cchFlags - 1) && RT_SUCCESS(rc); ++i) 
    492             if (pszFlags[i] != ' ') 
    493                 rc = VERR_INVALID_PARAMETER; 
     494    if (RT_SUCCESS(rc)) 
     495    { 
     496        /* We deal with flags as follows: 
     497         *  1) if flags are specified by the user, use them. 
     498         *  2) if no flags are specified, but the property exists, use the 
     499         *     existing flags. 
     500         *  3) if no flags are specified and the property does not exist, 
     501         *     start with empty flags (the default value of fFlags above). */ 
     502        if (3 == cParms) 
     503        { 
     504            char *pszFlags; 
     505            uint32_t cchFlags; 
     506            rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags); 
     507            if (RT_SUCCESS(rc)) 
     508                rc = validateFlags(pszFlags, &fFlags); 
     509        } 
     510        else 
     511            /* If this fails then fFlags will remain at zero, as per our spec. */ 
     512            CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); 
    494513    } 
    495514    /* 
     
    500519        RTTIMESPEC time; 
    501520        CFGMR3RemoveValue(mpValueNode, pszName); 
    502         if (mpTimestampNode != NULL) 
    503             CFGMR3RemoveValue(mpTimestampNode, pszName); 
    504         if ((3 == cParms) && (mpFlagsNode != NULL)) 
    505             CFGMR3RemoveValue(mpFlagsNode, pszName); 
     521        CFGMR3RemoveValue(mpTimestampNode, pszName); 
     522        CFGMR3RemoveValue(mpFlagsNode, pszName); 
    506523        rc = CFGMR3InsertString(mpValueNode, pszName, pszValue); 
    507524        if (RT_SUCCESS(rc)) 
    508525            rc = CFGMR3InsertInteger(mpTimestampNode, pszName, 
    509526                                     RTTimeSpecGetNano(RTTimeNow(&time))); 
    510         if (RT_SUCCESS(rc) && (3 == cParms)) 
    511             rc = CFGMR3InsertString(mpFlagsNode, pszName, pszFlags); 
    512         /* If we are not setting flags, make sure that there are some */ 
    513         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL) && (cParms != 3)) 
     527        if (RT_SUCCESS(rc)) 
     528            rc = CFGMR3InsertInteger(mpFlagsNode, pszName, fFlags); 
     529        /* If anything goes wrong, make sure that we leave a clean state 
     530         * behind. */ 
     531        if (!RT_SUCCESS(rc)) 
    514532        { 
    515             CFGMVALUETYPE dummy; 
    516             if (   CFGMR3QueryType(mpFlagsNode, pszName, &dummy) 
    517                 == VERR_CFGM_VALUE_NOT_FOUND) 
    518                 rc = CFGMR3InsertString(mpFlagsNode, pszName, ""); 
     533            CFGMR3RemoveValue(mpValueNode, pszName); 
     534            CFGMR3RemoveValue(mpTimestampNode, pszName); 
     535            CFGMR3RemoveValue(mpFlagsNode, pszName); 
    519536        } 
    520537    } 
     
    549566 
    550567    LogFlowThisFunc(("\n")); 
     568    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */ 
    551569    if (   (cParms != 1)  /* Hardcoded value as the next lines depend on it. */ 
    552570        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* name */ 
     
    676694    uint32_t cchPatterns = 0, cchBuf = 0; 
    677695    LogFlowThisFunc(("\n")); 
     696    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */ 
    678697    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */ 
    679698        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* patterns */ 
     
    722741                iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1; 
    723742                uint64_t u64Timestamp = 0; 
    724                 if (mpTimestampNode != NULL) 
    725                     CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 
     743                CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 
    726744                iTmpBuf += RTStrFormatNumber(&TmpBuf[iTmpBuf], u64Timestamp, 
    727745                                             10, 0, 0, 0) + 1; 
    728746                /* Get flags */ 
    729                 TmpBuf[iTmpBuf] = '\0';  /* In case there are none. */ 
    730                 if (mpFlagsNode != NULL) 
    731                     CFGMR3QueryString(mpFlagsNode, pszName, &TmpBuf[iTmpBuf], 
    732                                       cchTmpBuf - iTmpBuf);  /* Ignore failure */ 
     747                uint32_t fFlags = NILFLAG; 
     748                CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); 
     749                TmpBuf[iTmpBuf] = '\0';  /* Bad (== in)sanity, will be fixed. */ 
     750                writeFlags(fFlags, &TmpBuf[iTmpBuf]); 
    733751                iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1; 
    734752            } 
     
    767785    char szValue[MAX_VALUE_LEN]; 
    768786    uint64_t u64Timestamp = 0; 
    769     char szFlags[MAX_FLAGS_LEN]; 
     787    uint32_t fFlags = NILFLAG; 
     788    char szFlags[MAX_FLAGS_LEN + 1]; 
    770789    char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL; 
    771790 
     791    AssertPtr(mpValueNode); 
    772792    if (NULL == mpfnHostCallback) 
    773793        return;  /* Nothing to do. */ 
     
    779799    if (rc != VERR_CFGM_VALUE_NOT_FOUND) 
    780800    { 
    781         if (RT_SUCCESS(rc) && (mpTimestampNode != NULL)
     801        if (RT_SUCCESS(rc)
    782802            rc = CFGMR3QueryU64(mpTimestampNode, pszProperty, &u64Timestamp); 
    783         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL)) 
    784             rc = CFGMR3QueryString(mpFlagsNode, pszProperty, szFlags, 
    785                                    sizeof(szFlags)); 
     803        if (RT_SUCCESS(rc)) 
     804            rc = CFGMR3QueryU32(mpFlagsNode, pszProperty, &fFlags); 
     805        if (RT_SUCCESS(rc)) 
     806            rc = writeFlags(fFlags, szFlags); 
    786807        if (RT_SUCCESS(rc)) 
    787808            rc = RTStrDupEx(&pszName, pszProperty); 
    788         if (RT_SUCCESS(rc) && (mpTimestampNode != NULL)
     809        if (RT_SUCCESS(rc)
    789810            rc = RTStrDupEx(&pszValue, szValue); 
    790         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL)
     811        if (RT_SUCCESS(rc)
    791812            rc = RTStrDupEx(&pszFlags, szFlags); 
    792813        if (RT_SUCCESS(rc)) 
     
    934955            LogFlowFunc(("SET_CFGM_NODE\n")); 
    935956 
    936             if ((cParms < 1) || (cParms > 3)) 
    937             { 
     957            if (   (cParms != 3) 
     958                || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* pValue */ 
     959                || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR)   /* pTimestamp */ 
     960                || (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR)   /* pFlags */ 
     961               ) 
    938962                rc = VERR_INVALID_PARAMETER; 
    939             } 
    940             else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* pValue */ 
    941                      || ((cParms > 1) && (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR))   /* pTimestamp */ 
    942                      || ((cParms > 2) && (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR))   /* pFlags */ 
    943                     ) 
    944             { 
    945                 rc = VERR_INVALID_PARAMETER; 
    946             } 
    947963            else 
    948964            { 
    949                 PCFGMNODE pNode = NULL; 
     965                PCFGMNODE pValue = NULL, pTimestamp = NULL, pFlags = NULL; 
    950966                uint32_t cbDummy; 
    951967 
    952                 rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pNode, &cbDummy); 
     968                rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pValue, &cbDummy); 
    953969                if (RT_SUCCESS(rc)) 
    954                     mpValueNode = pNode; 
    955                 if (RT_SUCCESS(rc) && (cParms > 1)) 
     970                    rc = VBoxHGCMParmPtrGet (&paParms[1], (void **) &pTimestamp, &cbDummy); 
     971                if (RT_SUCCESS(rc)) 
     972                    rc = VBoxHGCMParmPtrGet (&paParms[2], (void **) &pFlags, &cbDummy); 
     973                if (RT_SUCCESS(rc)) 
    956974                { 
    957                     rc = VBoxHGCMParmPtrGet (&paParms[1], (void **) &pNode, &cbDummy); 
    958                     mpTimestampNode = pNode; 
    959                 } 
    960                 if (RT_SUCCESS(rc) && (cParms > 2)) 
    961                 { 
    962                     rc = VBoxHGCMParmPtrGet (&paParms[2], (void **) &pNode, &cbDummy); 
    963                     mpFlagsNode = pNode; 
     975                    mpValueNode     = pValue; 
     976                    mpTimestampNode = pTimestamp; 
     977                    mpFlagsNode     = pFlags; 
    964978                } 
    965979            } 
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r13165 r13293  
    44944494        char szPropFlags[MAX_FLAGS_LEN + 1]; 
    44954495        ULONG64 u64Timestamp = 0;  /* default */ 
    4496         szPropFlags[0] = '\0';  /* default */ 
    44974496        vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName)); 
    44984497        if (RT_SUCCESS(vrc)) 
     
    45004499        if (RT_SUCCESS(vrc)) 
    45014500        { 
    4502             CFGMR3QueryString (pFlags, szPropName, szPropFlags, sizeof(szPropFlags)); 
     4501            uint32_t fFlags; 
     4502            CFGMR3QueryU32 (pFlags, szPropName, &fFlags); 
     4503            writeFlags(fFlags, szPropFlags); 
    45034504            CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp); 
    45044505            Bstr(szPropName).cloneTo(&names[iProp]); 
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r13286 r13293  
    18131813            for (size_t i = 0; i < cProps; ++i) 
    18141814            { 
    1815                 rc = CFGMR3InsertString(pValues, Utf8Str(names[i]).raw(), Utf8Str(values[i]).raw()); RC_CHECK(); 
    1816                 rc = CFGMR3InsertInteger(pTimestamps, Utf8Str(names[i]).raw(), timestamps[i]);           RC_CHECK(); 
    1817                 rc = CFGMR3InsertString(pFlags, Utf8Str(names[i]).raw(), Utf8Str(flags[i]).raw());   RC_CHECK(); 
     1815                rc = CFGMR3InsertString(pValues, Utf8Str(names[i]).raw(), Utf8Str(values[i]).raw());    RC_CHECK(); 
     1816                rc = CFGMR3InsertInteger(pTimestamps, Utf8Str(names[i]).raw(), timestamps[i]);          RC_CHECK(); 
     1817                uint32_t fFlags; 
     1818                rc = guestProp::validateFlags(Utf8Str(flags[i]).raw(), &fFlags); 
     1819                AssertLogRelRCReturn(rc, VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 
     1820                    N_("Guest property '%lS' has invalid flags '%lS' in machine definition file"), 
     1821                       names[i], flags[i])); 
     1822                rc = CFGMR3InsertInteger(pFlags, Utf8Str(names[i]).raw(), fFlags);                      RC_CHECK(); 
    18181823            } 
    18191824 
  • trunk/src/VBox/Main/MachineImpl.cpp

    r13221 r13293  
    28042804        return E_INVALIDARG; 
    28052805 
    2806     /* For now there are no valid flags, so check this. */ 
    2807     if (aFlags != NULL) 
    2808         for (size_t i = 0; aFlags[i] != '\0'; ++i) 
    2809             if (aFlags[i] != ' ') 
    2810                 return E_INVALIDARG; 
    2811  
    28122806    AutoCaller autoCaller (this); 
    28132807    CheckComRCReturnRC (autoCaller.rc()); 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy