- Timestamp:
- Aug 10, 2012 10:19:57 AM (12 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/GuestSessionImpl.h
r42702 r42749 28 28 #include "GuestFsObjInfoImpl.h" 29 29 30 #include <iprt/isofs.h> /* For UpdateAdditions. */ 31 30 32 class Guest; 31 33 … … 136 138 137 139 protected: 140 141 int copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO, 142 Utf8Str const &strFileSource, const Utf8Str &strFileDest, 143 bool fOptional, uint32_t *pcbSize); 144 int runFile(GuestSession *pSession, GuestProcessStartupInfo &procInfo); 138 145 139 146 /** The (optionally) specified Guest Additions .ISO on the host -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r42716 r42749 33 33 #include <iprt/env.h> 34 34 #include <iprt/file.h> /* For CopyTo/From. */ 35 #include <iprt/isofs.h> /* For UpdateAdditions. */36 35 37 36 #include <VBox/com/array.h> 38 37 #include <VBox/version.h> 39 38 39 40 #define VBOX_SERVICE_ENVARG_BUG 40 41 41 42 // constructor / destructor … … 678 679 } 679 680 681 int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO, 682 Utf8Str const &strFileSource, const Utf8Str &strFileDest, 683 bool fOptional, uint32_t *pcbSize) 684 { 685 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 686 AssertPtrReturn(pISO, VERR_INVALID_POINTER); 687 /* pcbSize is optional. */ 688 689 uint32_t cbOffset; 690 size_t cbSize; 691 692 int rc = RTIsoFsGetFileInfo(pISO, strFileSource.c_str(), &cbOffset, &cbSize); 693 if (RT_FAILURE(rc)) 694 { 695 if (fOptional) 696 return VINF_SUCCESS; 697 698 return rc; 699 } 700 701 Assert(cbOffset); 702 Assert(cbSize); 703 rc = RTFileSeek(pISO->file, cbOffset, RTFILE_SEEK_BEGIN, NULL); 704 705 /* Copy over the Guest Additions file to the guest. */ 706 if (RT_SUCCESS(rc)) 707 { 708 LogRel(("Copying Guest Additions installer file \"%s\" to \"%s\" on guest ...\n", 709 strFileSource.c_str(), strFileDest.c_str())); 710 711 if (RT_SUCCESS(rc)) 712 { 713 SessionTaskCopyTo *pTask = new SessionTaskCopyTo(pSession /* GuestSession */, 714 &pISO->file, cbOffset, cbSize, 715 strFileDest, CopyFileFlag_None); 716 AssertPtrReturn(pTask, VERR_NO_MEMORY); 717 718 ComObjPtr<Progress> pProgressCopyTo; 719 rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer file \"%s\" to \"%s\" on guest"), 720 mSource.c_str(), strFileDest.c_str()), 721 pTask, pProgressCopyTo); 722 if (RT_SUCCESS(rc)) 723 { 724 BOOL fCanceled = FALSE; 725 HRESULT hr = pProgressCopyTo->WaitForCompletion(-1); 726 if ( SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled)) 727 && fCanceled) 728 { 729 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 730 } 731 else if (FAILED(hr)) 732 { 733 Assert(FAILED(hr)); 734 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 735 } 736 } 737 } 738 } 739 740 /** @todo Note: Since there is no file locking involved at the moment, there can be modifications 741 * between finished copying, the verification and the actual execution. */ 742 743 /* Determine where the installer image ended up and if it has the correct size. */ 744 if (RT_SUCCESS(rc)) 745 { 746 LogRel(("Verifying Guest Additions installer file \"%s\" ...\n", strFileDest.c_str())); 747 748 GuestFsObjData objData; 749 int64_t cbSizeOnGuest; 750 rc = pSession->fileQuerySizeInternal(strFileDest, &cbSizeOnGuest); 751 #ifdef VBOX_SERVICE_ENVARG_BUG 752 if (RT_FAILURE(rc)) 753 { 754 /* Ugly hack: Because older Guest Additions have problems with environment variable 755 expansion in parameters we have to check an alternative location on Windows. 756 So check for "%TEMP%\" being "C:\\Windows\\system32\\EMP" actually. */ 757 if (strFileDest.startsWith("%TEMP%\\", RTCString::CaseSensitive)) 758 { 759 Utf8Str strFileDestBug = "C:\\Windows\\system32\\EMP" + strFileDest.substr(sizeof("%TEMP%\\") - sizeof(char)); 760 rc = pSession->fileQuerySizeInternal(strFileDestBug, &cbSizeOnGuest); 761 } 762 } 763 #endif 764 if ( RT_SUCCESS(rc) 765 && cbSize == (uint64_t)cbSizeOnGuest) 766 { 767 LogRel(("Guest Additions installer file \"%s\" successfully verified\n", 768 strFileDest.c_str())); 769 } 770 else 771 { 772 if (RT_SUCCESS(rc)) /* Size does not match. */ 773 rc = VERR_BROKEN_PIPE; /** @todo FInd a better error. */ 774 } 775 776 if (RT_SUCCESS(rc)) 777 { 778 if (pcbSize) 779 *pcbSize = cbSizeOnGuest; 780 } 781 } 782 783 return rc; 784 } 785 786 int SessionTaskUpdateAdditions::runFile(GuestSession *pSession, GuestProcessStartupInfo &procInfo) 787 { 788 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 789 790 #ifdef VBOX_SERVICE_ENVARG_BUG 791 GuestFsObjData objData; 792 int rc = pSession->fileQueryInfoInternal(procInfo.mCommand, objData); 793 if (RT_FAILURE(rc)) 794 procInfo.mCommand = "C:\\Windows\\system32\\EMP" + procInfo.mCommand.substr(sizeof("%TEMP%\\") - sizeof(char)); 795 #endif 796 797 ComObjPtr<GuestProcess> pProcess; 798 rc = pSession->processCreateExInteral(procInfo, pProcess); 799 if (RT_SUCCESS(rc)) 800 rc = pProcess->startProcess(); 801 802 if (RT_SUCCESS(rc)) 803 { 804 LogRel(("Running %s ...\n", procInfo.mName.c_str())); 805 806 GuestProcessWaitResult waitRes; 807 rc = pProcess->waitFor(ProcessWaitForFlag_Terminate, 808 10 * 60 * 1000 /* 10 mins Timeout */, waitRes); 809 if (waitRes.mResult == ProcessWaitResult_Terminate) 810 { 811 ProcessStatus_T procStatus; 812 LONG exitCode; 813 if ( ( SUCCEEDED(pProcess->COMGETTER(Status(&procStatus))) 814 && procStatus != ProcessStatus_TerminatedNormally) 815 || ( SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode))) 816 && exitCode != 0) 817 ) 818 { 819 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 820 Utf8StrFmt(GuestSession::tr("Running %s failed with status %ld, exit code %ld"), 821 procInfo.mName.c_str(), procStatus, exitCode)); 822 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 823 } 824 else /* Yay, success! */ 825 { 826 LogRel(("%s successfully completed\n", procInfo.mName.c_str())); 827 } 828 } 829 else 830 { 831 if (RT_FAILURE(rc)) 832 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 833 Utf8StrFmt(GuestSession::tr("Error while waiting running %s: %Rrc"), 834 procInfo.mName.c_str(), rc)); 835 else 836 { 837 setProgressErrorMsg(VBOX_E_IPRT_ERROR, pProcess->errorMsg()); 838 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 839 } 840 } 841 } 842 843 if (!pProcess.isNull()) 844 pProcess->close(); 845 846 return rc; 847 } 848 680 849 int SessionTaskUpdateAdditions::Run(void) 681 850 { … … 734 903 735 904 RTISOFSFILE iso; 736 uint32_t cbOffset;737 size_t cbSize;738 739 905 if (RT_SUCCESS(rc)) 740 906 { … … 753 919 else 754 920 { 755 rc = RTIsoFsGetFileInfo(&iso, strInstallerImage.c_str(), &cbOffset, &cbSize); 756 if ( RT_SUCCESS(rc) 757 && cbOffset 758 && cbSize) 759 { 760 rc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL); 761 if (RT_FAILURE(rc)) 762 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 763 Utf8StrFmt(GuestSession::tr("Unable to retrievev setup file \"%s\" information on \"%s\": %Rrc"), 764 strInstallerImage.c_str(), mSource.c_str(), rc)); 765 } 766 else 767 { 768 switch (rc) 769 { 770 case VERR_FILE_NOT_FOUND: 771 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 772 Utf8StrFmt(GuestSession::tr("Installer \"%s\" was not found on \"%s\""), 773 strInstallerImage.c_str(), mSource.c_str())); 774 break; 775 776 default: 777 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 778 Utf8StrFmt(GuestSession::tr("Error while retrieving information for installer \"%s\" on \"%s\": %Rrc"), 779 strInstallerImage.c_str(), mSource.c_str(), rc)); 780 break; 781 } 782 } 783 784 /* Specify the ouput path on the guest side. */ 921 rc = setProgress(5); 922 785 923 /** @todo Add support for non-Windows as well! */ 786 924 Utf8Str strInstallerDest = "%TEMP%\\VBoxWindowsAdditions.exe"; 787 788 /* Copy over the Guest Additions installer to the guest. */ 789 if (RT_SUCCESS(rc)) 790 { 791 LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n", 792 strInstallerImage.c_str(), strInstallerDest.c_str())); 793 794 rc = setProgress(15); 795 if (RT_SUCCESS(rc)) 796 { 797 SessionTaskCopyTo *pTask = new SessionTaskCopyTo(pSession /* GuestSession */, 798 &iso.file, cbOffset, cbSize, 799 strInstallerDest, CopyFileFlag_None); 800 AssertPtrReturn(pTask, VERR_NO_MEMORY); 801 802 ComObjPtr<Progress> pProgressCopyTo; 803 rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer from \"%s\" to \"%s\" on the guest"), 804 mSource.c_str(), strInstallerDest.c_str()), 805 pTask, pProgressCopyTo); 806 if (RT_FAILURE(rc)) 807 { 808 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 809 Utf8StrFmt(GuestSession::tr("Unable to start copying Guest Additions installer \"%s\" to \"%s\": %Rrc"), 810 mSource.c_str(), strInstallerDest.c_str(), rc)); 811 } 812 else 813 { 814 BOOL fCanceled = FALSE; 815 hr = pProgressCopyTo->WaitForCompletion(-1); 816 if (SUCCEEDED(hr)) 817 { 818 rc = setProgress(20); 819 } 820 else if ( SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled)) 821 && fCanceled) 822 { 823 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 824 Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer \"%s\" to \"%s\" was canceled"), 825 mSource.c_str(), strInstallerDest.c_str(), hr)); 826 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 827 } 828 else 829 { 830 Assert(FAILED(hr)); 831 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 832 Utf8StrFmt(GuestSession::tr("Error while copying Guest Additions installer \"%s\" to \"%s\": %Rhrc"), 833 mSource.c_str(), strInstallerDest.c_str(), hr)); 834 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 835 } 836 } 837 } 838 } 839 840 if (RT_SUCCESS(rc)) 841 { 842 /* Install needed certificates for the WHQL crap. */ 843 /** @todo Copy over VBoxCertUtil? */ 844 rc = setProgress(25); 845 } 925 bool fInstallCertificates = false; 846 926 847 927 if (RT_SUCCESS(rc)) 848 928 { 849 929 /* 850 * Installer was transferred successfully, so let's start it 851 * (with system rights). 930 * Copy over main installer to the guest. 852 931 */ 853 LogRel(("Verifying Guest Additions installer ...\n")); 932 rc = copyFileToGuest(pSession, &iso, strInstallerImage, strInstallerDest, 933 false /* File is not optional */, NULL /* cbSize */); 934 if (RT_SUCCESS(rc)) 935 rc = setProgress(20); 936 937 /* 938 * Install needed certificates for the WHQL crap. 939 ** @todo Only for Windows! 940 */ 941 if (RT_SUCCESS(rc)) 942 { 943 rc = copyFileToGuest(pSession, &iso, "CERT/ORACLE_VBOX.CER", "%TEMP%\\oracle-vbox.cer", 944 true /* File is optional */, NULL /* cbSize */); 945 if (RT_SUCCESS(rc)) 946 { 947 rc = setProgress(30); 948 if (RT_SUCCESS(rc)) 949 { 950 rc = copyFileToGuest(pSession, &iso, "CERT/VBOXCERTUTIL.EXE", "%TEMP%\\VBoxCertUtil.exe", 951 true /* File is optional */, NULL /* cbSize */); 952 if (RT_SUCCESS(rc)) 953 { 954 fInstallCertificates = true; 955 rc = setProgress(40); 956 } 957 else 958 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 959 Utf8StrFmt(GuestSession::tr("Error while copying certificate installation tool to the guest: %Rrc"), rc)); 960 } 961 } 962 else 963 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 964 Utf8StrFmt(GuestSession::tr("Error while copying certificate to the guest: %Rrc"), rc)); 965 } 966 } 967 968 /* 969 * Run VBoxCertUtil.exe to install the Oracle certificate. 970 */ 971 if ( RT_SUCCESS(rc) 972 && fInstallCertificates) 973 { 974 LogRel(("Installing certificates on the guest ...\n")); 975 976 GuestProcessStartupInfo procInfo; 977 procInfo.mName = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Certificate Utility")); 978 procInfo.mCommand = Utf8Str("%TEMP%\\VBoxCertUtil.exe"); 979 procInfo.mFlags = ProcessCreateFlag_Hidden; 980 981 /* Construct arguments. */ 982 /** @todo Remove hardcoded paths. */ 983 procInfo.mArguments.push_back(Utf8Str("add-trusted-publisher")); 984 /* Ugly hack: Because older Guest Additions have problems with environment variable 985 expansion in parameters we have to check an alternative location on Windows. 986 So check for "%TEMP%\VBoxWindowsAdditions.exe" in a screwed up way. */ 987 #ifdef VBOX_SERVICE_ENVARG_BUG 988 GuestFsObjData objData; 989 rc = pSession->fileQueryInfoInternal("%TEMP%\\oracle-vbox.cer", objData); 990 if (RT_SUCCESS(rc)) 991 #endif 992 procInfo.mArguments.push_back(Utf8Str("%TEMP%\\oracle-vbox.cer")); 993 #ifdef VBOX_SERVICE_ENVARG_BUG 994 else 995 procInfo.mArguments.push_back(Utf8Str("C:\\Windows\\system32\\EMPoracle-vbox.cer")); 996 #endif 997 /* Overwrite rc in any case. */ 998 rc = runFile(pSession, procInfo); 999 } 1000 1001 if (RT_SUCCESS(rc)) 854 1002 rc = setProgress(60); 855 }856 1003 857 1004 if (RT_SUCCESS(rc)) 858 1005 { 859 /* Determine where the installer image ended up and if it has the 860 * correct size. */ 861 GuestFsObjData objData; 862 int64_t cbSizeOnGuest; 863 rc = pSession->fileQuerySizeInternal(strInstallerDest, &cbSizeOnGuest); 864 if (RT_FAILURE(rc)) 865 { 866 /** @todo Windows only! */ 867 868 /* Because older Guest Additions have problems with environment variable 869 * expansion in parameters we have to check an alternative location on Windows. 870 * So check for "%TEMP%\VBoxWindowsAdditions.exe" in a screwed up way. */ 871 rc = pSession->fileQuerySizeInternal("C:\\Windows\\system32\\EMPVBoxWindowsAdditions.exe", &cbSizeOnGuest); 872 if (RT_SUCCESS(rc)) 873 strInstallerDest = "C:\\Windows\\system32\\EMPVBoxWindowsAdditions.exe"; 874 } 875 876 if ( RT_SUCCESS(rc) 877 && cbSize == (uint64_t)cbSizeOnGuest) 878 { 879 LogRel(("Guest Additions installer successfully verified\n")); 880 rc = setProgress(65); 881 } 882 else 883 { 884 if (RT_FAILURE(rc)) 885 { 886 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 887 Utf8StrFmt(GuestSession::tr("Unable to find Guest Additions installer on guest: %Rrc"), rc)); 888 } 889 else 890 { 891 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 892 Utf8StrFmt(GuestSession::tr("Guest Additions installer was not transfered fully (%RI64/%RU64)"), 893 cbSizeOnGuest, cbSize)); 894 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 895 } 896 } 897 } 898 899 if (RT_SUCCESS(rc)) 900 { 1006 LogRel(("Updating Guest Additions ...\n")); 1007 901 1008 GuestProcessStartupInfo procInfo; 902 procInfo.mName = Utf8StrFmt(GuestSession::tr(" Guest Additions Setup"));1009 procInfo.mName = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Setup")); 903 1010 procInfo.mCommand = Utf8Str(strInstallerDest); 904 1011 procInfo.mFlags = ProcessCreateFlag_Hidden; … … 919 1026 procInfo.mArguments.push_back(Utf8Str("/post_installstatus")); 920 1027 921 ComObjPtr<GuestProcess> pProcess; 922 rc = pSession->processCreateExInteral(procInfo, pProcess); 1028 rc = runFile(pSession, procInfo); 923 1029 if (RT_SUCCESS(rc)) 924 rc = pProcess->startProcess(); 925 if (RT_SUCCESS(rc)) 926 rc = setProgress(65); 927 if (RT_SUCCESS(rc)) 928 { 929 LogRel(("Updating Guest Additions in progress ...\n")); 930 931 GuestProcessWaitResult waitRes; 932 rc = pProcess->waitFor(ProcessWaitForFlag_Terminate, 933 10 * 60 * 1000 /* 10 mins Timeout */, waitRes); 934 if (waitRes.mResult == ProcessWaitResult_Terminate) 935 { 936 ProcessStatus_T procStatus; 937 LONG exitCode; 938 if ( ( SUCCEEDED(pProcess->COMGETTER(Status(&procStatus))) 939 && procStatus != ProcessStatus_TerminatedNormally) 940 || ( SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode))) 941 && exitCode != 0) 942 ) 943 { 944 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 945 Utf8StrFmt(GuestSession::tr("Updating Guest Additions failed with status %ld, exit code %d"), 946 procStatus, exitCode)); /**@todo Add stringify methods! */ 947 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 948 } 949 else /* Yay, success! */ 950 { 951 /** @todo Add code for verifying the update. */ 952 LogRel(("Updating Guest Additions successful\n")); 953 hr = setProgressSuccess(); 954 } 955 } 956 else 957 { 958 if (RT_FAILURE(rc)) 959 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 960 Utf8StrFmt(GuestSession::tr("Error while waiting for Guest Additions update: %Rrc"), rc)); 961 else 962 { 963 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR, pProcess->errorMsg()); 964 rc = VERR_GENERAL_FAILURE; /* Fudge. */ 965 } 966 } 967 } 968 if (!pProcess.isNull()) 969 pProcess->close(); 1030 hr = setProgressSuccess(); 970 1031 } 971 1032 RTIsoFsClose(&iso);
Note:
See TracChangeset
for help on using the changeset viewer.