Changeset 13293 in vbox
- Timestamp:
- Oct 15, 2008 4:19:36 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestPropertySvc.h
r13159 r13293 35 35 #include <VBox/VBoxGuest.h> 36 36 #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 37 45 38 46 /** Everything defined in this file lives in this namespace. */ 39 47 namespace guestProp { 48 49 /****************************************************************************** 50 * Typedefs, constants and inlines * 51 ******************************************************************************/ 52 53 /** Maximum length for property names */ 54 enum { MAX_NAME_LEN = 64 }; 55 /** Maximum length for property values */ 56 enum { MAX_VALUE_LEN = 128 }; 57 /** Maximum number of properties per guest */ 58 enum { MAX_PROPS = 256 }; 59 60 /** 61 * The guest property flag values which are currently accepted. 62 */ 63 enum 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 */ 77 const 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 */ 93 enum { 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 */ 109 DECLINLINE(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 */ 151 DECLINLINE(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 } 40 176 41 177 /* … … 111 247 }; 112 248 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 122 249 /** 123 250 * HGCM parameter structures. Packing is explicitly defined as this is a wire format. -
trunk/src/VBox/HostServices/GuestProperties/service.cpp
r13212 r13293 327 327 328 328 LogFlowThisFunc(("\n")); 329 AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ 329 330 if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */ 330 331 || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ … … 373 374 uint32_t cchName, cchBuf; 374 375 size_t cchValue, cchFlags, cchBufActual; 376 char szFlags[MAX_FLAGS_LEN + 1]; 377 uint32_t fFlags; 375 378 376 379 /* … … 378 381 */ 379 382 LogFlowThisFunc(("\n")); 383 AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ 380 384 if ( (cParms != 4) /* Hardcoded value as the next lines depend on it. */ 381 385 || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ … … 389 393 if (RT_SUCCESS(rc)) 390 394 rc = validateName(pszName, cchName); 391 /* Get the value size */392 if (RT_SUCCESS(rc))393 rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue);394 395 395 396 /* 396 397 * Read and set the values we will return 397 398 */ 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); 402 410 /* Check that the buffer is big enough */ 403 411 if (RT_SUCCESS(rc)) … … 411 419 if (RT_SUCCESS(rc)) 412 420 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); 419 424 /* Timestamp */ 420 425 uint64_t u64Timestamp = 0; 421 if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))426 if (RT_SUCCESS(rc)) 422 427 CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 423 428 VBoxHGCMParmUInt64Set(&paParms[2], u64Timestamp); … … 449 454 { 450 455 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; 453 459 454 460 LogFlowThisFunc(("\n")); 461 AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ 455 462 /* 456 463 * First of all, make sure that we won't exceed the maximum number of properties. … … 485 492 if (RT_SUCCESS(rc)) 486 493 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); 494 513 } 495 514 /* … … 500 519 RTTIMESPEC time; 501 520 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); 506 523 rc = CFGMR3InsertString(mpValueNode, pszName, pszValue); 507 524 if (RT_SUCCESS(rc)) 508 525 rc = CFGMR3InsertInteger(mpTimestampNode, pszName, 509 526 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)) 514 532 { 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); 519 536 } 520 537 } … … 549 566 550 567 LogFlowThisFunc(("\n")); 568 AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ 551 569 if ( (cParms != 1) /* Hardcoded value as the next lines depend on it. */ 552 570 || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ … … 676 694 uint32_t cchPatterns = 0, cchBuf = 0; 677 695 LogFlowThisFunc(("\n")); 696 AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ 678 697 if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */ 679 698 || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* patterns */ … … 722 741 iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1; 723 742 uint64_t u64Timestamp = 0; 724 if (mpTimestampNode != NULL) 725 CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 743 CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp); 726 744 iTmpBuf += RTStrFormatNumber(&TmpBuf[iTmpBuf], u64Timestamp, 727 745 10, 0, 0, 0) + 1; 728 746 /* 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]); 733 751 iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1; 734 752 } … … 767 785 char szValue[MAX_VALUE_LEN]; 768 786 uint64_t u64Timestamp = 0; 769 char szFlags[MAX_FLAGS_LEN]; 787 uint32_t fFlags = NILFLAG; 788 char szFlags[MAX_FLAGS_LEN + 1]; 770 789 char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL; 771 790 791 AssertPtr(mpValueNode); 772 792 if (NULL == mpfnHostCallback) 773 793 return; /* Nothing to do. */ … … 779 799 if (rc != VERR_CFGM_VALUE_NOT_FOUND) 780 800 { 781 if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))801 if (RT_SUCCESS(rc)) 782 802 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); 786 807 if (RT_SUCCESS(rc)) 787 808 rc = RTStrDupEx(&pszName, pszProperty); 788 if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))809 if (RT_SUCCESS(rc)) 789 810 rc = RTStrDupEx(&pszValue, szValue); 790 if (RT_SUCCESS(rc) && (mpFlagsNode != NULL))811 if (RT_SUCCESS(rc)) 791 812 rc = RTStrDupEx(&pszFlags, szFlags); 792 813 if (RT_SUCCESS(rc)) … … 934 955 LogFlowFunc(("SET_CFGM_NODE\n")); 935 956 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 ) 938 962 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 }947 963 else 948 964 { 949 PCFGMNODE p Node= NULL;965 PCFGMNODE pValue = NULL, pTimestamp = NULL, pFlags = NULL; 950 966 uint32_t cbDummy; 951 967 952 rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &p Node, &cbDummy);968 rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pValue, &cbDummy); 953 969 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)) 956 974 { 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; 964 978 } 965 979 } -
trunk/src/VBox/Main/ConsoleImpl.cpp
r13165 r13293 4494 4494 char szPropFlags[MAX_FLAGS_LEN + 1]; 4495 4495 ULONG64 u64Timestamp = 0; /* default */ 4496 szPropFlags[0] = '\0'; /* default */4497 4496 vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName)); 4498 4497 if (RT_SUCCESS(vrc)) … … 4500 4499 if (RT_SUCCESS(vrc)) 4501 4500 { 4502 CFGMR3QueryString (pFlags, szPropName, szPropFlags, sizeof(szPropFlags)); 4501 uint32_t fFlags; 4502 CFGMR3QueryU32 (pFlags, szPropName, &fFlags); 4503 writeFlags(fFlags, szPropFlags); 4503 4504 CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp); 4504 4505 Bstr(szPropName).cloneTo(&names[iProp]); -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r13286 r13293 1813 1813 for (size_t i = 0; i < cProps; ++i) 1814 1814 { 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(); 1818 1823 } 1819 1824 -
trunk/src/VBox/Main/MachineImpl.cpp
r13221 r13293 2804 2804 return E_INVALIDARG; 2805 2805 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 2812 2806 AutoCaller autoCaller (this); 2813 2807 CheckComRCReturnRC (autoCaller.rc());
Note:
See TracChangeset
for help on using the changeset viewer.