| 126 | | /** Structure for holding a property */ |
|---|
| 127 | | struct Property |
|---|
| 128 | | { |
|---|
| 129 | | /** The name of the property */ |
|---|
| 130 | | std::string mName; |
|---|
| 131 | | /** The property value */ |
|---|
| 132 | | std::string mValue; |
|---|
| 133 | | /** The timestamp of the property */ |
|---|
| 134 | | uint64_t mTimestamp; |
|---|
| 135 | | /** The property flags */ |
|---|
| 136 | | uint32_t mFlags; |
|---|
| 137 | | /** Constructor with const char * */ |
|---|
| 138 | | Property(const char *pcszName, const char *pcszValue, |
|---|
| 139 | | uint64_t u64Timestamp, uint32_t u32Flags) |
|---|
| 140 | | : mName(pcszName), mValue(pcszValue), mTimestamp(u64Timestamp), |
|---|
| 141 | | mFlags(u32Flags) {} |
|---|
| 142 | | /** Constructor with std::string */ |
|---|
| 143 | | Property(std::string name, std::string value, uint64_t u64Timestamp, |
|---|
| 144 | | uint32_t u32Flags) |
|---|
| 145 | | : mName(name), mValue(value), mTimestamp(u64Timestamp), |
|---|
| 146 | | mFlags(u32Flags) {} |
|---|
| 147 | | }; |
|---|
| 148 | | /** The properties list type */ |
|---|
| 149 | | typedef std::list <Property> PropertyList; |
|---|
| 150 | | /** The property list */ |
|---|
| 151 | | PropertyList mProperties; |
|---|
| | 106 | /** Pointer to our configuration values node. */ |
|---|
| | 107 | PCFGMNODE mpValueNode; |
|---|
| | 108 | /** Pointer to our configuration timestamps node. */ |
|---|
| | 109 | PCFGMNODE mpTimestampNode; |
|---|
| | 110 | /** Pointer to our configuration flags node. */ |
|---|
| | 111 | PCFGMNODE mpFlagsNode; |
|---|
| 350 | | /** |
|---|
| 351 | | * Set a block of properties in the property registry, checking the validity |
|---|
| 352 | | * of the arguments passed. |
|---|
| 353 | | * |
|---|
| 354 | | * @returns iprt status value |
|---|
| 355 | | * @param cParms the number of HGCM parameters supplied |
|---|
| 356 | | * @param paParms the array of HGCM parameters |
|---|
| 357 | | * @thread HGCM |
|---|
| 358 | | */ |
|---|
| 359 | | int Service::setPropertyBlock(uint32_t cParms, VBOXHGCMSVCPARM paParms[]) |
|---|
| 360 | | { |
|---|
| 361 | | char **ppNames, **ppValues, **ppFlags; |
|---|
| 362 | | uint64_t *pTimestamps; |
|---|
| 363 | | uint32_t cbDummy; |
|---|
| 364 | | int rc = VINF_SUCCESS; |
|---|
| 365 | | |
|---|
| 366 | | /* |
|---|
| 367 | | * Get and validate the parameters |
|---|
| 368 | | */ |
|---|
| 369 | | 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)) |
|---|
| 374 | | ) |
|---|
| 375 | | rc = VERR_INVALID_PARAMETER; |
|---|
| 376 | | |
|---|
| 377 | | /* |
|---|
| 378 | | * Add the properties to the end of the list. If we succeed then we |
|---|
| 379 | | * will remove duplicates afterwards. |
|---|
| 380 | | */ |
|---|
| 381 | | /* Remember the last property before we started adding, for rollback or |
|---|
| 382 | | * cleanup. */ |
|---|
| 383 | | PropertyList::iterator itEnd = mProperties.end(); |
|---|
| 384 | | if (!mProperties.empty()) |
|---|
| 385 | | --itEnd; |
|---|
| 386 | | try |
|---|
| 387 | | { |
|---|
| 388 | | for (unsigned i = 0; RT_SUCCESS(rc) && ppNames[i] != NULL; ++i) |
|---|
| 389 | | { |
|---|
| 390 | | uint32_t fFlags; |
|---|
| 391 | | if ( !VALID_PTR(ppNames[i]) |
|---|
| 392 | | || !VALID_PTR(ppValues[i]) |
|---|
| 393 | | || !VALID_PTR(ppFlags[i]) |
|---|
| 394 | | ) |
|---|
| 395 | | rc = VERR_INVALID_POINTER; |
|---|
| 396 | | if (RT_SUCCESS(rc)) |
|---|
| 397 | | rc = validateFlags(ppFlags[i], &fFlags); |
|---|
| 398 | | if (RT_SUCCESS(rc)) |
|---|
| 399 | | mProperties.push_back(Property(ppNames[i], ppValues[i], |
|---|
| 400 | | pTimestamps[i], fFlags)); |
|---|
| 401 | | } |
|---|
| 402 | | } |
|---|
| 403 | | catch (std::bad_alloc) |
|---|
| 404 | | { |
|---|
| 405 | | rc = VERR_NO_MEMORY; |
|---|
| 406 | | } |
|---|
| 407 | | |
|---|
| 408 | | /* |
|---|
| 409 | | * If all went well then remove the duplicate elements. |
|---|
| 410 | | */ |
|---|
| 411 | | if (RT_SUCCESS(rc) && itEnd != mProperties.end()) |
|---|
| 412 | | { |
|---|
| 413 | | ++itEnd; |
|---|
| 414 | | for (unsigned i = 0; ppNames[i] != NULL; ++i) |
|---|
| 415 | | { |
|---|
| 416 | | bool found = false; |
|---|
| 417 | | for (PropertyList::iterator it = mProperties.begin(); |
|---|
| 418 | | !found && it != itEnd; ++it) |
|---|
| 419 | | if (it->mName.compare(ppNames[i]) == 0) |
|---|
| 420 | | { |
|---|
| 421 | | found = true; |
|---|
| 422 | | mProperties.erase(it); |
|---|
| 423 | | } |
|---|
| 424 | | } |
|---|
| 425 | | } |
|---|
| 426 | | |
|---|
| 427 | | /* |
|---|
| 428 | | * If something went wrong then rollback. This is possible because we |
|---|
| 429 | | * haven't deleted anything yet. |
|---|
| 430 | | */ |
|---|
| 431 | | if (RT_FAILURE(rc)) |
|---|
| 432 | | { |
|---|
| 433 | | if (itEnd != mProperties.end()) |
|---|
| 434 | | ++itEnd; |
|---|
| 435 | | mProperties.erase(itEnd, mProperties.end()); |
|---|
| 436 | | } |
|---|
| 437 | | return rc; |
|---|
| 438 | | } |
|---|
| | 320 | int Service::getPropValue(uint32_t cParms, VBOXHGCMSVCPARM paParms[]) |
|---|
| | 321 | { |
|---|
| | 322 | int rc = VINF_SUCCESS; |
|---|
| | 323 | char *pszName, *pszValue; |
|---|
| | 324 | uint32_t cbName, cbValue; |
|---|
| | 325 | size_t cbValueActual; |
|---|
| | 326 | |
|---|
| | 327 | LogFlowThisFunc(("\n")); |
|---|
| | 328 | AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ |
|---|
| | 329 | if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */ |
|---|
| | 330 | || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ |
|---|
| | 331 | || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* value */ |
|---|
| | 332 | ) |
|---|
| | 333 | rc = VERR_INVALID_PARAMETER; |
|---|
| | 334 | if (RT_SUCCESS(rc)) |
|---|
| | 335 | rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cbName); |
|---|
| | 336 | if (RT_SUCCESS(rc)) |
|---|
| | 337 | rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pszValue, &cbValue); |
|---|
| | 338 | if (RT_SUCCESS(rc)) |
|---|
| | 339 | rc = validateName(pszName, cbName); |
|---|
| | 340 | if (RT_SUCCESS(rc)) |
|---|
| | 341 | rc = CFGMR3QuerySize(mpValueNode, pszName, &cbValueActual); |
|---|
| | 342 | if (RT_SUCCESS(rc)) |
|---|
| | 343 | VBoxHGCMParmUInt32Set(&paParms[2], cbValueActual); |
|---|
| | 344 | if (RT_SUCCESS(rc) && (cbValueActual > cbValue)) |
|---|
| | 345 | rc = VERR_BUFFER_OVERFLOW; |
|---|
| | 346 | if (RT_SUCCESS(rc)) |
|---|
| | 347 | rc = CFGMR3QueryString(mpValueNode, pszName, pszValue, cbValue); |
|---|
| | 348 | if (RT_SUCCESS(rc)) |
|---|
| | 349 | Log2(("Queried string %s, rc=%Rrc, value=%.*s\n", pszName, rc, cbValue, pszValue)); |
|---|
| | 350 | else if (VERR_CFGM_VALUE_NOT_FOUND == rc) |
|---|
| | 351 | rc = VERR_NOT_FOUND; |
|---|
| | 352 | LogFlowThisFunc(("rc = %Rrc\n", rc)); |
|---|
| | 353 | return rc; |
|---|
| | 354 | } |
|---|
| | 355 | |
|---|
| | 356 | |
|---|
| | 357 | /** |
|---|
| | 358 | * Retrieve a value from the property registry by name, checking the validity |
|---|
| | 359 | * of the arguments passed. If the guest has not allocated enough buffer |
|---|
| | 360 | * space for the value then we return VERR_OVERFLOW and set the size of the |
|---|
| | 361 | * buffer needed in the "size" HGCM parameter. If the name was not found at |
|---|
| | 362 | * all, we return VERR_NOT_FOUND. |
|---|
| | 363 | * |
|---|
| | 364 | * @returns iprt status value |
|---|
| | 365 | * @param cParms the number of HGCM parameters supplied |
|---|
| | 366 | * @param paParms the array of HGCM parameters |
|---|
| | 367 | * @thread HGCM |
|---|
| | 368 | */ |
|---|
| 527 | | * of the arguments passed. |
|---|
| 528 | | * |
|---|
| 529 | | * @returns iprt status value |
|---|
| 530 | | * @param cParms the number of HGCM parameters supplied |
|---|
| 531 | | * @param paParms the array of HGCM parameters |
|---|
| 532 | | * @param isGuest is this call coming from the guest (or the host)? |
|---|
| 533 | | * @throws std::bad_alloc if an out of memory condition occurs |
|---|
| 534 | | * @thread HGCM |
|---|
| 535 | | */ |
|---|
| 536 | | int Service::setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest) |
|---|
| 537 | | { |
|---|
| 538 | | int rc = VINF_SUCCESS; |
|---|
| 539 | | const char *pcszName, *pcszValue, *pcszFlags = NULL; |
|---|
| 540 | | uint32_t cchName, cchValue, cchFlags = 0; |
|---|
| 541 | | uint32_t fFlags = NILFLAG; |
|---|
| 542 | | |
|---|
| 543 | | LogFlowThisFunc(("\n")); |
|---|
| 544 | | /* |
|---|
| 545 | | * First of all, make sure that we won't exceed the maximum number of properties. |
|---|
| 546 | | */ |
|---|
| 547 | | if (mProperties.size() >= MAX_PROPS) |
|---|
| 548 | | rc = VERR_TOO_MUCH_DATA; |
|---|
| 549 | | |
|---|
| 550 | | /* |
|---|
| 551 | | * General parameter correctness checking. |
|---|
| 552 | | */ |
|---|
| 553 | | if ( RT_SUCCESS(rc) |
|---|
| 554 | | && ( (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 */ |
|---|
| 559 | | || ( (3 == cParms) |
|---|
| 560 | | && RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[2], |
|---|
| 561 | | (const void **) &pcszFlags, &cchFlags)) /* flags */ |
|---|
| 562 | | ) |
|---|
| 563 | | ) |
|---|
| 564 | | ) |
|---|
| 565 | | rc = VERR_INVALID_PARAMETER; |
|---|
| 566 | | |
|---|
| 567 | | /* |
|---|
| 568 | | * Check the values passed in the parameters for correctness. |
|---|
| 569 | | */ |
|---|
| 570 | | if (RT_SUCCESS(rc)) |
|---|
| 571 | | rc = validateName(pcszName, cchName); |
|---|
| 572 | | if (RT_SUCCESS(rc)) |
|---|
| 573 | | rc = validateValue(pcszValue, cchValue); |
|---|
| 574 | | if ((3 == cParms) && RT_SUCCESS(rc)) |
|---|
| 575 | | rc = RTStrValidateEncodingEx(pcszFlags, cchFlags, |
|---|
| 576 | | RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED); |
|---|
| 577 | | if ((3 == cParms) && RT_SUCCESS(rc)) |
|---|
| 578 | | rc = validateFlags(pcszFlags, &fFlags); |
|---|
| 579 | | |
|---|
| 580 | | /* |
|---|
| 581 | | * If the property already exists, check its flags to see if we are allowed |
|---|
| 582 | | * to change it. |
|---|
| 583 | | */ |
|---|
| 584 | | PropertyList::iterator it; |
|---|
| 585 | | bool found = false; |
|---|
| 586 | | if (RT_SUCCESS(rc)) |
|---|
| 587 | | for (it = mProperties.begin(); it != mProperties.end(); ++it) |
|---|
| 588 | | if (it->mName.compare(pcszName) == 0) |
|---|
| 589 | | { |
|---|
| 590 | | found = true; |
|---|
| 591 | | break; |
|---|
| 592 | | } |
|---|
| 593 | | if (RT_SUCCESS(rc) && found) |
|---|
| 594 | | if ( (isGuest && (it->mFlags & RDONLYGUEST)) |
|---|
| 595 | | || (!isGuest && (it->mFlags & RDONLYHOST)) |
|---|
| 596 | | ) |
|---|
| 597 | | rc = VERR_PERMISSION_DENIED; |
|---|
| 598 | | |
|---|
| 599 | | /* |
|---|
| 600 | | * Set the actual value |
|---|
| 601 | | */ |
|---|
| 602 | | if (RT_SUCCESS(rc)) |
|---|
| 603 | | { |
|---|
| 604 | | RTTIMESPEC time; |
|---|
| 605 | | uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time)); |
|---|
| 606 | | if (found) |
|---|
| 607 | | { |
|---|
| 608 | | it->mValue = pcszValue; |
|---|
| 609 | | it->mTimestamp = u64TimeNano; |
|---|
| 610 | | it->mFlags = fFlags; |
|---|
| 611 | | } |
|---|
| 612 | | else /* This can throw. No problem as we have nothing to roll back. */ |
|---|
| 613 | | mProperties.push_back(Property(pcszName, pcszValue, u64TimeNano, fFlags)); |
|---|
| 614 | | } |
|---|
| 615 | | |
|---|
| 616 | | /* |
|---|
| 617 | | * Send a notification to the host and return. |
|---|
| 618 | | */ |
|---|
| 619 | | if (RT_SUCCESS(rc)) |
|---|
| 620 | | { |
|---|
| 621 | | // if (isGuest) /* Notify the host even for properties that the host |
|---|
| 622 | | // * changed. Less efficient, but ensures consistency. */ |
|---|
| 623 | | notifyHost(pcszName); |
|---|
| 624 | | Log2(("Set string %s, rc=%Rrc, value=%s\n", pcszName, rc, pcszValue)); |
|---|
| 625 | | } |
|---|
| 626 | | LogFlowThisFunc(("rc = %Rrc\n", rc)); |
|---|
| 627 | | return rc; |
|---|
| 628 | | } |
|---|
| 629 | | |
|---|
| 630 | | |
|---|
| 631 | | /** |
|---|
| 632 | | * Remove a value in the property registry by name, checking the validity |
|---|
| 633 | | * of the arguments passed. |
|---|
| 634 | | * |
|---|
| 635 | | * @returns iprt status value |
|---|
| 636 | | * @param cParms the number of HGCM parameters supplied |
|---|
| 637 | | * @param paParms the array of HGCM parameters |
|---|
| 638 | | * @param isGuest is this call coming from the guest (or the host)? |
|---|
| 639 | | * @thread HGCM |
|---|
| 640 | | */ |
|---|
| 641 | | int Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest) |
|---|
| 642 | | { |
|---|
| 643 | | int rc = VINF_SUCCESS; |
|---|
| 644 | | const char *pcszName; |
|---|
| 645 | | uint32_t cbName; |
|---|
| 646 | | |
|---|
| 647 | | LogFlowThisFunc(("\n")); |
|---|
| 648 | | |
|---|
| 649 | | /* |
|---|
| 650 | | * Check the user-supplied parameters. |
|---|
| 651 | | */ |
|---|
| 652 | | if ( (cParms != 1) /* Hardcoded value as the next lines depend on it. */ |
|---|
| 653 | | || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[0], |
|---|
| 654 | | (const void **) &pcszName, &cbName)) /* name */ |
|---|
| 655 | | ) |
|---|
| 656 | | rc = VERR_INVALID_PARAMETER; |
|---|
| 657 | | if (RT_SUCCESS(rc)) |
|---|
| 658 | | rc = validateName(pcszName, cbName); |
|---|
| 659 | | |
|---|
| 660 | | /* |
|---|
| 661 | | * If the property exists, check its flags to see if we are allowed |
|---|
| 662 | | * to change it. |
|---|
| 663 | | */ |
|---|
| 664 | | PropertyList::iterator it; |
|---|
| 665 | | bool found = false; |
|---|
| 666 | | if (RT_SUCCESS(rc)) |
|---|
| 667 | | for (it = mProperties.begin(); it != mProperties.end(); ++it) |
|---|
| 668 | | if (it->mName.compare(pcszName) == 0) |
|---|
| 669 | | { |
|---|
| 670 | | found = true; |
|---|
| 671 | | break; |
|---|
| 672 | | } |
|---|
| 673 | | if (RT_SUCCESS(rc) && found) |
|---|
| 674 | | if ( (isGuest && (it->mFlags & RDONLYGUEST)) |
|---|
| 675 | | || (!isGuest && (it->mFlags & RDONLYHOST)) |
|---|
| 676 | | ) |
|---|
| 677 | | rc = VERR_PERMISSION_DENIED; |
|---|
| 678 | | |
|---|
| 679 | | /* |
|---|
| 680 | | * And delete the property if all is well. |
|---|
| 681 | | */ |
|---|
| 682 | | if (RT_SUCCESS(rc) && found) |
|---|
| 683 | | { |
|---|
| 684 | | mProperties.erase(it); |
|---|
| 685 | | // if (isGuest) /* Notify the host even for properties that the host |
|---|
| 686 | | // * changed. Less efficient, but ensures consistency. */ |
|---|
| 687 | | notifyHost(pcszName); |
|---|
| 688 | | } |
|---|
| 689 | | LogFlowThisFunc(("rc = %Rrc\n", rc)); |
|---|
| 690 | | return rc; |
|---|
| 691 | | } |
|---|
| 692 | | |
|---|
| 693 | | /** |
|---|
| 694 | | * Enumerate guest properties by mask, checking the validity |
|---|
| | 452 | int Service::setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest) |
|---|
| | 453 | { |
|---|
| | 454 | int rc = VINF_SUCCESS; |
|---|
| | 455 | char *pszName, *pszValue; |
|---|
| | 456 | uint32_t cchName, cchValue; |
|---|
| | 457 | uint32_t fFlags = NILFLAG; |
|---|
| | 458 | |
|---|
| | 459 | LogFlowThisFunc(("\n")); |
|---|
| | 460 | AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ |
|---|
| | 461 | /* |
|---|
| | 462 | * First of all, make sure that we won't exceed the maximum number of properties. |
|---|
| | 463 | */ |
|---|
| | 464 | { |
|---|
| | 465 | unsigned cChildren = 0; |
|---|
| | 466 | for (PCFGMNODE pChild = CFGMR3GetFirstChild(mpValueNode); pChild != 0; pChild = CFGMR3GetNextChild(pChild)) |
|---|
| | 467 | ++cChildren; |
|---|
| | 468 | if (cChildren >= MAX_PROPS) |
|---|
| | 469 | rc = VERR_TOO_MUCH_DATA; |
|---|
| | 470 | } |
|---|
| | 471 | /* |
|---|
| | 472 | * General parameter correctness checking. |
|---|
| | 473 | */ |
|---|
| | 474 | if ( RT_SUCCESS(rc) |
|---|
| | 475 | && ( (cParms < 2) || (cParms > 4) /* Hardcoded value as the next lines depend on it. */ |
|---|
| | 476 | || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ |
|---|
| | 477 | || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* value */ |
|---|
| | 478 | || ((3 == cParms) && (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR)) /* flags */ |
|---|
| | 479 | ) |
|---|
| | 480 | ) |
|---|
| | 481 | rc = VERR_INVALID_PARAMETER; |
|---|
| | 482 | /* |
|---|
| | 483 | * Check the values passed in the parameters for correctness. |
|---|
| | 484 | */ |
|---|
| | 485 | if (RT_SUCCESS(rc)) |
|---|
| | 486 | rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cchName); |
|---|
| | 487 | if (RT_SUCCESS(rc)) |
|---|
| | 488 | rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pszValue, &cchValue); |
|---|
| | 489 | if (RT_SUCCESS(rc)) |
|---|
| | 490 | rc = validateName(pszName, cchName); |
|---|
| | 491 | if (RT_SUCCESS(rc)) |
|---|
| | 492 | rc = validateValue(pszValue, cchValue); |
|---|
| | 493 | |
|---|
| | 494 | /* |
|---|
| | 495 | * If the property already exists, check its flags to see if we are allowed |
|---|
| | 496 | * to change it. |
|---|
| | 497 | */ |
|---|
| | 498 | if (RT_SUCCESS(rc)) |
|---|
| | 499 | { |
|---|
| | 500 | CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); /* Failure is no problem here. */ |
|---|
| | 501 | if ( (isGuest && (fFlags & RDONLYGUEST)) |
|---|
| | 502 | || (!isGuest && (fFlags & RDONLYHOST)) |
|---|
| | 503 | ) |
|---|
| | 504 | rc = VERR_PERMISSION_DENIED; |
|---|
| | 505 | } |
|---|
| | 506 | |
|---|
| | 507 | /* |
|---|
| | 508 | * Check whether the user supplied flags (if any) are valid. |
|---|
| | 509 | */ |
|---|
| | 510 | if (RT_SUCCESS(rc) && (3 == cParms)) |
|---|
| | 511 | { |
|---|
| | 512 | char *pszFlags; |
|---|
| | 513 | uint32_t cchFlags; |
|---|
| | 514 | rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags); |
|---|
| | 515 | if (RT_SUCCESS(rc)) |
|---|
| | 516 | rc = validateFlags(pszFlags, &fFlags); |
|---|
| | 517 | } |
|---|
| | 518 | /* |
|---|
| | 519 | * Set the actual value |
|---|
| | 520 | */ |
|---|
| | 521 | if (RT_SUCCESS(rc)) |
|---|
| | 522 | { |
|---|
| | 523 | RTTIMESPEC time; |
|---|
| | 524 | CFGMR3RemoveValue(mpValueNode, pszName); |
|---|
| | 525 | CFGMR3RemoveValue(mpTimestampNode, pszName); |
|---|
| | 526 | CFGMR3RemoveValue(mpFlagsNode, pszName); |
|---|
| | 527 | rc = CFGMR3InsertString(mpValueNode, pszName, pszValue); |
|---|
| | 528 | if (RT_SUCCESS(rc)) |
|---|
| | 529 | rc = CFGMR3InsertInteger(mpTimestampNode, pszName, |
|---|
| | 530 | RTTimeSpecGetNano(RTTimeNow(&time))); |
|---|
| | 531 | if (RT_SUCCESS(rc)) |
|---|
| | 532 | rc = CFGMR3InsertInteger(mpFlagsNode, pszName, fFlags); |
|---|
| | 533 | /* If anything goes wrong, make sure that we leave a clean state |
|---|
| | 534 | * behind. */ |
|---|
| | 535 | if (RT_FAILURE(rc)) |
|---|
| | 536 | { |
|---|
| | 537 | CFGMR3RemoveValue(mpValueNode, pszName); |
|---|
| | 538 | CFGMR3RemoveValue(mpTimestampNode, pszName); |
|---|
| | 539 | CFGMR3RemoveValue(mpFlagsNode, pszName); |
|---|
| | 540 | } |
|---|
| | 541 | } |
|---|
| | 542 | /* |
|---|
| | 543 | * Send a notification to the host and return. |
|---|
| | 544 | */ |
|---|
| | 545 | if (RT_SUCCESS(rc)) |
|---|
| | 546 | { |
|---|
| | 547 | if (isGuest) |
|---|
| | 548 | notifyHost(pszName); |
|---|
| | 549 | Log2(("Set string %s, rc=%Rrc, value=%s\n", pszName, rc, pszValue)); |
|---|
| | 550 | } |
|---|
| | 551 | LogFlowThisFunc(("rc = %Rrc\n", rc)); |
|---|
| | 552 | return rc; |
|---|
| | 553 | } |
|---|
| | 554 | |
|---|
| | 555 | |
|---|
| | 556 | /** |
|---|
| | 557 | * Remove a value in the property registry by name, checking the validity |
|---|
| | 558 | * of the arguments passed. |
|---|
| | 559 | * |
|---|
| | 560 | * @returns iprt status value |
|---|
| | 561 | * @param cParms the number of HGCM parameters supplied |
|---|
| | 562 | * @param paParms the array of HGCM parameters |
|---|
| | 563 | * @thread HGCM |
|---|
| | 564 | */ |
|---|
| | 565 | int Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest) |
|---|
| | 566 | { |
|---|
| | 567 | int rc = VINF_SUCCESS; |
|---|
| | 568 | char *pszName; |
|---|
| | 569 | uint32_t cbName; |
|---|
| | 570 | |
|---|
| | 571 | LogFlowThisFunc(("\n")); |
|---|
| | 572 | AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */ |
|---|
| | 573 | |
|---|
| | 574 | /* |
|---|
| | 575 | * Check the user-supplied parameters. |
|---|
| | 576 | */ |
|---|
| | 577 | if ( (cParms != 1) /* Hardcoded value as the next lines depend on it. */ |
|---|
| | 578 | || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */ |
|---|
| | 579 | ) |
|---|
| | 580 | rc = VERR_INVALID_PARAMETER; |
|---|
| | 581 | if (RT_SUCCESS(rc)) |
|---|
| | 582 | rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cbName); |
|---|
| | 583 | if (RT_SUCCESS(rc)) |
|---|
| | 584 | rc = validateName(pszName, cbName); |
|---|
| | 585 | |
|---|
| | 586 | /* |
|---|
| | 587 | * If the property already exists, check its flags to see if we are allowed |
|---|
| | 588 | * to change it. |
|---|
| | 589 | */ |
|---|
| | 590 | if (RT_SUCCESS(rc)) |
|---|
| | 591 | { |
|---|
| | 592 | uint32_t fFlags = NILFLAG; |
|---|
| | 593 | CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); /* Failure is no problem here. */ |
|---|
| | 594 | if ( (isGuest && (fFlags & RDONLYGUEST)) |
|---|
| | 595 | || (!isGuest && (fFlags & RDONLYHOST)) |
|---|
| | 596 | ) |
|---|
| | 597 | rc = VERR_PERMISSION_DENIED; |
|---|
| | 598 | } |
|---|
| | 599 | |
|---|
| | 600 | /* |
|---|
| | 601 | * And delete the property if all is well. |
|---|
| | 602 | */ |
|---|
| | 603 | if (RT_SUCCESS(rc)) |
|---|
| | 604 | { |
|---|
| | 605 | CFGMR3RemoveValue(mpValueNode, pszName); |
|---|
| | 606 | if (isGuest) |
|---|
| | 607 | notifyHost(pszName); |
|---|
| | 608 | } |
|---|
| | 609 | LogFlowThisFunc(("rc = %Rrc\n", rc)); |
|---|
| | 610 | return rc; |
|---|
| | 611 | } |
|---|
| | 612 | |
|---|
| | 613 | /** |
|---|
| | 614 | * Enumerate guest properties by mask, checking the validity |
|---|
| | 615 | * of the arguments passed. |
|---|
| | 616 | * |
|---|
| | 617 | * @returns iprt status value |
|---|
| | 618 | * @param cParms the number of HGCM parameters supplied |
|---|
| | 619 | * @param paParms the array of HGCM parameters |
|---|
| | 620 | * @thread HGCM |
|---|
| | 621 | */ |
|---|
| 741 | | /* |
|---|
| 742 | | * Next enumerate into a temporary buffer. This can throw, but this is |
|---|
| 743 | | * not a problem as we have nothing to roll back. |
|---|
| 744 | | */ |
|---|
| 745 | | std::string buffer; |
|---|
| 746 | | for (PropertyList::const_iterator it = mProperties.begin(); |
|---|
| 747 | | RT_SUCCESS(rc) && (it != mProperties.end()); ++it) |
|---|
| 748 | | { |
|---|
| 749 | | if ( matchAll |
|---|
| 750 | | || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX, |
|---|
| 751 | | it->mName.c_str(), RTSTR_MAX, NULL) |
|---|
| | 673 | /* |
|---|
| | 674 | * Next enumerate all values in the current node into a temporary buffer. |
|---|
| | 675 | */ |
|---|
| | 676 | RTMemAutoPtr<char> TmpBuf; |
|---|
| | 677 | uint32_t cchTmpBuf = 0, iTmpBuf = 0; |
|---|
| | 678 | PCFGMLEAF pLeaf = CFGMR3GetFirstValue(mpValueNode); |
|---|
| | 679 | while ((pLeaf != NULL) && RT_SUCCESS(rc)) |
|---|
| | 680 | { |
|---|
| | 681 | /* Reallocate the buffer if it has got too tight */ |
|---|
| | 682 | if (iTmpBuf + BLOCKINCR > cchTmpBuf) |
|---|
| | 683 | { |
|---|
| | 684 | cchTmpBuf += BLOCKINCR * 2; |
|---|
| | 685 | if (!TmpBuf.realloc(cchTmpBuf)) |
|---|
| | 686 | rc = VERR_NO_MEMORY; |
|---|
| | 687 | } |
|---|
| | 688 | /* Fetch the name into the buffer and if it matches one of the |
|---|
| | 689 | * patterns, add its value and an empty timestamp and flags. If it |
|---|
| | 690 | * doesn't match, we simply overwrite it in the buffer. */ |
|---|
| | 691 | if (RT_SUCCESS(rc)) |
|---|
| | 692 | rc = CFGMR3GetValueName(pLeaf, &TmpBuf[iTmpBuf], cchTmpBuf - iTmpBuf); |
|---|
| | 693 | /* Only increment the buffer offest if the name matches, otherwise we |
|---|
| | 694 | * overwrite it next iteration. */ |
|---|
| | 695 | if ( RT_SUCCESS(rc) |
|---|
| | 696 | && ( matchAll |
|---|
| | 697 | || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX, |
|---|
| | 698 | &TmpBuf[iTmpBuf], RTSTR_MAX, |
|---|
| | 699 | NULL) |
|---|
| | 700 | ) |
|---|