- Timestamp:
- Apr 5, 2024 12:23:48 PM (10 months ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r104003 r104178 968 968 }; 969 969 970 /** 971 * Generic class for handling a guest process output (i.e. stdout / stderr) stream. 972 */ 973 class GuestProcessOutputStream 974 { 975 public: 976 977 GuestProcessOutputStream(); 978 979 virtual ~GuestProcessOutputStream(); 980 981 public: 982 983 int AddData(const BYTE *pbData, size_t cbData); 984 985 void Destroy(); 986 987 #ifdef DEBUG 988 void Dump(const char *pszFile); 989 #endif 990 991 size_t GetOffset(void) const { return m_offBuf; } 992 993 size_t GetSize(void) const { return m_cbUsed; } 994 995 const BYTE *GetData(void) const { return m_pbBuffer; } 996 997 protected: 998 999 /** Maximum allowed size the stream buffer can grow to. 1000 * Defaults to 32 MB. */ 1001 size_t m_cbMax; 1002 /** Currently allocated size of internal stream buffer. */ 1003 size_t m_cbAllocated; 1004 /** Currently used size at m_offBuffer. */ 1005 size_t m_cbUsed; 1006 /** Current byte offset within the internal stream buffer. */ 1007 size_t m_offBuf; 1008 /** Internal stream buffer. */ 1009 BYTE *m_pbBuffer; 1010 }; 970 1011 971 1012 /** … … 1010 1051 * 1011 1052 * Only used for the busybox-like toolbox commands within VBoxService. 1053 * 1012 1054 * Deprecated, do not use anymore. 1013 1055 */ … … 1082 1124 * Deprecated, do not use anymore. 1083 1125 */ 1084 class GuestToolboxStream 1126 class GuestToolboxStream : public GuestProcessOutputStream 1085 1127 { 1086 1128 … … 1093 1135 public: 1094 1136 1095 int AddData(const BYTE *pbData, size_t cbData);1096 1097 void Destroy();1098 1099 #ifdef DEBUG1100 void Dump(const char *pszFile);1101 #endif1102 1103 size_t GetOffset(void) const { return m_offBuf; }1104 1105 size_t GetSize(void) const { return m_cbUsed; }1106 1107 1137 size_t GetBlocks(void) const { return m_cBlocks; } 1108 1138 … … 1111 1141 protected: 1112 1142 1113 /** Maximum allowed size the stream buffer can grow to.1114 * Defaults to 32 MB. */1115 size_t m_cbMax;1116 /** Currently allocated size of internal stream buffer. */1117 size_t m_cbAllocated;1118 /** Currently used size at m_offBuffer. */1119 size_t m_cbUsed;1120 /** Current byte offset within the internal stream buffer. */1121 size_t m_offBuf;1122 /** Internal stream buffer. */1123 BYTE *m_pbBuffer;1124 1143 /** How many completed stream blocks already were processed. */ 1125 1144 size_t m_cBlocks; -
trunk/src/VBox/Main/include/GuestProcessImpl.h
r98614 r104178 217 217 218 218 /** 219 * Wrapper class for running guest processes. 220 */ 221 class GuestProcessWrapper 222 { 223 public: 224 DECLARE_TRANSLATE_METHODS(GuestProcessWrapper) 225 226 GuestProcessWrapper(void); 227 228 virtual ~GuestProcessWrapper(void); 229 230 public: 231 232 int init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pvrcGuest); 233 234 void uninit(void); 235 236 /** Returns the stdout output from the guest process. */ 237 GuestProcessOutputStream &getStdOut(void) { return mStdOut; } 238 239 /** Returns the stderr output from the guest proces. */ 240 GuestProcessOutputStream &getStdErr(void) { return mStdErr; } 241 242 bool isRunning(void); 243 244 bool isTerminatedOk(void); 245 246 int getTerminationStatus(int32_t *piExitCode = NULL); 247 248 int terminate(uint32_t uTimeoutMS, int *pvrcGuest); 249 250 protected: 251 252 /** Pointer to session this toolbox object is bound to. */ 253 ComObjPtr<GuestSession> pSession; 254 /** Pointer to process object this object is bound to. */ 255 ComObjPtr<GuestProcess> pProcess; 256 /** The process startup info. */ 257 GuestProcessStartupInfo mStartupInfo; 258 /** Stream object for handling stdout data. */ 259 GuestProcessOutputStream mStdOut; 260 /** Stream object for handling stderr data. */ 261 GuestProcessOutputStream mStdErr; 262 }; 263 264 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 265 /** 219 266 * Internal class for handling the BusyBox-like tools built into VBoxService 220 267 * on the guest side. It's also called the VBoxService Toolbox (tm). … … 228 275 * Note! When implementing new functionality / commands, do *not* use this approach anymore! 229 276 * This class has to be kept to guarantee backwards-compatibility. 230 */ 231 class GuestProcessToolbox 277 * 278 * Deprecated, do not use anymore. 279 */ 280 class GuestProcessToolbox : public GuestProcessWrapper 232 281 { 233 282 public: 234 DECLARE_TRANSLATE_METHODS(GuestProcessTool )283 DECLARE_TRANSLATE_METHODS(GuestProcessToolbox) 235 284 236 285 GuestProcessToolbox(void); … … 240 289 public: 241 290 242 int init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pvrcGuest);243 244 void uninit(void);291 int wait(uint32_t fToolWaitFlags, int *pvrcGuest); 292 293 int waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *strmBlockOut, int *pvrcGuest); 245 294 246 295 int getCurrentBlock(uint32_t uHandle, GuestToolboxStreamBlock &strmBlock); … … 253 302 /** Returns the stderr output from the guest process tool. */ 254 303 GuestToolboxStream &getStdErr(void) { return mStdErr; } 255 256 int wait(uint32_t fToolWaitFlags, int *pvrcGuest);257 258 int waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStreamBlock, int *pvrcGuest);259 260 bool isRunning(void);261 262 bool isTerminatedOk(void);263 264 int getTerminationStatus(int32_t *piExitCode = NULL);265 266 int terminate(uint32_t uTimeoutMS, int *pvrcGuest);267 304 268 305 public: … … 282 319 * @{ */ 283 320 static int exitCodeToRc(const GuestProcessStartupInfo &startupInfo, int32_t iExitCode); 284 285 321 static int exitCodeToRc(const char *pszTool, int32_t iExitCode); 286 322 /** @} */ … … 293 329 protected: 294 330 295 /** Pointer to session this toolbox object is bound to. */296 ComObjPtr<GuestSession> pSession;297 /** Pointer to process object this toolbox object is bound to. */298 ComObjPtr<GuestProcess> pProcess;299 /** The toolbox' startup info. */300 GuestProcessStartupInfo mStartupInfo;301 331 /** Stream object for handling the toolbox' stdout data. */ 302 332 GuestToolboxStream mStdOut; … … 304 334 GuestToolboxStream mStdErr; 305 335 }; 336 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 306 337 307 338 #endif /* !MAIN_INCLUDED_GuestProcessImpl_h */ -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r102654 r104178 363 363 /** @} */ 364 364 365 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 365 366 /** @name Public internal methods for supporting older Guest Additions via 366 * VBoxService' built-in toolbox (< 7.1). 367 * VBoxService' built-in toolbox (< 7.1). Deprecated, do not use anymore. 367 368 * @{ */ 368 369 int i_directoryCreateViaToolbox(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pvrcGuest); … … 372 373 int i_fsObjQueryInfoViaToolbox(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pvrcGuest); 373 374 /** @} */ 375 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 374 376 375 377 public: -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r99393 r104178 530 530 /////////////////////////////////////////////////////////////////////////////// 531 531 532 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 533 /** @todo *NOT* thread safe yet! */ 534 /** @todo Add exception handling for STL stuff! */ 535 536 GuestToolboxStreamBlock::GuestToolboxStreamBlock(void) 537 : m_fComplete(false) { } 538 539 GuestToolboxStreamBlock::~GuestToolboxStreamBlock() 540 { 541 Clear(); 542 } 543 544 /** 545 * Clears (destroys) the currently stored stream pairs. 546 */ 547 void GuestToolboxStreamBlock::Clear(void) 548 { 549 m_fComplete = false; 550 m_mapPairs.clear(); 551 } 552 553 #ifdef DEBUG 554 /** 555 * Dumps the currently stored stream pairs to the (debug) log. 556 */ 557 void GuestToolboxStreamBlock::DumpToLog(void) const 558 { 559 LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items, fComplete=%RTbool):\n", 560 this, m_mapPairs.size(), m_fComplete)); 561 562 for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin(); 563 it != m_mapPairs.end(); ++it) 564 { 565 LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str())); 566 } 567 } 568 #endif 569 570 /** 571 * Returns a 64-bit signed integer of a specified key. 572 * 573 * @return VBox status code. VERR_NOT_FOUND if key was not found. 574 * @param pszKey Name of key to get the value for. 575 * @param piVal Pointer to value to return. 576 */ 577 int GuestToolboxStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const 578 { 579 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 580 AssertPtrReturn(piVal, VERR_INVALID_POINTER); 581 const char *pszValue = GetString(pszKey); 582 if (pszValue) 583 { 584 *piVal = RTStrToInt64(pszValue); 585 return VINF_SUCCESS; 586 } 587 return VERR_NOT_FOUND; 588 } 589 590 /** 591 * Returns a 64-bit integer of a specified key. 592 * 593 * @return int64_t Value to return, 0 if not found / on failure. 594 * @param pszKey Name of key to get the value for. 595 */ 596 int64_t GuestToolboxStreamBlock::GetInt64(const char *pszKey) const 597 { 598 int64_t iVal; 599 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal))) 600 return iVal; 601 return 0; 602 } 603 604 /** 605 * Returns the current number of stream pairs. 606 * 607 * @return uint32_t Current number of stream pairs. 608 */ 609 size_t GuestToolboxStreamBlock::GetCount(void) const 610 { 611 return m_mapPairs.size(); 612 } 613 614 /** 615 * Gets the return code (name = "rc") of this stream block. 616 * 617 * @return VBox status code. 618 * @retval VERR_NOT_FOUND if the return code string ("rc") was not found. 619 * @param fSucceedIfNotFound When set to @c true, this reports back VINF_SUCCESS when the key ("rc") is not found. 620 * This can happen with some (older) IPRT-provided tools such as RTPathRmCmd(), which only outputs 621 * rc on failure but not on success. Defaults to @c false. 622 */ 623 int GuestToolboxStreamBlock::GetVrc(bool fSucceedIfNotFound /* = false */) const 624 { 625 const char *pszValue = GetString("rc"); 626 if (pszValue) 627 return RTStrToInt16(pszValue); 628 if (fSucceedIfNotFound) 629 return VINF_SUCCESS; 630 /** @todo We probably should have a dedicated error for that, VERR_GSTCTL_GUEST_TOOLBOX_whatever. */ 631 return VERR_NOT_FOUND; 632 } 633 634 /** 635 * Returns a string value of a specified key. 636 * 637 * @return uint32_t Pointer to string to return, NULL if not found / on failure. 638 * @param pszKey Name of key to get the value for. 639 */ 640 const char *GuestToolboxStreamBlock::GetString(const char *pszKey) const 641 { 642 AssertPtrReturn(pszKey, NULL); 643 644 try 645 { 646 GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(pszKey); 647 if (itPairs != m_mapPairs.end()) 648 return itPairs->second.mValue.c_str(); 649 } 650 catch (const std::exception &ex) 651 { 652 RT_NOREF(ex); 653 } 654 return NULL; 655 } 656 657 /** 658 * Returns a 32-bit unsigned integer of a specified key. 659 * 660 * @return VBox status code. VERR_NOT_FOUND if key was not found. 661 * @param pszKey Name of key to get the value for. 662 * @param puVal Pointer to value to return. 663 */ 664 int GuestToolboxStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const 665 { 666 const char *pszValue = GetString(pszKey); 667 if (pszValue) 668 { 669 *puVal = RTStrToUInt32(pszValue); 670 return VINF_SUCCESS; 671 } 672 return VERR_NOT_FOUND; 673 } 674 675 /** 676 * Returns a 32-bit signed integer of a specified key. 677 * 678 * @returns 32-bit signed value 679 * @param pszKey Name of key to get the value for. 680 * @param iDefault The default to return on error if not found. 681 */ 682 int32_t GuestToolboxStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const 683 { 684 const char *pszValue = GetString(pszKey); 685 if (pszValue) 686 { 687 int32_t iRet; 688 int vrc = RTStrToInt32Full(pszValue, 0, &iRet); 689 if (RT_SUCCESS(vrc)) 690 return iRet; 691 ASSERT_GUEST_MSG_FAILED(("%s=%s\n", pszKey, pszValue)); 692 } 693 return iDefault; 694 } 695 696 /** 697 * Returns a 32-bit unsigned integer of a specified key. 698 * 699 * @return uint32_t Value to return, 0 if not found / on failure. 700 * @param pszKey Name of key to get the value for. 701 * @param uDefault The default value to return. 702 */ 703 uint32_t GuestToolboxStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const 704 { 705 uint32_t uVal; 706 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal))) 707 return uVal; 708 return uDefault; 709 } 710 711 /** 712 * Sets a value to a key or deletes a key by setting a NULL value. Extended version. 713 * 714 * @return VBox status code. 715 * @param pszKey Key name to process. 716 * @param cwcKey Maximum characters of \a pszKey to process. 717 * @param pszValue Value to set. Set NULL for deleting the key. 718 * @param cwcValue Maximum characters of \a pszValue to process. 719 * @param fOverwrite Whether a key can be overwritten with a new value if it already exists. Will assert otherwise. 720 */ 721 int GuestToolboxStreamBlock::SetValueEx(const char *pszKey, size_t cwcKey, const char *pszValue, size_t cwcValue, 722 bool fOverwrite /* = false */) 723 { 724 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 725 AssertReturn(cwcKey, VERR_INVALID_PARAMETER); 726 727 int vrc = VINF_SUCCESS; 728 try 729 { 730 Utf8Str const strKey(pszKey, cwcKey); 731 732 /* Take a shortcut and prevent crashes on some funny versions 733 * of STL if map is empty initially. */ 734 if (!m_mapPairs.empty()) 735 { 736 GuestCtrlStreamPairMapIter it = m_mapPairs.find(strKey); 737 if (it != m_mapPairs.end()) 738 { 739 if (pszValue == NULL) 740 m_mapPairs.erase(it); 741 else if (!fOverwrite) 742 AssertMsgFailedReturn(("Key '%*s' already exists! Value is '%s'\n", cwcKey, pszKey, m_mapPairs[strKey].mValue.c_str()), 743 VERR_ALREADY_EXISTS); 744 } 745 } 746 747 if (pszValue) 748 { 749 GuestToolboxStreamValue val(pszValue, cwcValue); 750 Log3Func(("strKey='%s', strValue='%s'\n", strKey.c_str(), val.mValue.c_str())); 751 m_mapPairs[strKey] = val; 752 } 753 } 754 catch (const std::exception &) 755 { 756 /** @todo set vrc? */ 757 } 758 return vrc; 759 } 760 761 /** 762 * Sets a value to a key or deletes a key by setting a NULL value. 763 * 764 * @return VBox status code. 765 * @param pszKey Key name to process. 766 * @param pszValue Value to set. Set NULL for deleting the key. 767 */ 768 int GuestToolboxStreamBlock::SetValue(const char *pszKey, const char *pszValue) 769 { 770 return SetValueEx(pszKey, RTSTR_MAX, pszValue, RTSTR_MAX); 771 } 772 773 /////////////////////////////////////////////////////////////////////////////// 774 775 GuestToolboxStream::GuestToolboxStream(void) 532 GuestProcessOutputStream::GuestProcessOutputStream(void) 776 533 : m_cbMax(_32M) 777 534 , m_cbAllocated(0) 778 535 , m_cbUsed(0) 779 536 , m_offBuf(0) 780 , m_pbBuffer(NULL) 781 , m_cBlocks(0) { } 782 783 GuestToolboxStream::~GuestToolboxStream(void) 537 , m_pbBuffer(NULL) { } 538 539 GuestProcessOutputStream::~GuestProcessOutputStream(void) 784 540 { 785 541 Destroy(); … … 794 550 * @param cbData Size (in bytes) of data to add. 795 551 */ 796 int Guest ToolboxStream::AddData(const BYTE *pbData, size_t cbData)552 int GuestProcessOutputStream::AddData(const BYTE *pbData, size_t cbData) 797 553 { 798 554 AssertPtrReturn(pbData, VERR_INVALID_POINTER); … … 865 621 * Destroys the internal data buffer. 866 622 */ 867 void Guest ToolboxStream::Destroy(void)623 void GuestProcessOutputStream::Destroy(void) 868 624 { 869 625 if (m_pbBuffer) … … 876 632 m_cbUsed = 0; 877 633 m_offBuf = 0; 878 m_cBlocks = 0;879 634 } 880 635 … … 886 641 * @param pszFile Absolute path to host file to dump the output to. 887 642 */ 888 void Guest ToolboxStream::Dump(const char *pszFile)643 void GuestProcessOutputStream::Dump(const char *pszFile) 889 644 { 890 645 LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n", … … 900 655 } 901 656 #endif /* DEBUG */ 657 658 /////////////////////////////////////////////////////////////////////////////// 659 660 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 661 /** @todo *NOT* thread safe yet! */ 662 /** @todo Add exception handling for STL stuff! */ 663 664 GuestToolboxStreamBlock::GuestToolboxStreamBlock(void) 665 : m_fComplete(false) { } 666 667 GuestToolboxStreamBlock::~GuestToolboxStreamBlock() 668 { 669 Clear(); 670 } 671 672 /** 673 * Clears (destroys) the currently stored stream pairs. 674 */ 675 void GuestToolboxStreamBlock::Clear(void) 676 { 677 m_fComplete = false; 678 m_mapPairs.clear(); 679 } 680 681 #ifdef DEBUG 682 /** 683 * Dumps the currently stored stream pairs to the (debug) log. 684 */ 685 void GuestToolboxStreamBlock::DumpToLog(void) const 686 { 687 LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items, fComplete=%RTbool):\n", 688 this, m_mapPairs.size(), m_fComplete)); 689 690 for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin(); 691 it != m_mapPairs.end(); ++it) 692 { 693 LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str())); 694 } 695 } 696 #endif 697 698 /** 699 * Returns a 64-bit signed integer of a specified key. 700 * 701 * @return VBox status code. VERR_NOT_FOUND if key was not found. 702 * @param pszKey Name of key to get the value for. 703 * @param piVal Pointer to value to return. 704 */ 705 int GuestToolboxStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const 706 { 707 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 708 AssertPtrReturn(piVal, VERR_INVALID_POINTER); 709 const char *pszValue = GetString(pszKey); 710 if (pszValue) 711 { 712 *piVal = RTStrToInt64(pszValue); 713 return VINF_SUCCESS; 714 } 715 return VERR_NOT_FOUND; 716 } 717 718 /** 719 * Returns a 64-bit integer of a specified key. 720 * 721 * @return int64_t Value to return, 0 if not found / on failure. 722 * @param pszKey Name of key to get the value for. 723 */ 724 int64_t GuestToolboxStreamBlock::GetInt64(const char *pszKey) const 725 { 726 int64_t iVal; 727 if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal))) 728 return iVal; 729 return 0; 730 } 731 732 /** 733 * Returns the current number of stream pairs. 734 * 735 * @return uint32_t Current number of stream pairs. 736 */ 737 size_t GuestToolboxStreamBlock::GetCount(void) const 738 { 739 return m_mapPairs.size(); 740 } 741 742 /** 743 * Gets the return code (name = "rc") of this stream block. 744 * 745 * @return VBox status code. 746 * @retval VERR_NOT_FOUND if the return code string ("rc") was not found. 747 * @param fSucceedIfNotFound When set to @c true, this reports back VINF_SUCCESS when the key ("rc") is not found. 748 * This can happen with some (older) IPRT-provided tools such as RTPathRmCmd(), which only outputs 749 * rc on failure but not on success. Defaults to @c false. 750 */ 751 int GuestToolboxStreamBlock::GetVrc(bool fSucceedIfNotFound /* = false */) const 752 { 753 const char *pszValue = GetString("rc"); 754 if (pszValue) 755 return RTStrToInt16(pszValue); 756 if (fSucceedIfNotFound) 757 return VINF_SUCCESS; 758 /** @todo We probably should have a dedicated error for that, VERR_GSTCTL_GUEST_TOOLBOX_whatever. */ 759 return VERR_NOT_FOUND; 760 } 761 762 /** 763 * Returns a string value of a specified key. 764 * 765 * @return uint32_t Pointer to string to return, NULL if not found / on failure. 766 * @param pszKey Name of key to get the value for. 767 */ 768 const char *GuestToolboxStreamBlock::GetString(const char *pszKey) const 769 { 770 AssertPtrReturn(pszKey, NULL); 771 772 try 773 { 774 GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(pszKey); 775 if (itPairs != m_mapPairs.end()) 776 return itPairs->second.mValue.c_str(); 777 } 778 catch (const std::exception &ex) 779 { 780 RT_NOREF(ex); 781 } 782 return NULL; 783 } 784 785 /** 786 * Returns a 32-bit unsigned integer of a specified key. 787 * 788 * @return VBox status code. VERR_NOT_FOUND if key was not found. 789 * @param pszKey Name of key to get the value for. 790 * @param puVal Pointer to value to return. 791 */ 792 int GuestToolboxStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const 793 { 794 const char *pszValue = GetString(pszKey); 795 if (pszValue) 796 { 797 *puVal = RTStrToUInt32(pszValue); 798 return VINF_SUCCESS; 799 } 800 return VERR_NOT_FOUND; 801 } 802 803 /** 804 * Returns a 32-bit signed integer of a specified key. 805 * 806 * @returns 32-bit signed value 807 * @param pszKey Name of key to get the value for. 808 * @param iDefault The default to return on error if not found. 809 */ 810 int32_t GuestToolboxStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const 811 { 812 const char *pszValue = GetString(pszKey); 813 if (pszValue) 814 { 815 int32_t iRet; 816 int vrc = RTStrToInt32Full(pszValue, 0, &iRet); 817 if (RT_SUCCESS(vrc)) 818 return iRet; 819 ASSERT_GUEST_MSG_FAILED(("%s=%s\n", pszKey, pszValue)); 820 } 821 return iDefault; 822 } 823 824 /** 825 * Returns a 32-bit unsigned integer of a specified key. 826 * 827 * @return uint32_t Value to return, 0 if not found / on failure. 828 * @param pszKey Name of key to get the value for. 829 * @param uDefault The default value to return. 830 */ 831 uint32_t GuestToolboxStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const 832 { 833 uint32_t uVal; 834 if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal))) 835 return uVal; 836 return uDefault; 837 } 838 839 /** 840 * Sets a value to a key or deletes a key by setting a NULL value. Extended version. 841 * 842 * @return VBox status code. 843 * @param pszKey Key name to process. 844 * @param cwcKey Maximum characters of \a pszKey to process. 845 * @param pszValue Value to set. Set NULL for deleting the key. 846 * @param cwcValue Maximum characters of \a pszValue to process. 847 * @param fOverwrite Whether a key can be overwritten with a new value if it already exists. Will assert otherwise. 848 */ 849 int GuestToolboxStreamBlock::SetValueEx(const char *pszKey, size_t cwcKey, const char *pszValue, size_t cwcValue, 850 bool fOverwrite /* = false */) 851 { 852 AssertPtrReturn(pszKey, VERR_INVALID_POINTER); 853 AssertReturn(cwcKey, VERR_INVALID_PARAMETER); 854 855 int vrc = VINF_SUCCESS; 856 try 857 { 858 Utf8Str const strKey(pszKey, cwcKey); 859 860 /* Take a shortcut and prevent crashes on some funny versions 861 * of STL if map is empty initially. */ 862 if (!m_mapPairs.empty()) 863 { 864 GuestCtrlStreamPairMapIter it = m_mapPairs.find(strKey); 865 if (it != m_mapPairs.end()) 866 { 867 if (pszValue == NULL) 868 m_mapPairs.erase(it); 869 else if (!fOverwrite) 870 AssertMsgFailedReturn(("Key '%*s' already exists! Value is '%s'\n", cwcKey, pszKey, m_mapPairs[strKey].mValue.c_str()), 871 VERR_ALREADY_EXISTS); 872 } 873 } 874 875 if (pszValue) 876 { 877 GuestToolboxStreamValue val(pszValue, cwcValue); 878 Log3Func(("strKey='%s', strValue='%s'\n", strKey.c_str(), val.mValue.c_str())); 879 m_mapPairs[strKey] = val; 880 } 881 } 882 catch (const std::exception &) 883 { 884 /** @todo set vrc? */ 885 } 886 return vrc; 887 } 888 889 /** 890 * Sets a value to a key or deletes a key by setting a NULL value. 891 * 892 * @return VBox status code. 893 * @param pszKey Key name to process. 894 * @param pszValue Value to set. Set NULL for deleting the key. 895 */ 896 int GuestToolboxStreamBlock::SetValue(const char *pszKey, const char *pszValue) 897 { 898 return SetValueEx(pszKey, RTSTR_MAX, pszValue, RTSTR_MAX); 899 } 900 901 /////////////////////////////////////////////////////////////////////////////// 902 903 GuestToolboxStream::GuestToolboxStream(void) 904 : m_cBlocks(0) 905 { 906 } 907 908 GuestToolboxStream::~GuestToolboxStream(void) 909 { 910 } 902 911 903 912 /** -
trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
r104003 r104178 372 372 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 373 373 { 374 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 374 375 vrc = i_openViaToolbox(pvrcGuest); 376 #else 377 RT_NOREF(pvrcGuest); 378 vrc = VERR_NOT_SUPPORTED; 379 #endif 375 380 } 376 381 … … 847 852 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 848 853 { 854 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 849 855 vrc = i_closeViaToolbox(pvrcGuest); 856 #else 857 RT_NOREF(pvrcGuest); 858 vrc = VERR_NOT_SUPPORTED; 859 #endif 850 860 } 851 861 … … 944 954 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 945 955 { 956 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 946 957 vrc = i_readInternalViaToolbox(objData, pvrcGuest); 958 #else 959 RT_NOREF(objData, pvrcGuest); 960 vrc = VERR_NOT_SUPPORTED; 961 #endif 947 962 } 948 963 -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r104003 r104178 2270 2270 /////////////////////////////////////////////////////////////////////////////// 2271 2271 2272 GuestProcess Toolbox::GuestProcessToolbox(void)2272 GuestProcessWrapper::GuestProcessWrapper(void) 2273 2273 : pSession(NULL), 2274 2274 pProcess(NULL) … … 2276 2276 } 2277 2277 2278 GuestProcess Toolbox::~GuestProcessToolbox(void)2278 GuestProcessWrapper::~GuestProcessWrapper(void) 2279 2279 { 2280 2280 uninit(); … … 2282 2282 2283 2283 /** 2284 * Initializes and starts a process toolon the guest.2284 * Initializes and starts a process on the guest. 2285 2285 * 2286 2286 * @returns VBox status code. 2287 * @param pGuestSession Guest session the process toolsshould be started in.2287 * @param pGuestSession Guest session the process should be started in. 2288 2288 * @param startupInfo Guest process startup info to use for starting. 2289 2289 * @param fAsync Whether to start asynchronously or not. … … 2291 2291 * VERR_GSTCTL_GUEST_ERROR was returned. Optional. 2292 2292 */ 2293 int GuestProcess Toolbox::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,2293 int GuestProcessWrapper::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, 2294 2294 bool fAsync, int *pvrcGuest) 2295 2295 { … … 2331 2331 2332 2332 /** 2333 * Unitializes a guest process toolby terminating it on the guest.2334 */ 2335 void GuestProcess Toolbox::uninit(void)2333 * Unitializes a guest process by terminating it on the guest. 2334 */ 2335 void GuestProcessWrapper::uninit(void) 2336 2336 { 2337 2337 /* Make sure the process is terminated and unregistered from the guest session. */ … … 2350 2350 2351 2351 /** 2352 * Gets the current guest process stream block. 2352 * Returns whether a guest process is still running or not. 2353 * 2354 * @returns \c true if running, or \c false if not. 2355 */ 2356 bool GuestProcessWrapper::isRunning(void) 2357 { 2358 AssertReturn(!pProcess.isNull(), false); 2359 2360 ProcessStatus_T procStatus = ProcessStatus_Undefined; 2361 HRESULT hrc = pProcess->COMGETTER(Status(&procStatus)); 2362 AssertComRC(hrc); 2363 2364 if ( procStatus == ProcessStatus_Started 2365 || procStatus == ProcessStatus_Paused 2366 || procStatus == ProcessStatus_Terminating) 2367 { 2368 return true; 2369 } 2370 2371 return false; 2372 } 2373 2374 /** 2375 * Returns whether the guest process has been run correctly or not, based on it's internal process 2376 * status and reported exit status. 2377 * 2378 * @return @c true if the guest process has been run correctly (exit status 0), or @c false if some error 2379 * occurred (exit status <> 0 or wrong process state). 2380 */ 2381 bool GuestProcessWrapper::isTerminatedOk(void) 2382 { 2383 return getTerminationStatus() == VINF_SUCCESS; 2384 } 2385 2386 2387 /** 2388 * Reports if the guest process has been run correctly. 2389 * 2390 * @retval VINF_SUCCESS if the process has stopped and the exit code is zero. 2391 * @retval VERR_GSTCTL_PROCESS_EXIT_CODE if the exit code is _not_ zero. 2392 * @retval VERR_GSTCTL_PROCESS_WRONG_STATE if still running. 2393 * 2394 * @param piExitCode Exit code of the tool. Optional. 2395 */ 2396 int GuestProcessWrapper::getTerminationStatus(int32_t *piExitCode /* = NULL */) 2397 { 2398 Assert(!pProcess.isNull()); 2399 AssertPtrNull(piExitCode); 2400 2401 int vrc; 2402 if (!isRunning()) 2403 { 2404 LONG iExitCode = -1; 2405 HRESULT hrc = pProcess->COMGETTER(ExitCode(&iExitCode)); 2406 AssertComRC(hrc); 2407 2408 if (piExitCode) 2409 *piExitCode = iExitCode; 2410 2411 vrc = iExitCode == 0 ? VINF_SUCCESS : VERR_GSTCTL_PROCESS_EXIT_CODE; 2412 } 2413 else 2414 { 2415 if (piExitCode) 2416 *piExitCode = -1; 2417 vrc = VERR_GSTCTL_PROCESS_WRONG_STATE; 2418 } 2419 2420 LogFlowFuncLeaveRC(vrc); 2421 return vrc; 2422 } 2423 2424 /** 2425 * Terminates a guest process. 2426 * 2427 * @returns VBox status code. 2428 * @param uTimeoutMS Timeout (in ms) to wait. 2429 * @param pvrcGuest Where to return the guest error when 2430 * VERR_GSTCTL_GUEST_ERROR was returned. Optional. 2431 */ 2432 int GuestProcessWrapper::terminate(uint32_t uTimeoutMS, int *pvrcGuest) 2433 { 2434 LogFlowThisFuncEnter(); 2435 2436 int vrc; 2437 if (!pProcess.isNull()) 2438 vrc = pProcess->i_terminateProcess(uTimeoutMS, pvrcGuest); 2439 else 2440 vrc = VERR_NOT_FOUND; 2441 2442 LogFlowFuncLeaveRC(vrc); 2443 return vrc; 2444 } 2445 2446 /////////////////////////////////////////////////////////////////////////////// 2447 2448 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 2449 GuestProcessToolbox::GuestProcessToolbox(void) 2450 { 2451 } 2452 2453 GuestProcessToolbox::~GuestProcessToolbox(void) 2454 { 2455 } 2456 2457 /** 2458 * Waits for a guest toolbox process. 2459 * 2460 * @returns VBox status code. 2461 * @param fToolWaitFlags Guest process tool wait flags to use for waiting. 2462 * @param pvrcGuest Where to return the guest error when 2463 * VERR_GSTCTL_GUEST_ERROR was returned. Optional. 2464 */ 2465 int GuestProcessToolbox::wait(uint32_t fToolWaitFlags, int *pvrcGuest) 2466 { 2467 return waitEx(fToolWaitFlags, NULL /* pStrmBlkOut */, pvrcGuest); 2468 } 2469 2470 /** 2471 * Waits for a guest toolbox process, also returning process output. 2472 * 2473 * @returns VBox status code. 2474 * @param fToolWaitFlags Guest process tool wait flags to use for waiting. 2475 * @param pStrmBlkOut Where to store the guest toolbox output. 2476 * @param pvrcGuest Where to return the guest error when 2477 * VERR_GSTCTL_GUEST_ERROR was returned. Optional. 2478 */ 2479 int GuestProcessToolbox::waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStrmBlkOut, int *pvrcGuest) 2480 { 2481 LogFlowThisFunc(("fToolWaitFlags=0x%x, pStrmBlkOut=%p, pvrcGuest=%p\n", fToolWaitFlags, pStrmBlkOut, pvrcGuest)); 2482 2483 int vrc; 2484 2485 /* Is the next block complete without waiting for new data from the guest? */ 2486 if (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK) 2487 { 2488 AssertPtr(pStrmBlkOut); 2489 vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut); 2490 if ( RT_SUCCESS(vrc) 2491 && pStrmBlkOut->IsComplete()) 2492 return vrc; 2493 /* else do the waiting below. */ 2494 } 2495 2496 /* Do the waiting. */ 2497 uint32_t fProcWaitForFlags = ProcessWaitForFlag_Terminate; 2498 if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut) 2499 fProcWaitForFlags |= ProcessWaitForFlag_StdOut; 2500 if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr) 2501 fProcWaitForFlags |= ProcessWaitForFlag_StdErr; 2502 2503 /** @todo Decrease timeout while running. */ 2504 uint64_t u64StartMS = RTTimeMilliTS(); 2505 uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS; 2506 2507 int vrcGuest = VINF_SUCCESS; 2508 bool fDone = false; 2509 2510 BYTE abBuf[_64K]; 2511 uint32_t cbRead; 2512 2513 bool fHandleStdOut = false; 2514 bool fHandleStdErr = false; 2515 2516 /** 2517 * Updates the elapsed time and checks if a 2518 * timeout happened, then breaking out of the loop. 2519 */ 2520 #define UPDATE_AND_CHECK_ELAPSED_TIME() \ 2521 u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \ 2522 if ( uTimeoutMS != RT_INDEFINITE_WAIT \ 2523 && u64ElapsedMS >= uTimeoutMS) \ 2524 { \ 2525 vrc = VERR_TIMEOUT; \ 2526 break; \ 2527 } 2528 2529 /** 2530 * Returns the remaining time (in ms). 2531 */ 2532 #define GET_REMAINING_TIME (uTimeoutMS == RT_INDEFINITE_WAIT ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS) 2533 2534 ProcessWaitResult_T waitRes = ProcessWaitResult_None; 2535 do 2536 { 2537 uint64_t u64ElapsedMS; 2538 UPDATE_AND_CHECK_ELAPSED_TIME(); 2539 2540 vrc = pProcess->i_waitFor(fProcWaitForFlags, GET_REMAINING_TIME, waitRes, &vrcGuest); 2541 if (RT_FAILURE(vrc)) 2542 break; 2543 2544 switch (waitRes) 2545 { 2546 case ProcessWaitResult_StdIn: 2547 vrc = VERR_NOT_IMPLEMENTED; 2548 break; 2549 2550 case ProcessWaitResult_StdOut: 2551 fHandleStdOut = true; 2552 break; 2553 2554 case ProcessWaitResult_StdErr: 2555 fHandleStdErr = true; 2556 break; 2557 2558 case ProcessWaitResult_WaitFlagNotSupported: 2559 if (fProcWaitForFlags & ProcessWaitForFlag_StdOut) 2560 fHandleStdOut = true; 2561 if (fProcWaitForFlags & ProcessWaitForFlag_StdErr) 2562 fHandleStdErr = true; 2563 /* Since waiting for stdout / stderr is not supported by the guest, 2564 * wait a bit to not hog the CPU too much when polling for data. */ 2565 RTThreadSleep(1); /* Optional, don't check vrc. */ 2566 break; 2567 2568 case ProcessWaitResult_Error: 2569 vrc = VERR_GSTCTL_GUEST_ERROR; 2570 break; 2571 2572 case ProcessWaitResult_Terminate: 2573 fDone = true; 2574 break; 2575 2576 case ProcessWaitResult_Timeout: 2577 vrc = VERR_TIMEOUT; 2578 break; 2579 2580 case ProcessWaitResult_Start: 2581 case ProcessWaitResult_Status: 2582 /* Not used here, just skip. */ 2583 break; 2584 2585 default: 2586 AssertMsgFailed(("Unhandled process wait result %RU32\n", waitRes)); 2587 break; 2588 } 2589 2590 if (RT_FAILURE(vrc)) 2591 break; 2592 2593 if (fHandleStdOut) 2594 { 2595 UPDATE_AND_CHECK_ELAPSED_TIME(); 2596 2597 cbRead = 0; 2598 vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDOUT, sizeof(abBuf), 2599 GET_REMAINING_TIME, 2600 abBuf, sizeof(abBuf), 2601 &cbRead, &vrcGuest); 2602 if ( RT_FAILURE(vrc) 2603 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2604 break; 2605 2606 if (cbRead) 2607 { 2608 LogFlowThisFunc(("Received %RU32 bytes from stdout\n", cbRead)); 2609 vrc = mStdOut.AddData(abBuf, cbRead); 2610 2611 if ( RT_SUCCESS(vrc) 2612 && (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK)) 2613 { 2614 AssertPtr(pStrmBlkOut); 2615 vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut); 2616 2617 /* When successful, break out of the loop because we're done 2618 * with reading the first stream block. */ 2619 if (RT_SUCCESS(vrc)) 2620 fDone = true; 2621 } 2622 } 2623 2624 fHandleStdOut = false; 2625 } 2626 2627 if (fHandleStdErr) 2628 { 2629 UPDATE_AND_CHECK_ELAPSED_TIME(); 2630 2631 cbRead = 0; 2632 vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDERR, sizeof(abBuf), 2633 GET_REMAINING_TIME, 2634 abBuf, sizeof(abBuf), 2635 &cbRead, &vrcGuest); 2636 if ( RT_FAILURE(vrc) 2637 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2638 break; 2639 2640 if (cbRead) 2641 { 2642 LogFlowThisFunc(("Received %RU32 bytes from stderr\n", cbRead)); 2643 vrc = mStdErr.AddData(abBuf, cbRead); 2644 } 2645 2646 fHandleStdErr = false; 2647 } 2648 2649 } while (!fDone && RT_SUCCESS(vrc)); 2650 2651 #undef UPDATE_AND_CHECK_ELAPSED_TIME 2652 #undef GET_REMAINING_TIME 2653 2654 if (RT_FAILURE(vrcGuest)) 2655 vrc = VERR_GSTCTL_GUEST_ERROR; 2656 2657 LogFlowThisFunc(("Loop ended with vrc=%Rrc, vrcGuest=%Rrc, waitRes=%RU32\n", vrc, vrcGuest, waitRes)); 2658 if (pvrcGuest) 2659 *pvrcGuest = vrcGuest; 2660 2661 LogFlowFuncLeaveRC(vrc); 2662 return vrc; 2663 } 2664 2665 /** 2666 * Gets the current guest toolbox process stream block. 2353 2667 * 2354 2668 * @returns VBox status code. … … 2375 2689 2376 2690 /** 2377 * Returns the result code from an ended guest process tool.2378 * 2379 * @returns Result code from guest process tool.2691 * Returns the result code from an ended guest toolbox process. 2692 * 2693 * @returns Result code from guest toolbox process. 2380 2694 */ 2381 2695 int GuestProcessToolbox::getRc(void) const … … 2386 2700 2387 2701 return GuestProcessToolbox::exitCodeToRc(mStartupInfo, exitCode); 2388 }2389 2390 /**2391 * Returns whether a guest process tool is still running or not.2392 *2393 * @returns \c true if running, or \c false if not.2394 */2395 bool GuestProcessToolbox::isRunning(void)2396 {2397 AssertReturn(!pProcess.isNull(), false);2398 2399 ProcessStatus_T procStatus = ProcessStatus_Undefined;2400 HRESULT hrc = pProcess->COMGETTER(Status(&procStatus));2401 AssertComRC(hrc);2402 2403 if ( procStatus == ProcessStatus_Started2404 || procStatus == ProcessStatus_Paused2405 || procStatus == ProcessStatus_Terminating)2406 {2407 return true;2408 }2409 2410 return false;2411 }2412 2413 /**2414 * Returns whether the tool has been run correctly or not, based on it's internal process2415 * status and reported exit status.2416 *2417 * @return @c true if the tool has been run correctly (exit status 0), or @c false if some error2418 * occurred (exit status <> 0 or wrong process state).2419 */2420 bool GuestProcessToolbox::isTerminatedOk(void)2421 {2422 return getTerminationStatus() == VINF_SUCCESS;2423 2702 } 2424 2703 … … 2525 2804 2526 2805 /** 2527 * Reports if the tool has been run correctly.2528 *2529 * @retval VINF_SUCCESS if the process has stopped and the exit code is zero.2530 * @retval VERR_GSTCTL_PROCESS_EXIT_CODE if the exit code is _not_ zero.2531 * @retval VERR_GSTCTL_PROCESS_WRONG_STATE if still running.2532 *2533 * @param piExitCode Exit code of the tool. Optional.2534 */2535 int GuestProcessToolbox::getTerminationStatus(int32_t *piExitCode /* = NULL */)2536 {2537 Assert(!pProcess.isNull());2538 AssertPtrNull(piExitCode);2539 2540 int vrc;2541 if (!isRunning())2542 {2543 LONG iExitCode = -1;2544 HRESULT hrc = pProcess->COMGETTER(ExitCode(&iExitCode));2545 AssertComRC(hrc);2546 2547 if (piExitCode)2548 *piExitCode = iExitCode;2549 2550 vrc = iExitCode == 0 ? VINF_SUCCESS : VERR_GSTCTL_PROCESS_EXIT_CODE;2551 }2552 else2553 {2554 if (piExitCode)2555 *piExitCode = -1;2556 vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;2557 }2558 2559 LogFlowFuncLeaveRC(vrc);2560 return vrc;2561 }2562 2563 /**2564 * Waits for a guest process tool.2565 *2566 * @returns VBox status code.2567 * @param fToolWaitFlags Guest process tool wait flags to use for waiting.2568 * @param pvrcGuest Where to return the guest error when2569 * VERR_GSTCTL_GUEST_ERROR was returned. Optional.2570 */2571 int GuestProcessToolbox::wait(uint32_t fToolWaitFlags, int *pvrcGuest)2572 {2573 return waitEx(fToolWaitFlags, NULL /* pStrmBlkOut */, pvrcGuest);2574 }2575 2576 /**2577 * Waits for a guest process tool, also returning process output.2578 *2579 * @returns VBox status code.2580 * @param fToolWaitFlags Guest process tool wait flags to use for waiting.2581 * @param pStrmBlkOut Where to store the guest process output.2582 * @param pvrcGuest Where to return the guest error when2583 * VERR_GSTCTL_GUEST_ERROR was returned. Optional.2584 */2585 int GuestProcessToolbox::waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStrmBlkOut, int *pvrcGuest)2586 {2587 LogFlowThisFunc(("fToolWaitFlags=0x%x, pStreamBlock=%p, pvrcGuest=%p\n", fToolWaitFlags, pStrmBlkOut, pvrcGuest));2588 2589 int vrc;2590 2591 /* Is the next block complete without waiting for new data from the guest? */2592 if (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK)2593 {2594 AssertPtr(pStrmBlkOut);2595 vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);2596 if ( RT_SUCCESS(vrc)2597 && pStrmBlkOut->IsComplete())2598 return vrc;2599 /* else do the waiting below. */2600 }2601 2602 /* Do the waiting. */2603 uint32_t fProcWaitForFlags = ProcessWaitForFlag_Terminate;2604 if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut)2605 fProcWaitForFlags |= ProcessWaitForFlag_StdOut;2606 if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr)2607 fProcWaitForFlags |= ProcessWaitForFlag_StdErr;2608 2609 /** @todo Decrease timeout while running. */2610 uint64_t u64StartMS = RTTimeMilliTS();2611 uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;2612 2613 int vrcGuest = VINF_SUCCESS;2614 bool fDone = false;2615 2616 BYTE abBuf[_64K];2617 uint32_t cbRead;2618 2619 bool fHandleStdOut = false;2620 bool fHandleStdErr = false;2621 2622 /**2623 * Updates the elapsed time and checks if a2624 * timeout happened, then breaking out of the loop.2625 */2626 #define UPDATE_AND_CHECK_ELAPSED_TIME() \2627 u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \2628 if ( uTimeoutMS != RT_INDEFINITE_WAIT \2629 && u64ElapsedMS >= uTimeoutMS) \2630 { \2631 vrc = VERR_TIMEOUT; \2632 break; \2633 }2634 2635 /**2636 * Returns the remaining time (in ms).2637 */2638 #define GET_REMAINING_TIME (uTimeoutMS == RT_INDEFINITE_WAIT ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS)2639 2640 ProcessWaitResult_T waitRes = ProcessWaitResult_None;2641 do2642 {2643 uint64_t u64ElapsedMS;2644 UPDATE_AND_CHECK_ELAPSED_TIME();2645 2646 vrc = pProcess->i_waitFor(fProcWaitForFlags, GET_REMAINING_TIME, waitRes, &vrcGuest);2647 if (RT_FAILURE(vrc))2648 break;2649 2650 switch (waitRes)2651 {2652 case ProcessWaitResult_StdIn:2653 vrc = VERR_NOT_IMPLEMENTED;2654 break;2655 2656 case ProcessWaitResult_StdOut:2657 fHandleStdOut = true;2658 break;2659 2660 case ProcessWaitResult_StdErr:2661 fHandleStdErr = true;2662 break;2663 2664 case ProcessWaitResult_WaitFlagNotSupported:2665 if (fProcWaitForFlags & ProcessWaitForFlag_StdOut)2666 fHandleStdOut = true;2667 if (fProcWaitForFlags & ProcessWaitForFlag_StdErr)2668 fHandleStdErr = true;2669 /* Since waiting for stdout / stderr is not supported by the guest,2670 * wait a bit to not hog the CPU too much when polling for data. */2671 RTThreadSleep(1); /* Optional, don't check vrc. */2672 break;2673 2674 case ProcessWaitResult_Error:2675 vrc = VERR_GSTCTL_GUEST_ERROR;2676 break;2677 2678 case ProcessWaitResult_Terminate:2679 fDone = true;2680 break;2681 2682 case ProcessWaitResult_Timeout:2683 vrc = VERR_TIMEOUT;2684 break;2685 2686 case ProcessWaitResult_Start:2687 case ProcessWaitResult_Status:2688 /* Not used here, just skip. */2689 break;2690 2691 default:2692 AssertMsgFailed(("Unhandled process wait result %RU32\n", waitRes));2693 break;2694 }2695 2696 if (RT_FAILURE(vrc))2697 break;2698 2699 if (fHandleStdOut)2700 {2701 UPDATE_AND_CHECK_ELAPSED_TIME();2702 2703 cbRead = 0;2704 vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDOUT, sizeof(abBuf),2705 GET_REMAINING_TIME,2706 abBuf, sizeof(abBuf),2707 &cbRead, &vrcGuest);2708 if ( RT_FAILURE(vrc)2709 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)2710 break;2711 2712 if (cbRead)2713 {2714 LogFlowThisFunc(("Received %RU32 bytes from stdout\n", cbRead));2715 vrc = mStdOut.AddData(abBuf, cbRead);2716 2717 if ( RT_SUCCESS(vrc)2718 && (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK))2719 {2720 AssertPtr(pStrmBlkOut);2721 vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);2722 2723 /* When successful, break out of the loop because we're done2724 * with reading the first stream block. */2725 if (RT_SUCCESS(vrc))2726 fDone = true;2727 }2728 }2729 2730 fHandleStdOut = false;2731 }2732 2733 if (fHandleStdErr)2734 {2735 UPDATE_AND_CHECK_ELAPSED_TIME();2736 2737 cbRead = 0;2738 vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDERR, sizeof(abBuf),2739 GET_REMAINING_TIME,2740 abBuf, sizeof(abBuf),2741 &cbRead, &vrcGuest);2742 if ( RT_FAILURE(vrc)2743 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)2744 break;2745 2746 if (cbRead)2747 {2748 LogFlowThisFunc(("Received %RU32 bytes from stderr\n", cbRead));2749 vrc = mStdErr.AddData(abBuf, cbRead);2750 }2751 2752 fHandleStdErr = false;2753 }2754 2755 } while (!fDone && RT_SUCCESS(vrc));2756 2757 #undef UPDATE_AND_CHECK_ELAPSED_TIME2758 #undef GET_REMAINING_TIME2759 2760 if (RT_FAILURE(vrcGuest))2761 vrc = VERR_GSTCTL_GUEST_ERROR;2762 2763 LogFlowThisFunc(("Loop ended with vrc=%Rrc, vrcGuest=%Rrc, waitRes=%RU32\n", vrc, vrcGuest, waitRes));2764 if (pvrcGuest)2765 *pvrcGuest = vrcGuest;2766 2767 LogFlowFuncLeaveRC(vrc);2768 return vrc;2769 }2770 2771 /**2772 * Terminates a guest process tool.2773 *2774 * @returns VBox status code.2775 * @param uTimeoutMS Timeout (in ms) to wait.2776 * @param pvrcGuest Where to return the guest error when2777 * VERR_GSTCTL_GUEST_ERROR was returned. Optional.2778 */2779 int GuestProcessToolbox::terminate(uint32_t uTimeoutMS, int *pvrcGuest)2780 {2781 LogFlowThisFuncEnter();2782 2783 int vrc;2784 if (!pProcess.isNull())2785 vrc = pProcess->i_terminateProcess(uTimeoutMS, pvrcGuest);2786 else2787 vrc = VERR_NOT_FOUND;2788 2789 LogFlowFuncLeaveRC(vrc);2790 return vrc;2791 }2792 2793 /**2794 2806 * Converts a toolbox tool's exit code to an IPRT error code. 2795 2807 * … … 2961 2973 return strErr; 2962 2974 } 2963 2975 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r104003 r104178 1091 1091 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1092 1092 { 1093 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 1093 1094 vrc = i_directoryCreateViaToolbox(strPath, uMode, uFlags, pvrcGuest); 1095 #else 1096 RT_NOREF(uMode, uFlags, pvrcGuest); 1097 vrc = VERR_NOT_SUPPORTED; 1098 #endif 1094 1099 } 1095 1100 … … 1255 1260 } 1256 1261 1262 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 1257 1263 /** 1258 1264 * Creates a temporary directory / file on the guest (legacy version). … … 1342 1348 return vrc; 1343 1349 } 1350 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 1344 1351 1345 1352 /** … … 1430 1437 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1431 1438 { 1439 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 1432 1440 vrc = i_fsCreateTempViaToolbox(strTemplate, strPath, fDirectory, strName, fMode, fSecure, pvrcGuest); 1441 #else 1442 RT_NOREF(strTemplate, strPath, fDirectory, strName, fMode, fSecure, pvrcGuest); 1443 vrc = VERR_NOT_SUPPORTED; 1444 #endif 1433 1445 } 1434 1446 … … 1769 1781 } 1770 1782 1783 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 1771 1784 /** 1772 1785 * Removes a file from the guest (legacy version). … … 1823 1836 return vrc; 1824 1837 } 1838 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 1825 1839 1826 1840 /** … … 1871 1885 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1872 1886 { 1887 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 1873 1888 vrc = i_fileRemoveViaToolbox(strPath, pvrcGuest); 1889 #else 1890 RT_NOREF(strPath, pvrcGuest); 1891 vrc = VERR_NOT_SUPPORTED; 1892 #endif 1874 1893 } 1875 1894 … … 2048 2067 } 2049 2068 2069 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 2050 2070 /** 2051 2071 * Queries information of a file system object (file, directory, ...). Legacy version. … … 2104 2124 return vrc; 2105 2125 } 2126 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 2106 2127 2107 2128 /** … … 2250 2271 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 2251 2272 { 2273 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 2252 2274 vrc = i_fsObjQueryInfoViaToolbox(strPath, fFollowSymlinks, objData, pvrcGuest); 2275 #else 2276 RT_NOREF(strPath, fFollowSymlinks, objData, pvrcGuest); 2277 vrc = VERR_NOT_SUPPORTED; 2278 #endif 2253 2279 } 2254 2280 -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r104161 r104178 2627 2627 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 2628 2628 2629 #ifndef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT 2630 RT_NOREF(procInfo, fSilent); 2631 return VERR_NOT_SUPPORTED; 2632 #else 2629 2633 LogRel(("Running %s ...\n", procInfo.mName.c_str())); 2630 2634 … … 2671 2675 2672 2676 return vrc; 2677 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */ 2673 2678 } 2674 2679
Note:
See TracChangeset
for help on using the changeset viewer.