Changeset 13916 in vbox for trunk/src/VBox/HostServices/GuestProperties
- Timestamp:
- Nov 6, 2008 1:48:05 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 38926
- Location:
- trunk/src/VBox/HostServices/GuestProperties
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestProperties/Makefile.kmk
r13574 r13916 37 37 $(PATH_TOOL_$(VBOX_VCC_TOOL)_ATLMFC_INC) \ 38 38 $(VBOX_PATH_SDK) 39 # For now! 40 VBoxGuestPropSvc_CXXFLAGS.win = -EHsc 39 41 40 42 VBoxGuestPropSvc_SOURCES = \ -
trunk/src/VBox/HostServices/GuestProperties/service.cpp
r13837 r13916 46 46 #include <VBox/HostServices/GuestPropertySvc.h> 47 47 48 #include <memory> /* for auto_ptr */ 49 #include <string> 50 #include <list> 51 48 #include <VBox/log.h> 52 49 #include <iprt/err.h> 53 50 #include <iprt/assert.h> … … 59 56 #include <iprt/req.h> 60 57 #include <iprt/thread.h> 61 #include <VBox/log.h> 62 63 /******************************************************************************* 64 * Internal functions * 65 *******************************************************************************/ 66 /** Extract a pointer value from an HGCM parameter structure */ 67 static int VBoxHGCMParmPtrGet (VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb) 68 { 69 if (pParm->type == VBOX_HGCM_SVC_PARM_PTR) 70 { 71 *ppv = pParm->u.pointer.addr; 72 *pcb = pParm->u.pointer.size; 73 return VINF_SUCCESS; 74 } 75 76 return VERR_INVALID_PARAMETER; 77 } 78 79 /** Extract a constant pointer value from an HGCM parameter structure */ 80 static int VBoxHGCMParmPtrConstGet (VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb) 81 { 82 if (pParm->type == VBOX_HGCM_SVC_PARM_PTR) 83 { 84 *ppv = pParm->u.pointer.addr; 85 *pcb = pParm->u.pointer.size; 86 return VINF_SUCCESS; 87 } 88 89 return VERR_INVALID_PARAMETER; 90 } 91 92 /** Set a uint32_t value to an HGCM parameter structure */ 93 static void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32) 94 { 95 pParm->type = VBOX_HGCM_SVC_PARM_32BIT; 96 pParm->u.uint32 = u32; 97 } 98 99 /** Set a uint64_t value to an HGCM parameter structure */ 100 static void VBoxHGCMParmUInt64Set (VBOXHGCMSVCPARM *pParm, uint64_t u64) 101 { 102 pParm->type = VBOX_HGCM_SVC_PARM_64BIT; 103 pParm->u.uint64 = u64; 104 } 105 106 /** Set a pointer value to an HGCM parameter structure */ 107 static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb) 108 { 109 pParm->type = VBOX_HGCM_SVC_PARM_PTR; 110 pParm->u.pointer.addr = pv; 111 pParm->u.pointer.size = cb; 112 } 58 59 #include <memory> /* for auto_ptr */ 60 #include <string> 61 #include <list> 113 62 114 63 namespace guestProp { … … 135 84 /** The property flags */ 136 85 uint32_t mFlags; 86 87 /** Default constructor */ 88 Property() : mName(""), mValue(""), mTimestamp(0), mFlags(NILFLAG) {} 137 89 /** Constructor with const char * */ 138 90 Property(const char *pcszName, const char *pcszValue, … … 150 102 /** The property list */ 151 103 PropertyList mProperties; 104 /** The list of property changes for guest notifications */ 105 PropertyList mGuestNotifications; 152 106 /** @todo we should have classes for thread and request handler thread */ 153 107 /** Queue of outstanding property change notifications */ … … 259 213 int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest); 260 214 int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 261 void notifyHost(const char *pszProperty); 215 int getNotification(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 216 void doNotifications(const char *pszProperty, uint64_t u64Timestamp); 262 217 static DECLCALLBACK(int) reqNotify(PFNHGCMSVCEXT pfnCallback, 263 218 void *pvData, char *pszName, … … 310 265 * a string terminator. 311 266 */ 312 int rc = RTStrValidateEncodingEx(pszName, RT_MIN(cbName, (uint32_t) MAX_NAME_LEN), 313 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED); 267 int rc = VINF_SUCCESS; 314 268 if (RT_SUCCESS(rc) && (cbName < 2)) 315 269 rc = VERR_INVALID_PARAMETER; 270 if (RT_SUCCESS(rc)) 271 rc = RTStrValidateEncodingEx(pszName, RT_MIN(cbName, (uint32_t) MAX_NAME_LEN), 272 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED); 316 273 317 274 LogFlowFunc(("returning %Rrc\n", rc)); … … 335 292 /* 336 293 * Validate the value, checking that it's proper UTF-8 and has 337 * a string terminator. Don't pass a 0 length request to the 338 * validator since it won't find any '\0' then. 339 */ 340 int rc = VINF_SUCCESS; 341 if (cbValue) 294 * a string terminator. 295 */ 296 int rc = VINF_SUCCESS; 297 if (RT_SUCCESS(rc) && (cbValue < 2)) 298 rc = VERR_INVALID_PARAMETER; 299 if (RT_SUCCESS(rc)) 342 300 rc = RTStrValidateEncodingEx(pszValue, RT_MIN(cbValue, (uint32_t) MAX_VALUE_LEN), 343 301 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED); … … 368 326 */ 369 327 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))328 || RT_FAILURE(paParms[0].getPointer ((void **) &ppNames, &cbDummy)) 329 || RT_FAILURE(paParms[1].getPointer ((void **) &ppValues, &cbDummy)) 330 || RT_FAILURE(paParms[2].getPointer ((void **) &pTimestamps, &cbDummy)) 331 || RT_FAILURE(paParms[3].getPointer ((void **) &ppFlags, &cbDummy)) 374 332 ) 375 333 rc = VERR_INVALID_PARAMETER; … … 464 422 */ 465 423 LogFlowThisFunc(("\n")); 466 if ( (cParms != 4)/* Hardcoded value as the next lines depend on it. */467 || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */468 || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* buffer */424 if ( cParms != 4 /* Hardcoded value as the next lines depend on it. */ 425 || RT_FAILURE (paParms[0].getPointer ((const void **) &pcszName, &cchName)) /* name */ 426 || RT_FAILURE (paParms[1].getPointer ((void **) &pchBuf, &cchBuf)) /* buffer */ 469 427 ) 470 428 rc = VERR_INVALID_PARAMETER; 471 if (RT_SUCCESS(rc))472 rc = VBoxHGCMParmPtrConstGet(&paParms[0], (const void **) &pcszName, &cchName);473 if (RT_SUCCESS(rc))474 rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf);475 429 if (RT_SUCCESS(rc)) 476 430 rc = validateName(pcszName, cchName); … … 500 454 { 501 455 cchBufActual = it->mValue.size() + 1 + cchFlags; 502 VBoxHGCMParmUInt32Set(&paParms[3],cchBufActual);456 paParms[3].setUInt32 (cchBufActual); 503 457 } 504 458 if (RT_SUCCESS(rc) && (cchBufActual > cchBuf)) … … 510 464 pchBuf[it->mValue.size()] = '\0'; /* Terminate the value */ 511 465 strcpy(pchBuf + it->mValue.size() + 1, szFlags); 512 VBoxHGCMParmUInt64Set(&paParms[2],it->mTimestamp);466 paParms[2].setUInt64 (it->mTimestamp); 513 467 } 514 468 … … 540 494 uint32_t cchName, cchValue, cchFlags = 0; 541 495 uint32_t fFlags = NILFLAG; 496 RTTIMESPEC time; 497 uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time)); 542 498 543 499 LogFlowThisFunc(("\n")); … … 553 509 if ( RT_SUCCESS(rc) 554 510 && ( (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 */511 || RT_FAILURE(paParms[0].getPointer ((const void **) &pcszName, 512 &cchName)) /* name */ 513 || RT_FAILURE(paParms[1].getPointer ((const void **) &pcszValue, 514 &cchValue)) /* value */ 559 515 || ( (3 == cParms) 560 && RT_FAILURE( VBoxHGCMParmPtrConstGet(&paParms[2],561 (const void **) &pcszFlags,&cchFlags)) /* flags */516 && RT_FAILURE(paParms[2].getPointer ((const void **) &pcszFlags, 517 &cchFlags)) /* flags */ 562 518 ) 563 519 ) … … 602 558 if (RT_SUCCESS(rc)) 603 559 { 604 RTTIMESPEC time;605 uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time));606 560 if (found) 607 561 { … … 621 575 // if (isGuest) /* Notify the host even for properties that the host 622 576 // * changed. Less efficient, but ensures consistency. */ 623 notifyHost(pcszName);577 doNotifications(pcszName, u64TimeNano); 624 578 Log2(("Set string %s, rc=%Rrc, value=%s\n", pcszName, rc, pcszValue)); 625 579 } … … 651 605 */ 652 606 if ( (cParms != 1) /* Hardcoded value as the next lines depend on it. */ 653 || RT_FAILURE( VBoxHGCMParmPtrConstGet(&paParms[0],654 (const void **) &pcszName,&cbName)) /* name */607 || RT_FAILURE(paParms[0].getPointer ((const void **) &pcszName, 608 &cbName)) /* name */ 655 609 ) 656 610 rc = VERR_INVALID_PARAMETER; … … 682 636 if (RT_SUCCESS(rc) && found) 683 637 { 638 RTTIMESPEC time; 639 uint64_t u64Timestamp = RTTimeSpecGetNano(RTTimeNow(&time)); 684 640 mProperties.erase(it); 685 641 // if (isGuest) /* Notify the host even for properties that the host 686 642 // * changed. Less efficient, but ensures consistency. */ 687 notifyHost(pcszName);643 doNotifications(pcszName, u64Timestamp); 688 644 } 689 645 LogFlowThisFunc(("rc = %Rrc\n", rc)); … … 711 667 LogFlowThisFunc(("\n")); 712 668 if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */ 713 || RT_FAILURE(VBoxHGCMParmPtrConstGet(&paParms[0], 714 (const void **) &pcchPatterns, &cchPatterns)) /* patterns */ 715 || RT_FAILURE(VBoxHGCMParmPtrGet(&paParms[1], 716 (void **) &pchBuf, &cchBuf)) /* return buffer */ 669 || RT_FAILURE(paParms[0].getPointer ((const void **) &pcchPatterns, 670 &cchPatterns)) /* patterns */ 671 || RT_FAILURE(paParms[1].getPointer ((void **) &pchBuf, &cchBuf)) /* return buffer */ 717 672 ) 718 673 rc = VERR_INVALID_PARAMETER; … … 777 732 if (RT_SUCCESS(rc)) 778 733 { 779 VBoxHGCMParmUInt32Set(&paParms[2],buffer.size());734 paParms[2].setUInt32 (buffer.size()); 780 735 /* Copy the memory if it fits into the guest buffer */ 781 736 if (buffer.size() <= cchBuf) … … 788 743 789 744 /** 790 * Notify the service owner that a property has been added/deleted/changed 791 * @param pszProperty the name of the property which has changed 745 * Get the next guest notification. 746 * 747 * @returns iprt status value 748 * @param cParms the number of HGCM parameters supplied 749 * @param paParms the array of HGCM parameters 750 * @thread HGCM 751 */ 752 int Service::getNotification(uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 753 { 754 int rc = VINF_SUCCESS; 755 char *pchBuf; 756 uint32_t cchBuf = 0; 757 uint64_t u64Timestamp; 758 bool warn = false; 759 760 /* 761 * Get the HGCM function arguments and perform basic verification. 762 */ 763 LogFlowThisFunc(("\n")); 764 if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */ 765 || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp)) /* timestamp */ 766 || RT_FAILURE(paParms[1].getPointer ((void **) &pchBuf, &cchBuf)) /* return buffer */ 767 || cchBuf < 1 768 ) 769 rc = VERR_INVALID_PARAMETER; 770 771 /* 772 * Find the change to notify of. 773 */ 774 Property next; 775 /* Return the oldest notification if no timestamp was specified. */ 776 if (RT_SUCCESS(rc) && !mGuestNotifications.empty() && u64Timestamp == 0) 777 next = mGuestNotifications.front(); 778 /* Only search if the guest hasn't seen the most recent notification. */ 779 else if ( RT_SUCCESS(rc) 780 && !mGuestNotifications.empty() 781 && mGuestNotifications.back().mTimestamp != u64Timestamp) 782 { 783 /* We count backwards, as the guest should normally be querying the 784 * most recent events. */ 785 PropertyList::const_reverse_iterator it = mGuestNotifications.rbegin(); 786 for ( ; it != mGuestNotifications.rend() 787 && it->mTimestamp != u64Timestamp; 788 ++it 789 ) {} 790 /* Warn if the timestamp was not found. */ 791 if (it == mGuestNotifications.rend()) 792 warn = true; 793 /* This is a reverse iterator, so --it goes up the list. */ 794 --it; 795 next = *it; 796 } 797 798 /* 799 * Format the data to write to the buffer. 800 */ 801 std::string buffer; 802 if (RT_SUCCESS(rc)) 803 { 804 char szFlags[MAX_FLAGS_LEN]; 805 rc = writeFlags(next.mFlags, szFlags); 806 if (RT_SUCCESS(rc)) 807 { 808 buffer += next.mName; 809 buffer += '\0'; 810 buffer += next.mValue; 811 buffer += '\0'; 812 buffer += szFlags; 813 buffer += '\0'; 814 u64Timestamp = next.mTimestamp; 815 } 816 } 817 818 /* 819 * Write out the data. 820 */ 821 paParms[0].setUInt64(u64Timestamp); 822 paParms[2].setUInt32(buffer.size()); 823 if (RT_SUCCESS(rc) && buffer.size() <= cchBuf) 824 buffer.copy(pchBuf, cchBuf); 825 else if (RT_SUCCESS(rc)) 826 rc = VERR_BUFFER_OVERFLOW; 827 if (RT_SUCCESS(rc) && warn) 828 rc = VWRN_NOT_FOUND; 829 return rc; 830 } 831 832 /** 833 * Notify the service owner and the guest that a property has been 834 * added/deleted/changed 835 * @param pszProperty the name of the property which has changed 836 * @param u64Timestamp the time at which the change took place 792 837 * @note this call allocates memory which the reqNotify request is expected to 793 838 * free again, using RTStrFree(). … … 795 840 * @thread HGCM service 796 841 */ 797 void Service::notifyHost(const char *pszProperty) 798 { 799 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD 842 void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) 843 { 800 844 char szFlags[MAX_FLAGS_LEN]; 801 845 char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL; 802 846 int rc = VINF_SUCCESS; 803 847 804 if (NULL == mpfnHostCallback) 805 return; /* Nothing to do. */ 848 AssertPtrReturnVoid(pszProperty); 806 849 PropertyList::const_iterator it; 807 850 bool found = false; … … 814 857 } 815 858 /* 816 * First case: if the property exists then send the host its current value 817 */ 818 if (found) 819 { 859 * First case: if the property exists then send its current value 860 */ 861 if (found && mpfnHostCallback != NULL) 862 { 863 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD 864 /* Send out a host notification */ 820 865 rc = writeFlags(it->mFlags, szFlags); 821 866 if (RT_SUCCESS(rc)) … … 831 876 (uint32_t) RT_HIDWORD(it->mTimestamp), 832 877 (uint32_t) RT_LODWORD(it->mTimestamp), pszFlags); 833 } 834 else 878 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */ 879 } 880 if (found) 881 { 882 /* Add the change to the queue for guest notifications */ 883 if (RT_SUCCESS(rc)) 884 { 885 try 886 { 887 mGuestNotifications.push_back(*it); 888 } 889 catch (std::bad_alloc) 890 { 891 rc = VERR_NO_MEMORY; 892 } 893 } 894 } 895 835 896 /* 836 897 * Second case: if the property does not exist then send the host an empty 837 898 * value 838 899 */ 839 { 900 if (!found && mpfnHostCallback != NULL) 901 { 902 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD 903 /* Send out a host notification */ 840 904 rc = RTStrDupEx(&pszName, pszProperty); 841 905 if (RT_SUCCESS(rc)) 842 906 rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT, 843 907 (PFNRT)Service::reqNotify, 7, mpfnHostCallback, 844 mpvHostData, pszName, NULL, 0, 0, NULL); 845 } 908 mpvHostData, pszName, NULL, 909 RT_HIDWORD(u64Timestamp), 910 RT_LODWORD(u64Timestamp), NULL); 911 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */ 912 } 913 if (!found) 914 { 915 /* Add the change to the queue for guest notifications */ 916 if (RT_SUCCESS(rc)) 917 { 918 try 919 { 920 mGuestNotifications.push_back(Property(pszProperty, "", 921 u64Timestamp, NILFLAG) 922 ); 923 } 924 catch (std::bad_alloc) 925 { 926 rc = VERR_NO_MEMORY; 927 } 928 } 929 } 930 if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS) 931 mGuestNotifications.pop_front(); 846 932 if (RT_FAILURE(rc)) /* clean up if we failed somewhere */ 847 933 { … … 850 936 RTStrFree(pszFlags); 851 937 } 852 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */853 938 } 854 939 … … 932 1017 LogFlowFunc(("ENUM_PROPS\n")); 933 1018 rc = enumProps(cParms, paParms); 1019 break; 1020 1021 /* The guest wishes to get the next property notification */ 1022 case GET_NOTIFICATION: 1023 LogFlowFunc(("GET_NOTIFICATION\n")); 1024 rc = getNotification(cParms, paParms); 934 1025 break; 935 1026 -
trunk/src/VBox/HostServices/GuestProperties/testcase/Makefile.kmk
r13779 r13916 42 42 OTHERS += $(PATH_tstGuestPropSvc)/tstGuestPropSvc.run 43 43 $$(PATH_tstGuestPropSvc)/tstGuestPropSvc.run: $$(INSTARGET_tstGuestPropSvc) 44 $(INSTARGET_tstGuestPropSvc) quiet44 export VBOX_LOG_DEST=nofile; $(INSTARGET_tstGuestPropSvc) quiet 45 45 $(QUIET)$(APPEND) -t "$@" "done" 46 46 endif -
trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
r13781 r13916 32 32 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable); 33 33 34 /** Set a pointer value to an HGCM parameter structure */35 static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)36 {37 pParm->type = VBOX_HGCM_SVC_PARM_PTR;38 pParm->u.pointer.addr = pv;39 pParm->u.pointer.size = cb;40 }41 42 /** Extract a uint64_t value from an HGCM parameter structure */43 static int VBoxHGCMParmUInt32Get (VBOXHGCMSVCPARM *pParm, uint32_t *pu32Value)44 {45 if (pParm->type == VBOX_HGCM_SVC_PARM_32BIT)46 {47 *pu32Value = pParm->u.uint32;48 return VINF_SUCCESS;49 }50 51 return VERR_INVALID_PARAMETER;52 }53 54 /** Extract a uint64_t value from an HGCM parameter structure */55 static int VBoxHGCMParmUInt64Get (VBOXHGCMSVCPARM *pParm, uint64_t *pu64Value)56 {57 if (pParm->type == VBOX_HGCM_SVC_PARM_64BIT)58 {59 *pu64Value = pParm->u.uint64;60 return VINF_SUCCESS;61 }62 63 return VERR_INVALID_PARAMETER;64 }65 66 34 /** Simple call handle structure for the guest call completion callback */ 67 35 struct VBOXHGCMCALLHANDLE_TYPEDEF … … 250 218 { 251 219 VBOXHGCMSVCPARM paParms[4]; 252 VBoxHGCMParmPtrSet(&paParms[0],(void *) apcszNameBlock, 0);253 VBoxHGCMParmPtrSet(&paParms[1],(void *) apcszValueBlock, 0);254 VBoxHGCMParmPtrSet(&paParms[2],(void *) au64TimestampBlock, 0);255 VBoxHGCMParmPtrSet(&paParms[3],(void *) apcszFlagsBlock, 0);220 paParms[0].setPointer ((void *) apcszNameBlock, 0); 221 paParms[1].setPointer ((void *) apcszValueBlock, 0); 222 paParms[2].setPointer ((void *) au64TimestampBlock, 0); 223 paParms[3].setPointer ((void *) apcszFlagsBlock, 0); 256 224 rc = ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4, 257 225 paParms); … … 370 338 char buffer[2048]; 371 339 VBOXHGCMSVCPARM paParms[3]; 372 VBoxHGCMParmPtrSet(&paParms[0], 373 (void *) enumStrings[i].pcszPatterns, 374 enumStrings[i].cchPatterns); 375 VBoxHGCMParmPtrSet(&paParms[1], 376 (void *) buffer, 377 enumStrings[i].cchBuffer - 1); 340 paParms[0].setPointer ((void *) enumStrings[i].pcszPatterns, 341 enumStrings[i].cchPatterns); 342 paParms[1].setPointer ((void *) buffer, 343 enumStrings[i].cchBuffer - 1); 378 344 AssertBreakStmt(sizeof(buffer) > enumStrings[i].cchBuffer, 379 345 rc = VERR_INTERNAL_ERROR); … … 391 357 { 392 358 uint32_t cchBufferActual; 393 rc = VBoxHGCMParmUInt32Get(&paParms[2],&cchBufferActual);359 rc = paParms[2].getUInt32 (&cchBufferActual); 394 360 if (RT_SUCCESS(rc) && cchBufferActual != enumStrings[i].cchBuffer) 395 361 { … … 403 369 if (RT_SUCCESS(rc)) 404 370 { 405 VBoxHGCMParmPtrSet(&paParms[1], (void *) buffer, 406 enumStrings[i].cchBuffer); 371 paParms[1].setPointer ((void *) buffer, enumStrings[i].cchBuffer); 407 372 rc = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 408 373 3, paParms); … … 495 460 strncat(szValue, setProperties[i].pcszValue, sizeof(szValue)); 496 461 strncat(szFlags, setProperties[i].pcszFlags, sizeof(szFlags)); 497 VBoxHGCMParmPtrSet(&paParms[0],szName, strlen(szName) + 1);498 VBoxHGCMParmPtrSet(&paParms[1],szValue, strlen(szValue) + 1);499 VBoxHGCMParmPtrSet(&paParms[2],szFlags, strlen(szFlags) + 1);462 paParms[0].setPointer (szName, strlen(szName) + 1); 463 paParms[1].setPointer (szValue, strlen(szValue) + 1); 464 paParms[2].setPointer (szFlags, strlen(szFlags) + 1); 500 465 if (setProperties[i].isHost) 501 466 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, … … 567 532 char szName[MAX_NAME_LEN] = ""; 568 533 strncat(szName, delProperties[i].pcszName, sizeof(szName)); 569 VBoxHGCMParmPtrSet(&paParms[0],szName, strlen(szName) + 1);534 paParms[0].setPointer (szName, strlen(szName) + 1); 570 535 if (delProperties[i].isHost) 571 536 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, … … 644 609 rc = VERR_INTERNAL_ERROR); 645 610 strncat(szName, getProperties[i].pcszName, sizeof(szName)); 646 VBoxHGCMParmPtrSet(&paParms[0],szName, strlen(szName) + 1);647 VBoxHGCMParmPtrSet(&paParms[1],szBuffer, sizeof(szBuffer));611 paParms[0].setPointer (szName, strlen(szName) + 1); 612 paParms[1].setPointer (szBuffer, sizeof(szBuffer)); 648 613 rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4, 649 614 paParms); … … 663 628 { 664 629 uint32_t u32ValueLen; 665 rc = VBoxHGCMParmUInt32Get(&paParms[3],&u32ValueLen);630 rc = paParms[3].getUInt32 (&u32ValueLen); 666 631 if (RT_FAILURE(rc)) 667 632 RTPrintf("Failed to get the size of the output buffer for property '%s'\n", … … 680 645 { 681 646 uint64_t u64Timestamp; 682 rc = VBoxHGCMParmUInt64Get(&paParms[2],&u64Timestamp);647 rc = paParms[2].getUInt64 (&u64Timestamp); 683 648 if (RT_FAILURE(rc)) 684 649 RTPrintf("Failed to get the timestamp for property '%s'\n", … … 699 664 } 700 665 666 /** Array of properties for testing GET_PROP_HOST. */ 667 static const struct 668 { 669 /** Buffer returned */ 670 const char *pchBuffer; 671 /** What size should the buffer be? */ 672 uint32_t cchBuffer; 673 } 674 getNotifications[] = 675 { 676 { "Red\0Stop!\0TRANSIENT", sizeof("Red\0Stop!\0TRANSIENT") }, 677 { "Amber\0Caution!\0", sizeof("Amber\0Caution!\0") }, 678 { "Green\0Go!\0READONLY", sizeof("Green\0Go!\0READONLY") }, 679 { "Blue\0What on earth...?\0", sizeof("Blue\0What on earth...?\0") }, 680 { "Red\0\0", sizeof("Red\0\0") }, 681 { "Amber\0\0", sizeof("Amber\0\0") }, 682 { NULL, 0 } 683 }; 684 685 /** 686 * Test the GET_NOTIFICATION function. 687 * @returns iprt status value to indicate whether the test went as expected. 688 * @note prints its own diagnostic information to stdout. 689 */ 690 int testGetNotification(VBOXHGCMSVCFNTABLE *pTable) 691 { 692 int rc = VINF_SUCCESS; 693 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; 694 char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN]; 695 696 RTPrintf("Testing the GET_NOTIFICATION call.\n"); 697 uint64_t u64Timestamp = 0; 698 uint32_t u32Size = 0; 699 VBOXHGCMSVCPARM paParms[3]; 700 701 /* Test "buffer too small" */ 702 paParms[0].setUInt64 (u64Timestamp); 703 paParms[1].setPointer ((void *) chBuffer, getNotifications[0].cchBuffer - 1); 704 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 705 GET_NOTIFICATION, 3, paParms); 706 if ( callHandle.rc != VERR_BUFFER_OVERFLOW 707 || RT_FAILURE(paParms[2].getUInt32 (&u32Size)) 708 || u32Size != getNotifications[0].cchBuffer 709 ) 710 { 711 RTPrintf("Getting notification for property '%s' with a too small buffer did not fail correctly.\n", 712 getNotifications[0].pchBuffer); 713 rc = VERR_UNRESOLVED_ERROR; 714 } 715 716 /* Test successful notification queries */ 717 for (unsigned i = 0; RT_SUCCESS(rc) && (getNotifications[i].pchBuffer != NULL); 718 ++i) 719 { 720 paParms[0].setUInt64 (u64Timestamp); 721 paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer)); 722 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 723 GET_NOTIFICATION, 3, paParms); 724 if ( RT_FAILURE(callHandle.rc) 725 || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp)) 726 || RT_FAILURE(paParms[2].getUInt32 (&u32Size)) 727 || u32Size != getNotifications[i].cchBuffer 728 || memcmp(chBuffer, getNotifications[i].pchBuffer, u32Size) != 0 729 ) 730 { 731 RTPrintf("Failed to get notification for property '%s'.\n", 732 getNotifications[i].pchBuffer); 733 rc = VERR_UNRESOLVED_ERROR; 734 } 735 } 736 737 /* Test when no new events are available */ 738 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 739 GET_NOTIFICATION, 3, paParms); 740 if ( RT_FAILURE(callHandle.rc) 741 || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp)) 742 || u64Timestamp != 0 743 ) 744 { 745 RTPrintf("Failed to signal properly that no new notifications are available.\n"); 746 rc = VERR_UNRESOLVED_ERROR; 747 } 748 749 /* Test a query with an unknown timestamp */ 750 paParms[0].setUInt64 (1); 751 paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer)); 752 if (RT_SUCCESS(rc)) 753 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 754 GET_NOTIFICATION, 3, paParms); 755 if ( RT_SUCCESS(rc) 756 && ( callHandle.rc != VWRN_NOT_FOUND 757 || RT_FAILURE(callHandle.rc) 758 || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp)) 759 || RT_FAILURE(paParms[2].getUInt32 (&u32Size)) 760 || u32Size != getNotifications[0].cchBuffer 761 || memcmp(chBuffer, getNotifications[0].pchBuffer, u32Size) != 0 762 ) 763 ) 764 { 765 RTPrintf("Problem getting notification for property '%s' with unknown timestamp, rc=%Rrc.\n", 766 getNotifications[0].pchBuffer, callHandle.rc); 767 rc = VERR_UNRESOLVED_ERROR; 768 } 769 return rc; 770 } 771 772 /** 773 * Test the GET_NOTIFICATION function when no notifications are available. 774 * @returns iprt status value to indicate whether the test went as expected. 775 * @note prints its own diagnostic information to stdout. 776 */ 777 int testNoNotifications(VBOXHGCMSVCFNTABLE *pTable) 778 { 779 int rc = VINF_SUCCESS; 780 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; 781 char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN]; 782 783 RTPrintf("Testing the GET_NOTIFICATION call when no notifications are available.\n"); 784 uint64_t u64Timestamp = 0; 785 uint32_t u32Size = 0; 786 VBOXHGCMSVCPARM paParms[3]; 787 788 paParms[0].setUInt64 (u64Timestamp); 789 paParms[1].setPointer ((void *) chBuffer, sizeof(chBuffer)); 790 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 791 GET_NOTIFICATION, 3, paParms); 792 if ( RT_FAILURE(callHandle.rc) 793 || RT_FAILURE(paParms[0].getUInt64 (&u64Timestamp)) 794 || u64Timestamp != 0 795 ) 796 { 797 RTPrintf("Failed to signal properly that no new notifications are available.\n"); 798 rc = VERR_UNRESOLVED_ERROR; 799 } 800 return rc; 801 } 802 701 803 int main(int argc, char **argv) 702 804 { … … 717 819 if (RT_FAILURE(testEnumPropsHost(&svcTable))) 718 820 return 1; 821 if (RT_FAILURE(testNoNotifications(&svcTable))) 822 return 1; 719 823 if (RT_FAILURE(testSetProp(&svcTable))) 720 824 return 1; … … 723 827 if (RT_FAILURE(testGetProp(&svcTable))) 724 828 return 1; 829 if (RT_FAILURE(testGetNotification(&svcTable))) 830 return 1; 725 831 RTPrintf("tstGuestPropSvc: SUCCEEDED.\n"); 726 832 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.