Changeset 32866 in vbox
- Timestamp:
- Oct 1, 2010 2:41:42 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
-
Frontends/VBoxManage/Makefile.kmk (modified) (1 diff)
-
Frontends/VBoxManage/VBoxManageGuestCtrl.cpp (modified) (9 diffs)
-
Main/GuestImpl.cpp (modified) (2 diffs)
-
Main/Makefile.kmk (modified) (1 diff)
-
Main/idl/VirtualBox.xidl (modified) (2 diffs)
-
Main/include/GuestImpl.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
r32719 r32866 56 56 $(if $(VBOX_WITH_AHCI), VBOX_WITH_AHCI) \ 57 57 $(if $(VBOX_WITH_ALSA), VBOX_WITH_ALSA) \ 58 $(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST) \ 58 59 $(if $(VBOX_WITH_E1000),VBOX_WITH_E1000) \ 59 60 $(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL) \ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r32854 r32866 64 64 /** Set by the signal handler. */ 65 65 static volatile bool g_fExecCanceled = false; 66 static volatile bool g_fCopyCanceled = false; 66 67 67 68 #endif /* VBOX_ONLY_DOCS */ … … 77 78 " [--flags <flags>] [--timeout <msec>]\n" 78 79 " [--verbose] [--wait-for exit,stdout,stderr||]\n" 80 #ifdef VBOX_WITH_COPYTOGUEST 81 "\n" 82 " copyto <vmname>|<uuid>\n" 83 " <source on host> <destination on guest>\n" 84 " [--recursive] [--verbose] [--flags <flags>]\n" 85 #endif 79 86 "\n"); 80 87 } … … 89 96 * unnecessary here. 90 97 */ 91 static void execProcessSignalHandler(int iSignal)98 static void ctrlExecProcessSignalHandler(int iSignal) 92 99 { 93 100 NOREF(iSignal); … … 95 102 } 96 103 97 static const char * getStatus(ULONG uStatus)104 static const char *ctrlExecGetStatus(ULONG uStatus) 98 105 { 99 106 switch (uStatus) … … 120 127 } 121 128 122 static int handle ExecProgram(HandlerArg *a)129 static int handleCtrlExecProgram(HandlerArg *a) 123 130 { 124 131 /* … … 379 386 if (fCancelable) 380 387 { 381 signal(SIGINT, execProcessSignalHandler);388 signal(SIGINT, ctrlExecProcessSignalHandler); 382 389 #ifdef SIGBREAK 383 signal(SIGBREAK, execProcessSignalHandler);390 signal(SIGBREAK, ctrlExecProcessSignalHandler); 384 391 #endif 385 392 } … … 518 525 rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus); 519 526 if (SUCCEEDED(rc)) 520 RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", 521 uRetExitCode, uRetStatus, getStatus(uRetStatus), uRetFlags); 527 RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, uRetStatus, ctrlExecGetStatus(uRetStatus), uRetFlags); 522 528 } 523 529 } … … 533 539 return SUCCEEDED(rc) ? 0 : 1; 534 540 } 541 542 #ifdef VBOX_WITH_COPYTOGUEST 543 /** 544 * Signal handler that sets g_fCopyCanceled. 545 * 546 * This can be executed on any thread in the process, on Windows it may even be 547 * a thread dedicated to delivering this signal. Do not doing anything 548 * unnecessary here. 549 */ 550 static void ctrlCopySignalHandler(int iSignal) 551 { 552 NOREF(iSignal); 553 ASMAtomicWriteBool(&g_fCopyCanceled, true); 554 } 555 556 static int handleCtrlCopyTo(HandlerArg *a) 557 { 558 /* 559 * Check the syntax. We can deduce the correct syntax from the number of 560 * arguments. 561 */ 562 if (a->argc < 3) /* At least the source + destination should be present :-). */ 563 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters"); 564 565 Utf8Str Utf8Source(a->argv[1]); 566 Utf8Str Utf8Dest(a->argv[2]); 567 uint32_t uFlags = 0; 568 bool fVerbose = false; 569 bool fCopyRecursive = false; 570 571 /* Iterate through all possible commands (if available). */ 572 bool usageOK = true; 573 for (int i = 2; usageOK && i < a->argc; i++) 574 { 575 if (!strcmp(a->argv[i], "--flags")) 576 { 577 if (i + 1 >= a->argc) 578 usageOK = false; 579 else 580 { 581 /* Nothing to do here yet. */ 582 ++i; 583 } 584 } 585 else if ( !strcmp(a->argv[i], "--recursive") 586 || !strcmp(a->argv[i], "--r")) 587 { 588 uFlags |= CopyFileFlag_Recursive; 589 } 590 else if ( !strcmp(a->argv[i], "--update") 591 || !strcmp(a->argv[i], "--u")) 592 { 593 uFlags |= CopyFileFlag_Update; 594 } 595 else if ( !strcmp(a->argv[i], "--follow") 596 || !strcmp(a->argv[i], "--f")) 597 { 598 uFlags |= CopyFileFlag_FollowLinks; 599 } 600 /** @todo Add force flag for overwriting existing stuff. */ 601 else if (!strcmp(a->argv[i], "--verbose")) 602 fVerbose = true; 603 else 604 return errorSyntax(USAGE_GUESTCONTROL, 605 "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str()); 606 } 607 608 if (!usageOK) 609 return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters"); 610 611 if (Utf8Source.isEmpty()) 612 return errorSyntax(USAGE_GUESTCONTROL, 613 "No source specified!"); 614 615 if (Utf8Dest.isEmpty()) 616 return errorSyntax(USAGE_GUESTCONTROL, 617 "No destination specified!"); 618 619 /* lookup VM. */ 620 ComPtr<IMachine> machine; 621 /* assume it's an UUID */ 622 HRESULT rc = a->virtualBox->GetMachine(Bstr(a->argv[0]).raw(), 623 machine.asOutParam()); 624 if (FAILED(rc) || !machine) 625 { 626 /* must be a name */ 627 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), 628 machine.asOutParam())); 629 } 630 631 if (machine) 632 { 633 do 634 { 635 /* open an existing session for VM */ 636 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Shared)); 637 // @todo r=dj assert that it's an existing session 638 639 /* get the mutable session machine */ 640 a->session->COMGETTER(Machine)(machine.asOutParam()); 641 642 /* get the associated console */ 643 ComPtr<IConsole> console; 644 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam())); 645 646 ComPtr<IGuest> guest; 647 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam())); 648 649 ComPtr<IProgress> progress; 650 ULONG uPID = 0; 651 652 if (fVerbose) 653 { 654 if (fCopyRecursive) 655 RTPrintf("Recursively copying \"%s\" to \"%s\" ...\n", Utf8Source, Utf8Dest); 656 else 657 RTPrintf("Copying \"%s\" to \"%s\" ...\n", Utf8Source, Utf8Dest); 658 } 659 660 /* Do the copy. */ 661 rc = guest->CopyToGuest(Bstr(Utf8Source).raw(), Bstr(Utf8Dest).raw(), 662 uFlags, progress.asOutParam()); 663 if (FAILED(rc)) 664 { 665 /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way 666 * because it contains more accurate info about what went wrong. */ 667 ErrorInfo info(guest, COM_IIDOF(IGuest)); 668 if (info.isFullAvailable()) 669 { 670 if (rc == VBOX_E_IPRT_ERROR) 671 RTMsgError("%ls.", info.getText().raw()); 672 else 673 RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode()); 674 } 675 break; 676 } 677 else 678 { 679 /* setup signal handling if cancelable */ 680 ASSERT(progress); 681 bool fCanceledAlready = false; 682 BOOL fCancelable; 683 HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable); 684 if (FAILED(hrc)) 685 fCancelable = FALSE; 686 if (fCancelable) 687 { 688 signal(SIGINT, ctrlCopySignalHandler); 689 #ifdef SIGBREAK 690 signal(SIGBREAK, ctrlCopySignalHandler); 691 #endif 692 } 693 694 /* Wait for process to exit ... */ 695 BOOL fCompleted = FALSE; 696 BOOL fCanceled = FALSE; 697 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted)))) 698 { 699 /* Process async cancelation */ 700 if (g_fCopyCanceled && !fCanceledAlready) 701 { 702 hrc = progress->Cancel(); 703 if (SUCCEEDED(hrc)) 704 fCanceledAlready = TRUE; 705 else 706 g_fCopyCanceled = false; 707 } 708 709 /* Progress canceled by Main API? */ 710 if ( SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled))) 711 && fCanceled) 712 { 713 break; 714 } 715 } 716 717 /* Undo signal handling */ 718 if (fCancelable) 719 { 720 signal(SIGINT, SIG_DFL); 721 #ifdef SIGBREAK 722 signal(SIGBREAK, SIG_DFL); 723 #endif 724 } 725 726 if (fCanceled) 727 { 728 if (fVerbose) 729 RTPrintf("Copy operation canceled!\n"); 730 } 731 else if ( fCompleted 732 && SUCCEEDED(rc)) 733 { 734 LONG iRc = false; 735 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc); 736 if (FAILED(iRc)) 737 { 738 com::ProgressErrorInfo info(progress); 739 if ( info.isFullAvailable() 740 || info.isBasicAvailable()) 741 { 742 /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way 743 * because it contains more accurate info about what went wrong. */ 744 if (info.getResultCode() == VBOX_E_IPRT_ERROR) 745 RTMsgError("%ls.", info.getText().raw()); 746 else 747 { 748 RTMsgError("Copy operation error details:"); 749 GluePrintErrorInfo(info); 750 } 751 } 752 else 753 { 754 if (RT_FAILURE(rc)) 755 RTMsgError("Error while looking up error code, rc=%Rrc", rc); 756 else 757 com::GluePrintRCMessage(iRc); 758 } 759 } 760 else if (fVerbose) 761 { 762 RTPrintf("Copy operation successful!\n"); 763 } 764 } 765 else 766 { 767 if (fVerbose) 768 RTPrintf("Copy operation aborted!\n"); 769 } 770 } 771 a->session->UnlockMachine(); 772 } while (0); 773 } 774 return SUCCEEDED(rc) ? 0 : 1; 775 } 776 #endif 535 777 536 778 /** … … 552 794 if ( strcmp(a->argv[0], "exec") == 0 553 795 || strcmp(a->argv[0], "execute") == 0) 554 return handleExecProgram(&arg); 796 { 797 return handleCtrlExecProgram(&arg); 798 } 799 #ifdef VBOX_WITH_COPYTOGUEST 800 else if ( strcmp(a->argv[0], "copyto") == 0 801 || strcmp(a->argv[0], "copy_to") == 0) 802 { 803 return handleCtrlCopyTo(&arg); 804 } 805 #endif 555 806 556 807 /* default: */ -
trunk/src/VBox/Main/GuestImpl.cpp
r32855 r32866 33 33 #endif 34 34 #include <iprt/cpp/utils.h> 35 #include <iprt/dir.h> 35 36 #include <iprt/getopt.h> 37 #include <iprt/list.h> 38 #include <iprt/path.h> 36 39 #include <VBox/pgm.h> 37 40 … … 1539 1542 } 1540 1543 1544 #ifdef VBOX_WITH_COPYTOGUEST 1545 int Guest::directoryEntryAppend(const char *pszPath, PRTLISTNODE pList) 1546 { 1547 using namespace guestControl; 1548 1549 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 1550 AssertPtrReturn(pList, VERR_INVALID_POINTER); 1551 1552 LogFlowFunc(("Appending to pList=%p: %s\n", pList, pszPath)); 1553 1554 DirEntry *pNode = (DirEntry*)RTMemAlloc(sizeof(DirEntry)); 1555 if (pNode == NULL) 1556 return VERR_NO_MEMORY; 1557 1558 if (RT_SUCCESS(RTStrAAppend(&pNode->pszPath, pszPath))) 1559 { 1560 pNode->Node.pPrev = NULL; 1561 pNode->Node.pNext = NULL; 1562 RTListAppend(pList, &pNode->Node); 1563 return VINF_SUCCESS; 1564 } 1565 return VERR_NO_MEMORY; 1566 } 1567 1568 int Guest::directoryRead(const char *pszDirectory, const char *pszFilter, 1569 ULONG uFlags, ULONG *pcObjects, PRTLISTNODE pList) 1570 { 1571 using namespace guestControl; 1572 1573 AssertPtrReturn(pszDirectory, VERR_INVALID_POINTER); 1574 /* Filter is optional. */ 1575 AssertPtrReturn(pcObjects, VERR_INVALID_POINTER); 1576 AssertPtrReturn(pList, VERR_INVALID_POINTER); 1577 1578 LogFlowFunc(("Reading directory: %s, filter: %s\n", 1579 pszDirectory, pszFilter ? pszFilter : "<None>")); 1580 1581 char *pszDirWithFilter = NULL; 1582 PRTDIR pDir; 1583 int rc = RTStrAAppend(&pszDirWithFilter, pszDirectory); 1584 if (RT_SUCCESS(rc)) 1585 { 1586 if (pszFilter) 1587 { 1588 RTStrAAppend(&pszDirWithFilter, pszDirectory); 1589 rc = RTDirOpenFiltered(&pDir, pszDirectory, RTDIRFILTER_WINNT); 1590 } 1591 else 1592 rc = RTDirOpen(&pDir, pszDirectory); 1593 } 1594 1595 if (RT_SUCCESS(rc)) 1596 { 1597 rc = directoryEntryAppend(pszDirectory, pList); 1598 if (RT_SUCCESS(rc)) 1599 { 1600 *pcObjects = *pcObjects + 1; 1601 for (;;) 1602 { 1603 RTDIRENTRY DirEntry; 1604 rc = RTDirRead(pDir, &DirEntry, NULL); 1605 if (RT_FAILURE(rc)) 1606 break; 1607 switch (DirEntry.enmType) 1608 { 1609 case RTDIRENTRYTYPE_DIRECTORY: 1610 if (uFlags & CopyFileFlag_Recursive) 1611 rc = directoryRead(DirEntry.szName, pszFilter, 1612 uFlags, pcObjects, pList); 1613 break; 1614 1615 case RTDIRENTRYTYPE_FILE: 1616 { 1617 char *pszFile; 1618 if (RTStrAPrintf(&pszFile, "%s/%s", 1619 pszDirectory, DirEntry.szName)) 1620 { 1621 rc = directoryEntryAppend(pszFile, pList); 1622 if (RT_SUCCESS(rc)) 1623 *pcObjects = *pcObjects + 1; 1624 RTStrFree(pszFile); 1625 } 1626 break; 1627 } 1628 1629 case RTDIRENTRYTYPE_SYMLINK: 1630 if ( (uFlags & CopyFileFlag_Recursive) 1631 && (uFlags & CopyFileFlag_FollowLinks)) 1632 { 1633 rc = directoryRead(DirEntry.szName, pszFilter, 1634 uFlags, pcObjects, pList); 1635 } 1636 break; 1637 1638 default: 1639 break; 1640 } 1641 if (RT_FAILURE(rc)) 1642 break; 1643 } 1644 } 1645 RTDirClose(pDir); 1646 } 1647 if (pszDirWithFilter) 1648 RTStrFree(pszDirWithFilter); 1649 return rc; 1650 } 1651 #endif 1652 1653 STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest, ULONG aFlags, 1654 IProgress **aProgress) 1655 { 1656 #ifndef VBOX_WITH_GUEST_CONTROL 1657 ReturnComNotImplemented(); 1658 #else /* VBOX_WITH_GUEST_CONTROL */ 1659 #ifndef VBOX_WITH_COPYTOGUEST 1660 ReturnComNotImplemented(); 1661 #else 1662 using namespace guestControl; 1663 1664 CheckComArgStrNotEmptyOrNull(aSource); 1665 CheckComArgStrNotEmptyOrNull(aDest); 1666 CheckComArgOutPointerValid(aProgress); 1667 1668 AutoCaller autoCaller(this); 1669 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1670 1671 /* Validate flags. */ 1672 if (aFlags) 1673 { 1674 if ( !(aFlags & CopyFileFlag_Recursive) 1675 && !(aFlags & CopyFileFlag_Update) 1676 && !(aFlags & CopyFileFlag_FollowLinks)) 1677 return E_INVALIDARG; 1678 } 1679 1680 HRESULT rc = S_OK; 1681 1682 try 1683 { 1684 char szSourceAbs[RTPATH_MAX]; 1685 Utf8Str Utf8Dest(aDest); 1686 1687 int vrc = RTPathAbs(Utf8Str(aSource).c_str(), 1688 szSourceAbs, sizeof(szSourceAbs)); 1689 if (RT_SUCCESS(vrc)) 1690 { 1691 LogRel(("Copying \"%s\" to guest into \"%s\" ...\n", 1692 szSourceAbs, Utf8Dest.c_str())); 1693 } 1694 else 1695 rc = setError(VBOX_E_IPRT_ERROR, 1696 tr("Could not determine absolute path! rc=%Rrc"), vrc); 1697 1698 ULONG cObjectsToCopy = 0; 1699 RTLISTNODE listEntries; 1700 if (SUCCEEDED(rc)) 1701 { 1702 /* 1703 * Count objects to copy. 1704 * This is needed for have multi operation progress object. 1705 * Examples: 1706 * D:\ -> D:\* 1707 * E:\asdf\qwer\ -> E:\asdf\qwer\* 1708 * C:\temp.txt 1709 * C:\Foo\bar\*.txt 1710 * /home/foo/bar/movie.avi 1711 */ 1712 char *pszFileName = RTPathFilename(szSourceAbs); 1713 RTListInit(&listEntries); 1714 1715 vrc = directoryRead(szSourceAbs, pszFileName /* Filter */, 1716 aFlags, &cObjectsToCopy, &listEntries); 1717 if (RT_FAILURE(vrc)) 1718 rc = setError(VBOX_E_IPRT_ERROR, 1719 tr("Could not open source directory! rc=%Rrc"), vrc); 1720 } 1721 1722 if (SUCCEEDED(rc)) 1723 { 1724 /* 1725 * Create progress object. Note that this is a multi operation 1726 * object to perform an operation per the following steps: 1727 * - Operation 1 (0): Create/start process. 1728 * - Operation 2 (1): Wait for process to exit. 1729 * If this progress completed successfully (S_OK), the process 1730 * started and exited normally. In any other case an error/exception 1731 * occured. 1732 */ 1733 ComObjPtr <Progress> progress; 1734 rc = progress.createObject(); 1735 if (SUCCEEDED(rc)) 1736 { 1737 rc = progress->init(static_cast<IGuest*>(this), 1738 Bstr(tr("Executing process")).raw(), 1739 TRUE, 1740 cObjectsToCopy, /* Number of operations. */ 1741 Bstr(tr("Starting process ...")).raw()); /* Description of first stage. */ 1742 } 1743 if (FAILED(rc)) return rc; 1744 } 1745 1746 /* Destroy list. */ 1747 DirEntry *pNode = RTListNodeGetFirst(&listEntries, DirEntry, Node); 1748 while (pNode) 1749 { 1750 DirEntry *pNext = RTListNodeGetNext(&pNode->Node, DirEntry, Node); 1751 bool fLast = RTListNodeIsLast(&listEntries, &pNode->Node); 1752 1753 if (pNode->pszPath) 1754 RTStrFree(pNode->pszPath); 1755 RTListNodeRemove(&pNode->Node); 1756 RTMemFree(pNode); 1757 1758 if (fLast) 1759 break; 1760 1761 pNode = pNext; 1762 } 1763 } 1764 1765 #if 0 1766 1767 /* 1768 * Prepare process execution. 1769 */ 1770 int vrc = VINF_SUCCESS; 1771 Utf8Str Utf8Command(aCommand); 1772 1773 /* Adjust timeout */ 1774 if (aTimeoutMS == 0) 1775 aTimeoutMS = UINT32_MAX; 1776 1777 /* Prepare arguments. */ 1778 char **papszArgv = NULL; 1779 uint32_t uNumArgs = 0; 1780 if (aArguments > 0) 1781 { 1782 com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments)); 1783 uNumArgs = args.size(); 1784 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1)); 1785 AssertReturn(papszArgv, E_OUTOFMEMORY); 1786 for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++) 1787 vrc = RTUtf16ToUtf8(args[i], &papszArgv[i]); 1788 papszArgv[uNumArgs] = NULL; 1789 } 1790 1791 Utf8Str Utf8UserName(aUserName); 1792 Utf8Str Utf8Password(aPassword); 1793 if (RT_SUCCESS(vrc)) 1794 { 1795 uint32_t uContextID = 0; 1796 1797 char *pszArgs = NULL; 1798 if (uNumArgs > 0) 1799 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0); 1800 if (RT_SUCCESS(vrc)) 1801 { 1802 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 1803 1804 /* Prepare environment. */ 1805 void *pvEnv = NULL; 1806 uint32_t uNumEnv = 0; 1807 uint32_t cbEnv = 0; 1808 if (aEnvironment > 0) 1809 { 1810 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment)); 1811 1812 for (unsigned i = 0; i < env.size(); i++) 1813 { 1814 vrc = prepareExecuteEnv(Utf8Str(env[i]).c_str(), &pvEnv, &cbEnv, &uNumEnv); 1815 if (RT_FAILURE(vrc)) 1816 break; 1817 } 1818 } 1819 1820 LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n", 1821 Utf8Command.c_str(), Utf8UserName.c_str())); 1822 1823 if (RT_SUCCESS(vrc)) 1824 { 1825 PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS)); 1826 AssertReturn(pData, VBOX_E_IPRT_ERROR); 1827 RT_ZERO(*pData); 1828 uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START, 1829 pData, sizeof(CALLBACKDATAEXECSTATUS), progress); 1830 Assert(uContextID > 0); 1831 1832 VBOXHGCMSVCPARM paParms[15]; 1833 int i = 0; 1834 paParms[i++].setUInt32(uContextID); 1835 paParms[i++].setPointer((void*)Utf8Command.c_str(), (uint32_t)Utf8Command.length() + 1); 1836 paParms[i++].setUInt32(aFlags); 1837 paParms[i++].setUInt32(uNumArgs); 1838 paParms[i++].setPointer((void*)pszArgs, cbArgs); 1839 paParms[i++].setUInt32(uNumEnv); 1840 paParms[i++].setUInt32(cbEnv); 1841 paParms[i++].setPointer((void*)pvEnv, cbEnv); 1842 paParms[i++].setPointer((void*)Utf8UserName.c_str(), (uint32_t)Utf8UserName.length() + 1); 1843 paParms[i++].setPointer((void*)Utf8Password.c_str(), (uint32_t)Utf8Password.length() + 1); 1844 paParms[i++].setUInt32(aTimeoutMS); 1845 1846 VMMDev *vmmDev; 1847 { 1848 /* Make sure mParent is valid, so set the read lock while using. 1849 * Do not keep this lock while doing the actual call, because in the meanwhile 1850 * another thread could request a write lock which would be a bad idea ... */ 1851 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1852 1853 /* Forward the information to the VMM device. */ 1854 AssertPtr(mParent); 1855 vmmDev = mParent->getVMMDev(); 1856 } 1857 1858 if (vmmDev) 1859 { 1860 LogFlowFunc(("hgcmHostCall numParms=%d\n", i)); 1861 vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD, 1862 i, paParms); 1863 } 1864 else 1865 vrc = VERR_INVALID_VM_HANDLE; 1866 RTMemFree(pvEnv); 1867 } 1868 RTStrFree(pszArgs); 1869 } 1870 if (RT_SUCCESS(vrc)) 1871 { 1872 LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS)); 1873 1874 /* 1875 * Wait for the HGCM low level callback until the process 1876 * has been started (or something went wrong). This is necessary to 1877 * get the PID. 1878 */ 1879 CallbackMapIter it = getCtrlCallbackContextByID(uContextID); 1880 BOOL fCanceled = FALSE; 1881 if (it != mCallbackMap.end()) 1882 { 1883 ComAssert(!it->second.pProgress.isNull()); 1884 1885 /* 1886 * Wait for the first stage (=0) to complete (that is starting the process). 1887 */ 1888 PCALLBACKDATAEXECSTATUS pData = NULL; 1889 rc = it->second.pProgress->WaitForOperationCompletion(0, aTimeoutMS); 1890 if (SUCCEEDED(rc)) 1891 { 1892 /* Was the operation canceled by one of the parties? */ 1893 rc = it->second.pProgress->COMGETTER(Canceled)(&fCanceled); 1894 if (FAILED(rc)) throw rc; 1895 1896 if (!fCanceled) 1897 { 1898 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1899 1900 pData = (PCALLBACKDATAEXECSTATUS)it->second.pvData; 1901 Assert(it->second.cbData == sizeof(CALLBACKDATAEXECSTATUS)); 1902 AssertPtr(pData); 1903 1904 /* Did we get some status? */ 1905 switch (pData->u32Status) 1906 { 1907 case PROC_STS_STARTED: 1908 /* Process is (still) running; get PID. */ 1909 *aPID = pData->u32PID; 1910 break; 1911 1912 /* In any other case the process either already 1913 * terminated or something else went wrong, so no PID ... */ 1914 case PROC_STS_TEN: /* Terminated normally. */ 1915 case PROC_STS_TEA: /* Terminated abnormally. */ 1916 case PROC_STS_TES: /* Terminated through signal. */ 1917 case PROC_STS_TOK: 1918 case PROC_STS_TOA: 1919 case PROC_STS_DWN: 1920 /* 1921 * Process (already) ended, but we want to get the 1922 * PID anyway to retrieve the output in a later call. 1923 */ 1924 *aPID = pData->u32PID; 1925 break; 1926 1927 case PROC_STS_ERROR: 1928 vrc = pData->u32Flags; /* u32Flags member contains IPRT error code. */ 1929 break; 1930 1931 case PROC_STS_UNDEFINED: 1932 vrc = VERR_TIMEOUT; /* Operation did not complete within time. */ 1933 break; 1934 1935 default: 1936 vrc = VERR_INVALID_PARAMETER; /* Unknown status, should never happen! */ 1937 break; 1938 } 1939 } 1940 else /* Operation was canceled. */ 1941 vrc = VERR_CANCELLED; 1942 } 1943 else /* Operation did not complete within time. */ 1944 vrc = VERR_TIMEOUT; 1945 1946 /* 1947 * Do *not* remove the callback yet - we might wait with the IProgress object on something 1948 * else (like end of process) ... 1949 */ 1950 if (RT_FAILURE(vrc)) 1951 { 1952 if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */ 1953 rc = setError(VBOX_E_IPRT_ERROR, 1954 tr("The file '%s' was not found on guest"), Utf8Command.c_str()); 1955 else if (vrc == VERR_PATH_NOT_FOUND) 1956 rc = setError(VBOX_E_IPRT_ERROR, 1957 tr("The path to file '%s' was not found on guest"), Utf8Command.c_str()); 1958 else if (vrc == VERR_BAD_EXE_FORMAT) 1959 rc = setError(VBOX_E_IPRT_ERROR, 1960 tr("The file '%s' is not an executable format on guest"), Utf8Command.c_str()); 1961 else if (vrc == VERR_AUTHENTICATION_FAILURE) 1962 rc = setError(VBOX_E_IPRT_ERROR, 1963 tr("The specified user '%s' was not able to logon on guest"), Utf8UserName.c_str()); 1964 else if (vrc == VERR_TIMEOUT) 1965 rc = setError(VBOX_E_IPRT_ERROR, 1966 tr("The guest did not respond within time (%ums)"), aTimeoutMS); 1967 else if (vrc == VERR_CANCELLED) 1968 rc = setError(VBOX_E_IPRT_ERROR, 1969 tr("The execution operation was canceled")); 1970 else if (vrc == VERR_PERMISSION_DENIED) 1971 rc = setError(VBOX_E_IPRT_ERROR, 1972 tr("Invalid user/password credentials")); 1973 else 1974 { 1975 if (pData && pData->u32Status == PROC_STS_ERROR) 1976 rc = setError(VBOX_E_IPRT_ERROR, 1977 tr("Process could not be started: %Rrc"), pData->u32Flags); 1978 else 1979 rc = setError(E_UNEXPECTED, 1980 tr("The service call failed with error %Rrc"), vrc); 1981 } 1982 } 1983 else /* Execution went fine. */ 1984 { 1985 /* Return the progress to the caller. */ 1986 progress.queryInterfaceTo(aProgress); 1987 } 1988 } 1989 else /* Callback context not found; should never happen! */ 1990 AssertMsg(it != mCallbackMap.end(), ("Callback context with ID %u not found!", uContextID)); 1991 } 1992 else /* HGCM related error codes .*/ 1993 { 1994 if (vrc == VERR_INVALID_VM_HANDLE) 1995 rc = setError(VBOX_E_VM_ERROR, 1996 tr("VMM device is not available (is the VM running?)")); 1997 else if (vrc == VERR_TIMEOUT) 1998 rc = setError(VBOX_E_VM_ERROR, 1999 tr("The guest execution service is not ready")); 2000 else if (vrc == VERR_HGCM_SERVICE_NOT_FOUND) 2001 rc = setError(VBOX_E_VM_ERROR, 2002 tr("The guest execution service is not available")); 2003 else /* HGCM call went wrong. */ 2004 rc = setError(E_UNEXPECTED, 2005 tr("The HGCM call failed with error %Rrc"), vrc); 2006 } 2007 2008 for (unsigned i = 0; i < uNumArgs; i++) 2009 RTMemFree(papszArgv[i]); 2010 RTMemFree(papszArgv); 2011 } 2012 2013 if (RT_FAILURE(vrc)) 2014 LogRel(("Executing guest process \"%s\" as user \"%s\" failed with %Rrc\n", 2015 Utf8Command.c_str(), Utf8UserName.c_str(), vrc)); 2016 #endif 2017 catch (std::bad_alloc &) 2018 { 2019 rc = E_OUTOFMEMORY; 2020 } 2021 return rc; 2022 #endif /* VBOX_WITH_COPYTOGUEST */ 2023 #endif /* VBOX_WITH_GUEST_CONTROL */ 2024 } 2025 1541 2026 // public methods only for internal purposes 1542 2027 ///////////////////////////////////////////////////////////////////////////// -
trunk/src/VBox/Main/Makefile.kmk
r32728 r32866 58 58 $(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,) \ 59 59 $(if $(VBOX_WITH_NETFLT),VBOX_WITH_NETFLT,) \ 60 $(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST,) \ 60 61 $(if $(VBOX_WITH_CROGL),VBOX_WITH_CROGL,) \ 61 62 $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,) \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r32852 r32866 7719 7719 </enum> 7720 7720 7721 <enum 7722 name="CopyFileFlag" 7723 uuid="23f79fdf-738a-493d-b80b-42d607c9b916" 7724 > 7725 <desc> 7726 Host/Guest copy flags. 7727 </desc> 7728 7729 <const name="None" value="0"> 7730 <desc>No flag set.</desc> 7731 </const> 7732 7733 <const name="Recursive" value="2"> 7734 <desc>Copy directories recursively.</desc> 7735 </const> 7736 7737 <const name="Update" value="4"> 7738 <desc>Copy only when the source file is newer than the destination file or when the destination file is missing.</desc> 7739 </const> 7740 7741 <const name="FollowLinks" value="4"> 7742 <desc>Follow symbolic links.</desc> 7743 </const> 7744 </enum> 7745 7721 7746 <interface 7722 7747 name="IGuest" extends="$unknown" 7723 uuid=" cd80e5b8-faef-4be3-8d0e-d68fee10708d"7748 uuid="6e3113ac-ed90-4864-8c2c-942c8022324d" 7724 7749 wsmap="managed" 7725 7750 > … … 8007 8032 The current process status. 8008 8033 </desc> 8034 </param> 8035 </method> 8036 8037 <method name="copyToGuest"> 8038 <desc> 8039 Copies files/directories from host to the guest. 8040 8041 <result name="VBOX_E_IPRT_ERROR"> 8042 Error while copying. 8043 </result> 8044 8045 </desc> 8046 <param name="source" type="wstring" dir="in"> 8047 <desc> 8048 Foo. 8049 </desc> 8050 </param> 8051 <param name="dest" type="wstring" dir="in"> 8052 <desc> 8053 Bar. 8054 </desc> 8055 </param> 8056 <param name="flags" type="unsigned long" dir="in"> 8057 <desc> 8058 Copy flags. 8059 </desc> 8060 </param> 8061 <param name="progress" type="IProgress" dir="return"> 8062 <desc>Progress object to track the operation completion.</desc> 8009 8063 </param> 8010 8064 </method> -
trunk/src/VBox/Main/include/GuestImpl.h
r32086 r32866 20 20 21 21 #include "VirtualBoxBase.h" 22 #include <iprt/list.h> 22 23 #include <VBox/ostypes.h> 23 24 … … 99 100 STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData)); 100 101 STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG *aStatus); 102 STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, ULONG aFlags, IProgress **aProgress); 101 103 STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, 102 104 ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache, … … 148 150 typedef std::map< uint32_t, GuestProcess >::iterator GuestProcessMapIter; 149 151 typedef std::map< uint32_t, GuestProcess >::const_iterator GuestProcessMapIterConst; 152 153 #ifdef VBOX_WITH_COPYTOGUEST 154 /* 155 * 156 */ 157 struct DirEntry 158 { 159 char *pszPath; 160 RTLISTNODE Node; 161 }; 162 163 int directoryEntryAppend(const char *pszPath, PRTLISTNODE pList); 164 int directoryRead(const char *pszDirectory, const char *pszFilter, ULONG uFlags, ULONG *pcObjects, PRTLISTNODE pList); 165 #endif 150 166 151 167 int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
Note:
See TracChangeset
for help on using the changeset viewer.

