Changeset 10929 in vbox
- Timestamp:
- Jul 29, 2008 1:23:40 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33777
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestPropertySvc.h
r10797 r10929 199 199 * Null-separated array of patterns to match the properties against. 200 200 * (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. 202 203 */ 203 204 HGCMFunctionParameter patterns; 204 205 /** 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) 207 208 * The number of strings in the array is always a multiple of four, 208 209 * 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. 210 212 */ 211 213 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; 212 219 } EnumProperties; 213 220 #pragma pack () -
trunk/src/VBox/HostServices/GuestProperties/service.cpp
r10814 r10929 53 53 #include <iprt/assert.h> 54 54 #include <iprt/string.h> 55 #include <iprt/mem.h> 56 #include <iprt/autores> 55 57 #include <VBox/log.h> 56 58 … … 170 172 int setKey(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 171 173 int delKey(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 174 int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 172 175 void call (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, 173 176 void *pvClient, uint32_t eFunction, uint32_t cParms, … … 178 181 179 182 /** 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 */ 192 static 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 /** 180 208 * Checking that the key passed by the guest fits our criteria for a 181 209 * configuration key … … 198 226 rc = RTStrValidateEncodingEx(pszKey, cbKey - 1, 0); 199 227 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); 204 230 205 231 LogFlowFunc(("returning %Rrc\n", rc)); … … 228 254 rc = RTStrValidateEncodingEx(pszValue, cbValue - 1, 0); 229 255 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); 234 258 235 259 if (RT_SUCCESS(rc)) … … 428 452 } 429 453 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 */ 462 static 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. */ 511 static 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 */ 544 int 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 430 629 431 630 /** … … 474 673 break; 475 674 675 case ENUM_PROPS: 676 LogFlowFunc(("ENUM_PROPS\n")); 677 rc = enumProps(cParms, paParms); 678 break; 476 679 default: 477 680 rc = VERR_NOT_IMPLEMENTED;
Note:
See TracChangeset
for help on using the changeset viewer.