~ubuntu-branches/ubuntu/quantal/virtualbox/quantal

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-client/GuestCtrlImpl.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2012-04-05 12:41:55 UTC
  • mfrom: (3.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120405124155-i7b39tv5ddwhubbe
Tags: 4.1.12-dfsg-2
* Upstream has replaced the 4.1.12 tarball with a new one that fixes a
  crash when creating host only interfaces. (Closes: #667460)
  - Add 36-tarball-respin.patch which contains the diff between the old
    and the new tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
153
153
}
154
154
 
155
155
/**
 
156
 * Assigns a host PID to a specified context.
 
157
 * Does not do locking!
 
158
 *
 
159
 * @param   uContextID
 
160
 * @param   uHostPID
 
161
 */
 
162
int Guest::callbackAssignHostPID(uint32_t uContextID, uint32_t uHostPID)
 
163
{
 
164
    AssertReturn(uContextID, VERR_INVALID_PARAMETER);
 
165
    AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
 
166
 
 
167
    int rc = VINF_SUCCESS;
 
168
 
 
169
    CallbackMapIter it = mCallbackMap.find(uContextID);
 
170
    if (it == mCallbackMap.end())
 
171
        return VERR_NOT_FOUND;
 
172
 
 
173
    it->second.uHostPID = uHostPID;
 
174
 
 
175
    return VINF_SUCCESS;
 
176
}
 
177
 
 
178
/**
156
179
 * Destroys the formerly allocated callback data. The callback then
157
180
 * needs to get removed from the callback map via callbackRemove().
158
181
 * Does not do locking!
200
223
    return (it == mCallbackMap.end()) ? false : true;
201
224
}
202
225
 
 
226
/**
 
227
 * Frees the user data (actual context data) of a callback.
 
228
 * Does not do locking!
 
229
 *
 
230
 * @param   pvData              Data to free.
 
231
 */
203
232
void Guest::callbackFreeUserData(void *pvData)
204
233
{
205
234
    if (pvData)
209
238
    }
210
239
}
211
240
 
 
241
/**
 
242
 * Retrieves the (generated) host PID of a given callback.
 
243
 *
 
244
 * @return  The host PID, if found, 0 otherwise.
 
245
 * @param   uContextID              Context ID to lookup host PID for.
 
246
 * @param   puHostPID               Where to store the host PID.
 
247
 */
 
248
uint32_t Guest::callbackGetHostPID(uint32_t uContextID)
 
249
{
 
250
    AssertReturn(uContextID, VERR_INVALID_PARAMETER);
 
251
 
 
252
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
253
 
 
254
    CallbackMapIterConst it = mCallbackMap.find(uContextID);
 
255
    if (it == mCallbackMap.end())
 
256
        return 0;
 
257
 
 
258
    return it->second.uHostPID;
 
259
}
 
260
 
212
261
int Guest::callbackGetUserData(uint32_t uContextID, eVBoxGuestCtrlCallbackType *pEnmType,
213
262
                               void **ppvData, size_t *pcbData)
214
263
{
245
294
 * modify the data ...*/
246
295
void* Guest::callbackGetUserDataMutableRaw(uint32_t uContextID, size_t *pcbData)
247
296
{
248
 
    AssertReturn(uContextID, NULL);
 
297
    /* uContextID can be 0. */
249
298
    /* pcbData is optional. */
250
299
 
251
300
    CallbackMapIterConst it = mCallbackMap.find(uContextID);
315
364
 
316
365
bool Guest::callbackIsCanceled(uint32_t uContextID)
317
366
{
318
 
    AssertReturn(uContextID, true);
 
367
    if (!uContextID)
 
368
        return true; /* If no context ID given then take a shortcut. */
319
369
 
320
370
    ComPtr<IProgress> pProgress;
321
371
    {
457
507
            }
458
508
            else
459
509
            {
460
 
 
461
510
                hRC = pProgress->notifyComplete(VBOX_E_IPRT_ERROR /* Must not be S_OK. */,
462
511
                                                COM_IIDOF(IGuest),
463
512
                                                Guest::getStaticComponentName(),
481
530
}
482
531
 
483
532
/**
484
 
 * TODO
 
533
 * Notifies all callbacks which are assigned to a certain guest PID to set a certain
 
534
 * return/error code and an optional (error) message.
485
535
 *
486
536
 * @return  IPRT status code.
487
 
 * @param   uPID
488
 
 * @param   iRC
489
 
 * @param   pszMessage
 
537
 * @param   uGuestPID               Guest PID to find all callbacks for.
 
538
 * @param   iRC                     Return (error) code to set for the found callbacks.
 
539
 * @param   pszMessage              Optional (error) message to set.
490
540
 */
491
 
int Guest::callbackNotifyAllForPID(uint32_t uPID, int iRC, const char *pszMessage)
 
541
int Guest::callbackNotifyAllForPID(uint32_t uGuestPID, int iRC, const char *pszMessage)
492
542
{
493
 
    AssertReturn(uPID, VERR_INVALID_PARAMETER);
 
543
    AssertReturn(uGuestPID, VERR_INVALID_PARAMETER);
494
544
 
495
545
    int vrc = VINF_SUCCESS;
496
546
 
511
561
            {
512
562
                PCALLBACKDATAEXECOUT pItData = (PCALLBACKDATAEXECOUT)it->second.pvData;
513
563
                AssertPtr(pItData);
514
 
                if (pItData->u32PID == uPID)
 
564
                if (pItData->u32PID == uGuestPID)
515
565
                    vrc = callbackNotifyEx(it->first, iRC, pszMessage);
516
566
                break;
517
567
            }
523
573
            {
524
574
                PCALLBACKDATAEXECINSTATUS pItData = (PCALLBACKDATAEXECINSTATUS)it->second.pvData;
525
575
                AssertPtr(pItData);
526
 
                if (pItData->u32PID == uPID)
 
576
                if (pItData->u32PID == uGuestPID)
527
577
                    vrc = callbackNotifyEx(it->first, iRC, pszMessage);
528
578
                break;
529
579
            }
701
751
    AssertPtrReturn(pData, VERR_INVALID_PARAMETER);
702
752
 
703
753
    uint32_t uContextID = pData->hdr.u32ContextID;
704
 
    Assert(uContextID);
 
754
    /* The context ID might be 0 in case the guest was not able to fetch
 
755
     * actual command. So we can't do much now but report an error. */
705
756
 
706
757
    /* Scope write locks as much as possible. */
707
758
    {
734
785
        /* Handle process map. This needs to be done first in order to have a valid
735
786
         * map in case some callback gets notified a bit below. */
736
787
 
 
788
        uint32_t uHostPID = 0;
 
789
 
737
790
        /* Note: PIDs never get removed here in case the guest process signalled its
738
791
         *       end; instead the next call of GetProcessStatus() will remove the PID
739
792
         *       from the process map after we got the process' final (exit) status.
740
793
         *       See waitpid() for an example. */
741
794
        if (pData->u32PID) /* Only add/change a process if it has a valid PID (>0). */
742
795
        {
 
796
            uHostPID = callbackGetHostPID(uContextID);
 
797
            Assert(uHostPID);
 
798
 
743
799
            switch (pData->u32Status)
744
800
            {
745
801
                /* Just reach through flags. */
746
802
                case PROC_STS_TES:
747
803
                case PROC_STS_TOK:
748
 
                    vrc = processSetStatus(pData->u32PID,
 
804
                    vrc = processSetStatus(uHostPID, pData->u32PID,
749
805
                                           (ExecuteProcessStatus_T)pData->u32Status,
750
 
                                           0 /* Exit code. */, pData->u32Flags);
 
806
                                           0 /* Exit code */, pData->u32Flags);
751
807
                    break;
752
808
                /* Interprete u32Flags as the guest process' exit code. */
753
809
                default:
754
 
                    vrc = processSetStatus(pData->u32PID,
 
810
                    vrc = processSetStatus(uHostPID, pData->u32PID,
755
811
                                           (ExecuteProcessStatus_T)pData->u32Status,
756
 
                                           pData->u32Flags /* Exit code. */, 0 /* Flags. */);
757
 
 
 
812
                                           pData->u32Flags /* Exit code */, 0 /* Flags */);
758
813
                    break;
759
814
            }
760
815
        }
761
816
 
762
 
        /* Do progress handling. */
763
 
        switch (pData->u32Status)
 
817
        if (RT_SUCCESS(vrc))
764
818
        {
765
 
            case PROC_STS_STARTED:
766
 
                vrc = callbackMoveForward(uContextID, Guest::tr("Waiting for process to exit ..."));
767
 
                LogRel(("Guest process (PID %u) started\n", pData->u32PID)); /** @todo Add process name */
768
 
                break;
769
 
 
770
 
            case PROC_STS_TEN: /* Terminated normally. */
771
 
                vrc = callbackNotifyComplete(uContextID);
772
 
                LogRel(("Guest process (PID %u) exited normally\n", pData->u32PID)); /** @todo Add process name */
773
 
                break;
774
 
 
775
 
            case PROC_STS_TEA: /* Terminated abnormally. */
776
 
                LogRel(("Guest process (PID %u) terminated abnormally with exit code = %u\n",
777
 
                        pData->u32PID, pData->u32Flags)); /** @todo Add process name */
778
 
                errMsg = Utf8StrFmt(Guest::tr("Process terminated abnormally with status '%u'"),
779
 
                                    pData->u32Flags);
780
 
                rcCallback = VERR_GENERAL_FAILURE; /** @todo */
781
 
                break;
782
 
 
783
 
            case PROC_STS_TES: /* Terminated through signal. */
784
 
                LogRel(("Guest process (PID %u) terminated through signal with exit code = %u\n",
785
 
                        pData->u32PID, pData->u32Flags)); /** @todo Add process name */
786
 
                errMsg = Utf8StrFmt(Guest::tr("Process terminated via signal with status '%u'"),
787
 
                                    pData->u32Flags);
788
 
                rcCallback = VERR_GENERAL_FAILURE; /** @todo */
789
 
                break;
790
 
 
791
 
            case PROC_STS_TOK:
792
 
                LogRel(("Guest process (PID %u) timed out and was killed\n", pData->u32PID)); /** @todo Add process name */
793
 
                errMsg = Utf8StrFmt(Guest::tr("Process timed out and was killed"));
794
 
                rcCallback = VERR_TIMEOUT;
795
 
                break;
796
 
 
797
 
            case PROC_STS_TOA:
798
 
                LogRel(("Guest process (PID %u) timed out and could not be killed\n", pData->u32PID)); /** @todo Add process name */
799
 
                errMsg = Utf8StrFmt(Guest::tr("Process timed out and could not be killed"));
800
 
                rcCallback = VERR_TIMEOUT;
801
 
                break;
802
 
 
803
 
            case PROC_STS_DWN:
804
 
                LogRel(("Guest process (PID %u) killed because system is shutting down\n", pData->u32PID)); /** @todo Add process name */
805
 
                /*
806
 
                 * If u32Flags has ExecuteProcessFlag_IgnoreOrphanedProcesses set, we don't report an error to
807
 
                 * our progress object. This is helpful for waiters which rely on the success of our progress object
808
 
                 * even if the executed process was killed because the system/VBoxService is shutting down.
809
 
                 *
810
 
                 * In this case u32Flags contains the actual execution flags reached in via Guest::ExecuteProcess().
811
 
                 */
812
 
                if (pData->u32Flags & ExecuteProcessFlag_IgnoreOrphanedProcesses)
813
 
                {
 
819
            /* Do progress handling. */
 
820
            switch (pData->u32Status)
 
821
            {
 
822
                case PROC_STS_STARTED:
 
823
                    vrc = callbackMoveForward(uContextID, Guest::tr("Waiting for process to exit ..."));
 
824
                    LogRel(("Guest process (PID %u) started\n", pData->u32PID)); /** @todo Add process name */
 
825
                    break;
 
826
 
 
827
                case PROC_STS_TEN: /* Terminated normally. */
814
828
                    vrc = callbackNotifyComplete(uContextID);
815
 
                }
816
 
                else
817
 
                {
818
 
                    errMsg = Utf8StrFmt(Guest::tr("Process killed because system is shutting down"));
819
 
                    rcCallback = VERR_CANCELLED;
820
 
                }
821
 
                break;
822
 
 
823
 
            case PROC_STS_ERROR:
824
 
                if (pData->u32PID)
825
 
                {
826
 
                    LogRel(("Guest process (PID %u) could not be started because of rc=%Rrc\n",
827
 
                            pData->u32PID, pData->u32Flags)); /** @todo Add process name */
828
 
                }
829
 
                else
830
 
                {
831
 
                    switch (pData->u32Flags)
832
 
                    {
833
 
                        case VERR_MAX_PROCS_REACHED:
834
 
                            LogRel(("Guest process could not be started because maximum number of parallel guest processes has been reached\n"));
835
 
                            break;
836
 
 
837
 
                        default:
838
 
                            LogRel(("Guest process could not be started because of rc=%Rrc\n",
839
 
                                    pData->u32Flags));
840
 
                    }
841
 
 
842
 
                }
843
 
                errMsg = Utf8StrFmt(Guest::tr("Process execution failed with rc=%Rrc"), pData->u32Flags);
844
 
                rcCallback = pData->u32Flags; /* Report back rc. */
845
 
                break;
846
 
 
847
 
            default:
848
 
                vrc = VERR_INVALID_PARAMETER;
849
 
                break;
 
829
                    LogRel(("Guest process (PID %u) exited normally (exit code: %u)\n",
 
830
                            pData->u32PID, pData->u32Flags)); /** @todo Add process name */
 
831
                    break;
 
832
 
 
833
                case PROC_STS_TEA: /* Terminated abnormally. */
 
834
                    LogRel(("Guest process (PID %u) terminated abnormally (exit code: %u)\n",
 
835
                            pData->u32PID, pData->u32Flags)); /** @todo Add process name */
 
836
                    errMsg = Utf8StrFmt(Guest::tr("Process terminated abnormally with status '%u'"),
 
837
                                        pData->u32Flags);
 
838
                    rcCallback = VERR_GENERAL_FAILURE; /** @todo */
 
839
                    break;
 
840
 
 
841
                case PROC_STS_TES: /* Terminated through signal. */
 
842
                    LogRel(("Guest process (PID %u) terminated through signal (exit code: %u)\n",
 
843
                            pData->u32PID, pData->u32Flags)); /** @todo Add process name */
 
844
                    errMsg = Utf8StrFmt(Guest::tr("Process terminated via signal with status '%u'"),
 
845
                                        pData->u32Flags);
 
846
                    rcCallback = VERR_GENERAL_FAILURE; /** @todo */
 
847
                    break;
 
848
 
 
849
                case PROC_STS_TOK:
 
850
                    LogRel(("Guest process (PID %u) timed out and was killed\n", pData->u32PID)); /** @todo Add process name */
 
851
                    errMsg = Utf8StrFmt(Guest::tr("Process timed out and was killed"));
 
852
                    rcCallback = VERR_TIMEOUT;
 
853
                    break;
 
854
 
 
855
                case PROC_STS_TOA:
 
856
                    LogRel(("Guest process (PID %u) timed out and could not be killed\n", pData->u32PID)); /** @todo Add process name */
 
857
                    errMsg = Utf8StrFmt(Guest::tr("Process timed out and could not be killed"));
 
858
                    rcCallback = VERR_TIMEOUT;
 
859
                    break;
 
860
 
 
861
                case PROC_STS_DWN:
 
862
                    LogRel(("Guest process (PID %u) killed because system is shutting down\n", pData->u32PID)); /** @todo Add process name */
 
863
                    /*
 
864
                     * If u32Flags has ExecuteProcessFlag_IgnoreOrphanedProcesses set, we don't report an error to
 
865
                     * our progress object. This is helpful for waiters which rely on the success of our progress object
 
866
                     * even if the executed process was killed because the system/VBoxService is shutting down.
 
867
                     *
 
868
                     * In this case u32Flags contains the actual execution flags reached in via Guest::ExecuteProcess().
 
869
                     */
 
870
                    if (pData->u32Flags & ExecuteProcessFlag_IgnoreOrphanedProcesses)
 
871
                    {
 
872
                        vrc = callbackNotifyComplete(uContextID);
 
873
                    }
 
874
                    else
 
875
                    {
 
876
                        errMsg = Utf8StrFmt(Guest::tr("Process killed because system is shutting down"));
 
877
                        rcCallback = VERR_CANCELLED;
 
878
                    }
 
879
                    break;
 
880
 
 
881
                case PROC_STS_ERROR:
 
882
                {
 
883
                    Utf8Str errDetail;
 
884
                    if (pData->u32PID)
 
885
                    {
 
886
                        errDetail = Utf8StrFmt(Guest::tr("Guest process (PID %u) could not be started because of rc=%Rrc"),
 
887
                                               pData->u32PID, pData->u32Flags);
 
888
                    }
 
889
                    else
 
890
                    {
 
891
                        switch (pData->u32Flags) /* u32Flags member contains the IPRT error code from guest side. */
 
892
                        {
 
893
                            case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
 
894
                                errDetail = Utf8StrFmt(Guest::tr("The specified file was not found on guest"));
 
895
                                break;
 
896
 
 
897
                            case VERR_PATH_NOT_FOUND:
 
898
                                errDetail = Utf8StrFmt(Guest::tr("Could not resolve path to specified file was not found on guest"));
 
899
                                break;
 
900
 
 
901
                            case VERR_BAD_EXE_FORMAT:
 
902
                                errDetail = Utf8StrFmt(Guest::tr("The specified file is not an executable format on guest"));
 
903
                                break;
 
904
 
 
905
                            case VERR_AUTHENTICATION_FAILURE:
 
906
                                errDetail = Utf8StrFmt(Guest::tr("The specified user was not able to logon on guest"));
 
907
                                break;
 
908
 
 
909
                            case VERR_TIMEOUT:
 
910
                                errDetail = Utf8StrFmt(Guest::tr("The guest did not respond within time"));
 
911
                                break;
 
912
 
 
913
                            case VERR_CANCELLED:
 
914
                                errDetail = Utf8StrFmt(Guest::tr("The execution operation was canceled"));
 
915
                                break;
 
916
 
 
917
                            case VERR_PERMISSION_DENIED:
 
918
                                errDetail = Utf8StrFmt(Guest::tr("Invalid user/password credentials"));
 
919
                                break;
 
920
 
 
921
                            case VERR_MAX_PROCS_REACHED:
 
922
                                errDetail = Utf8StrFmt(Guest::tr("Guest process could not be started because maximum number of parallel guest processes has been reached"));
 
923
                                break;
 
924
 
 
925
                            default:
 
926
                                errDetail = Utf8StrFmt(Guest::tr("Guest process reported error %Rrc"), pData->u32Flags);
 
927
                                break;
 
928
                        }
 
929
                    }
 
930
 
 
931
                    errMsg = Utf8StrFmt(Guest::tr("Process execution failed: "), pData->u32Flags) + errDetail;
 
932
                    rcCallback = pData->u32Flags; /* Report back guest rc. */
 
933
 
 
934
                    LogRel((errMsg.c_str()));
 
935
 
 
936
                    break;
 
937
                }
 
938
 
 
939
                default:
 
940
                    vrc = VERR_INVALID_PARAMETER;
 
941
                    break;
 
942
            }
850
943
        }
851
944
    }
852
945
    else
860
953
    {
861
954
        AssertMsg(!errMsg.isEmpty(), ("Error message must not be empty!\n"));
862
955
 
863
 
        /* Notify all callbacks which are still waiting on something
864
 
         * which is related to the current PID. */
865
 
        if (pData->u32PID)
 
956
        if (uContextID)
866
957
        {
867
 
            int rc2 = callbackNotifyAllForPID(pData->u32PID, rcCallback, errMsg.c_str());
 
958
            /* Notify all callbacks which are still waiting on something
 
959
             * which is related to the current PID. */
 
960
            if (pData->u32PID)
 
961
            {
 
962
                int rc2 = callbackNotifyAllForPID(pData->u32PID, rcCallback, errMsg.c_str());
 
963
                if (RT_FAILURE(rc2))
 
964
                {
 
965
                    LogFlowFunc(("Failed to notify other callbacks for PID=%u\n",
 
966
                                 pData->u32PID));
 
967
                    if (RT_SUCCESS(vrc))
 
968
                        vrc = rc2;
 
969
                }
 
970
            }
 
971
 
 
972
            /* Let the caller know what went wrong ... */
 
973
            int rc2 = callbackNotifyEx(uContextID, rcCallback, errMsg.c_str());
868
974
            if (RT_FAILURE(rc2))
869
975
            {
870
 
                LogFlowFunc(("Failed to notify other callbacks for PID=%u\n",
871
 
                             pData->u32PID));
 
976
                LogFlowFunc(("Failed to notify callback CID=%u for PID=%u\n",
 
977
                             uContextID, pData->u32PID));
872
978
                if (RT_SUCCESS(vrc))
873
979
                    vrc = rc2;
874
980
            }
875
981
        }
876
 
 
877
 
        /* Let the caller know what went wrong ... */
878
 
        int rc2 = callbackNotifyEx(uContextID, rcCallback, errMsg.c_str());
879
 
        if (RT_FAILURE(rc2))
 
982
        else
880
983
        {
881
 
            LogFlowFunc(("Failed to notify callback CID=%u for PID=%u\n",
882
 
                         uContextID, pData->u32PID));
883
 
            if (RT_SUCCESS(vrc))
884
 
                vrc = rc2;
 
984
            /* Since we don't know which context exactly failed all we can do is to shutdown
 
985
             * all contexts ... */
 
986
            errMsg = Utf8StrFmt(Guest::tr("Client reported critical error %Rrc -- shutting down"),
 
987
                                pData->u32Flags);
 
988
 
 
989
            /* Cancel all callbacks. */
 
990
            CallbackMapIter it;
 
991
            for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
 
992
            {
 
993
                int rc2 = callbackNotifyEx(it->first, VERR_CANCELLED,
 
994
                                           errMsg.c_str());
 
995
                AssertRC(rc2);
 
996
            }
885
997
        }
 
998
 
886
999
        LogFlowFunc(("Process (CID=%u, status=%u) reported: %s\n",
887
1000
                     uContextID, pData->u32Status, errMsg.c_str()));
888
1001
    }
1000
1113
                            Guest::tr("Client disconnected"));
1001
1114
}
1002
1115
 
 
1116
uint32_t Guest::processGetGuestPID(uint32_t uHostPID)
 
1117
{
 
1118
    AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
 
1119
 
 
1120
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
1121
 
 
1122
    GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
 
1123
    if (it == mGuestProcessMap.end())
 
1124
        return 0;
 
1125
 
 
1126
    return it->second.mGuestPID;
 
1127
}
 
1128
 
1003
1129
/**
1004
1130
 * Gets guest process information. Removes the process from the map
1005
1131
 * after the process was marked as exited/terminated.
1006
1132
 *
1007
1133
 * @return  IPRT status code.
1008
 
 * @param   u32PID                  PID of process to get status for.
 
1134
 * @param   uHostPID                Host PID of guest process to get status for.
1009
1135
 * @param   pProcess                Where to store the process information. Optional.
1010
1136
 * @param   fRemove                 Flag indicating whether to remove the
1011
1137
 *                                  process from the map when process marked a
1012
1138
 *                                  exited/terminated.
1013
1139
 */
1014
 
int Guest::processGetStatus(uint32_t u32PID, PVBOXGUESTCTRL_PROCESS pProcess,
 
1140
int Guest::processGetStatus(uint32_t uHostPID, PVBOXGUESTCTRL_PROCESS pProcess,
1015
1141
                            bool fRemove)
1016
1142
{
1017
 
    AssertReturn(u32PID, VERR_INVALID_PARAMETER);
 
1143
    AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
1018
1144
 
1019
1145
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1020
1146
 
1021
 
    GuestProcessMapIter it = mGuestProcessMap.find(u32PID);
 
1147
    GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
1022
1148
    if (it != mGuestProcessMap.end())
1023
1149
    {
1024
1150
        if (pProcess)
1025
1151
        {
 
1152
            pProcess->mGuestPID = it->second.mGuestPID;
1026
1153
            pProcess->mStatus   = it->second.mStatus;
1027
1154
            pProcess->mExitCode = it->second.mExitCode;
1028
1155
            pProcess->mFlags    = it->second.mFlags;
1029
1156
        }
1030
1157
 
1031
 
        /* If the is marked as stopped/terminated
1032
 
         * remove it from the map. */
 
1158
        /* Only remove processes from our map when they signalled their final
 
1159
         * status. */
1033
1160
        if (   fRemove
1034
 
            && it->second.mStatus != ExecuteProcessStatus_Started)
 
1161
            && (   it->second.mStatus != ExecuteProcessStatus_Undefined
 
1162
                && it->second.mStatus != ExecuteProcessStatus_Started))
1035
1163
        {
1036
1164
            mGuestProcessMap.erase(it);
1037
1165
        }
1042
1170
    return VERR_NOT_FOUND;
1043
1171
}
1044
1172
 
1045
 
int Guest::processSetStatus(uint32_t u32PID, ExecuteProcessStatus_T enmStatus, uint32_t uExitCode, uint32_t uFlags)
 
1173
/**
 
1174
 * Sets the current status of a guest process.
 
1175
 *
 
1176
 * @return  IPRT status code.
 
1177
 * @param   uHostPID                Host PID of guest process to set status (and guest PID) for.
 
1178
 * @param   uGuestPID               Guest PID to assign to the host PID.
 
1179
 * @param   enmStatus               Current status to set.
 
1180
 * @param   uExitCode               Exit code (if any).
 
1181
 * @param   uFlags                  Additional flags.
 
1182
 */
 
1183
int Guest::processSetStatus(uint32_t uHostPID, uint32_t uGuestPID,
 
1184
                            ExecuteProcessStatus_T enmStatus, uint32_t uExitCode, uint32_t uFlags)
1046
1185
{
1047
 
    AssertReturn(u32PID, VERR_INVALID_PARAMETER);
 
1186
    AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
 
1187
    /* Assigning a guest PID is optional. */
1048
1188
 
1049
1189
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1050
1190
 
1051
 
    GuestProcessMapIter it = mGuestProcessMap.find(u32PID);
 
1191
    GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
1052
1192
    if (it != mGuestProcessMap.end())
1053
1193
    {
1054
 
        it->second.mStatus = enmStatus;
 
1194
        it->second.mGuestPID = uGuestPID;
 
1195
        it->second.mStatus   = enmStatus;
1055
1196
        it->second.mExitCode = uExitCode;
1056
 
        it->second.mFlags = uFlags;
 
1197
        it->second.mFlags    = uFlags;
1057
1198
    }
1058
1199
    else
1059
1200
    {
1060
1201
        VBOXGUESTCTRL_PROCESS process;
1061
1202
 
1062
 
        process.mStatus = enmStatus;
 
1203
        /* uGuestPID is optional -- the caller could call this function
 
1204
         * before the guest process actually was started and a (valid) guest PID
 
1205
         * was returned. */
 
1206
        process.mGuestPID = uGuestPID;
 
1207
        process.mStatus   = enmStatus;
1063
1208
        process.mExitCode = uExitCode;
1064
 
        process.mFlags = uFlags;
 
1209
        process.mFlags    = uFlags;
1065
1210
 
1066
 
        mGuestProcessMap[u32PID] = process;
 
1211
        mGuestProcessMap[uHostPID] = process;
1067
1212
    }
1068
1213
 
1069
1214
    return VINF_SUCCESS;
1070
1215
}
1071
1216
 
1072
 
HRESULT Guest::handleErrorCompletion(int rc)
 
1217
HRESULT Guest::setErrorCompletion(int rc)
1073
1218
{
1074
1219
    HRESULT hRC;
1075
1220
    if (rc == VERR_NOT_FOUND)
1087
1232
    return hRC;
1088
1233
}
1089
1234
 
1090
 
HRESULT Guest::handleErrorHGCM(int rc)
 
1235
HRESULT Guest::setErrorFromProgress(ComPtr<IProgress> pProgress)
 
1236
{
 
1237
    BOOL fCompleted;
 
1238
    HRESULT rc = pProgress->COMGETTER(Completed)(&fCompleted);
 
1239
    ComAssertComRC(rc);
 
1240
 
 
1241
    LONG rcProc = S_OK;
 
1242
    Utf8Str strError;
 
1243
 
 
1244
    if (!fCompleted)
 
1245
    {
 
1246
        BOOL fCanceled;
 
1247
        rc = pProgress->COMGETTER(Canceled)(&fCanceled);
 
1248
        ComAssertComRC(rc);
 
1249
 
 
1250
        strError = fCanceled ? Utf8StrFmt(Guest::tr("Process execution was canceled"))
 
1251
                             : Utf8StrFmt(Guest::tr("Process neither completed nor canceled; this shouldn't happen"));
 
1252
    }
 
1253
    else
 
1254
    {
 
1255
        rc = pProgress->COMGETTER(ResultCode)(&rcProc);
 
1256
        ComAssertComRC(rc);
 
1257
 
 
1258
        if (FAILED(rcProc))
 
1259
        {
 
1260
            ProgressErrorInfo info(pProgress);
 
1261
            strError = info.getText();
 
1262
        }
 
1263
    }
 
1264
 
 
1265
    if (FAILED(rcProc))
 
1266
    {
 
1267
        AssertMsg(!strError.isEmpty(), ("Error message must not be empty!\n"));
 
1268
        return setErrorInternal(rcProc,
 
1269
                                this->getClassIID(),
 
1270
                                this->getComponentName(),
 
1271
                                strError,
 
1272
                                false /* aWarning */,
 
1273
                                false /* aLogIt */);
 
1274
    }
 
1275
 
 
1276
    return S_OK;
 
1277
}
 
1278
 
 
1279
HRESULT Guest::setErrorHGCM(int rc)
1091
1280
{
1092
1281
    HRESULT hRC;
1093
1282
    if (rc == VERR_INVALID_VM_HANDLE)
1157
1346
                                     GuestCtrlStreamObjects *pObjStdOut, GuestCtrlStreamObjects *pObjStdErr,
1158
1347
                                     IProgress **aProgress, ULONG *aPID)
1159
1348
{
1160
 
    ComPtr<IProgress> progressTool;
 
1349
    ComPtr<IProgress> pProgress;
1161
1350
    ULONG uPID;
1162
1351
    ULONG uFlags = ExecuteProcessFlag_Hidden;
1163
1352
    if (uFlagsToAdd)
1164
1353
        uFlags |= uFlagsToAdd;
1165
1354
 
1166
 
    bool fWaitForOutput = false;
 
1355
    bool fParseOutput = false;
1167
1356
    if (   (   (uFlags & ExecuteProcessFlag_WaitForStdOut)
1168
1357
            && pObjStdOut)
1169
1358
        || (   (uFlags & ExecuteProcessFlag_WaitForStdErr)
1170
1359
            && pObjStdErr))
1171
1360
    {
1172
 
        fWaitForOutput = true;
 
1361
        fParseOutput = true;
1173
1362
    }
1174
1363
 
1175
 
    HRESULT rc = ExecuteProcess(aTool,
 
1364
    HRESULT hr = ExecuteProcess(aTool,
1176
1365
                                uFlags,
1177
1366
                                ComSafeArrayInArg(aArguments),
1178
1367
                                ComSafeArrayInArg(aEnvironment),
1179
1368
                                aUsername, aPassword,
1180
 
                                0 /* No timeout. */,
1181
 
                                &uPID, progressTool.asOutParam());
1182
 
    if (   SUCCEEDED(rc)
1183
 
        && fWaitForOutput)
1184
 
    {
1185
 
        BOOL fCompleted;
1186
 
        while (   SUCCEEDED(progressTool->COMGETTER(Completed)(&fCompleted))
1187
 
               && !fCompleted)
1188
 
        {
1189
 
            BOOL fCanceled;
1190
 
            rc = progressTool->COMGETTER(Canceled)(&fCanceled);
1191
 
            AssertComRC(rc);
1192
 
            if (fCanceled)
1193
 
            {
1194
 
                rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1195
 
                                   tr("%s was cancelled"), Utf8Str(aDescription).c_str());
1196
 
                break;
1197
 
            }
1198
 
 
1199
 
            if (   (uFlags & ExecuteProcessFlag_WaitForStdOut)
1200
 
                && pObjStdOut)
1201
 
            {
1202
 
                rc = executeStreamParse(uPID, ProcessOutputFlag_None /* StdOut */, *pObjStdOut);
1203
 
            }
1204
 
 
1205
 
            if (   (uFlags & ExecuteProcessFlag_WaitForStdErr)
1206
 
                && pObjStdErr)
1207
 
            {
1208
 
                rc = executeStreamParse(uPID, ProcessOutputFlag_StdErr, *pObjStdErr);
1209
 
            }
1210
 
 
1211
 
            if (FAILED(rc))
1212
 
                break;
1213
 
        }
1214
 
    }
1215
 
 
1216
 
    if (SUCCEEDED(rc))
 
1369
                                0 /* No timeout */,
 
1370
                                &uPID, pProgress.asOutParam());
 
1371
    if (SUCCEEDED(hr))
 
1372
    {
 
1373
        /* Wait for tool being started. */
 
1374
        hr = pProgress->WaitForOperationCompletion( 0 /* Stage, starting the process */,
 
1375
                                                   -1 /* No timeout */);
 
1376
    }
 
1377
 
 
1378
    if (   SUCCEEDED(hr)
 
1379
        && !(uFlags & ExecuteProcessFlag_WaitForProcessStartOnly))
 
1380
    {
 
1381
        if (!fParseOutput)
 
1382
        {
 
1383
            if (   !(uFlags & ExecuteProcessFlag_WaitForStdOut)
 
1384
                && !(uFlags & ExecuteProcessFlag_WaitForStdErr))
 
1385
            {
 
1386
                hr = executeWaitForExit(uPID, pProgress, 0 /* No timeout */);
 
1387
            }
 
1388
        }
 
1389
        else
 
1390
        {
 
1391
            BOOL fCompleted;
 
1392
            while (   SUCCEEDED(pProgress->COMGETTER(Completed)(&fCompleted))
 
1393
                   && !fCompleted)
 
1394
            {
 
1395
                BOOL fCanceled;
 
1396
                hr = pProgress->COMGETTER(Canceled)(&fCanceled);
 
1397
                AssertComRC(hr);
 
1398
                if (fCanceled)
 
1399
                {
 
1400
                    hr = setErrorNoLog(VBOX_E_IPRT_ERROR,
 
1401
                                       tr("%s was cancelled"), Utf8Str(aDescription).c_str());
 
1402
                    break;
 
1403
                }
 
1404
 
 
1405
                if (   (uFlags & ExecuteProcessFlag_WaitForStdOut)
 
1406
                    && pObjStdOut)
 
1407
                {
 
1408
                    hr = executeStreamParse(uPID, ProcessOutputFlag_None /* StdOut */, *pObjStdOut);
 
1409
                }
 
1410
 
 
1411
                if (   (uFlags & ExecuteProcessFlag_WaitForStdErr)
 
1412
                    && pObjStdErr)
 
1413
                {
 
1414
                    hr = executeStreamParse(uPID, ProcessOutputFlag_StdErr, *pObjStdErr);
 
1415
                }
 
1416
 
 
1417
                if (FAILED(hr))
 
1418
                    break;
 
1419
            }
 
1420
        }
 
1421
    }
 
1422
 
 
1423
    if (SUCCEEDED(hr))
1217
1424
    {
1218
1425
        if (aProgress)
1219
1426
        {
1220
1427
            /* Return the progress to the caller. */
1221
 
            progressTool.queryInterfaceTo(aProgress);
 
1428
            pProgress.queryInterfaceTo(aProgress);
1222
1429
        }
 
1430
        else if (!pProgress.isNull())
 
1431
            pProgress.setNull();
1223
1432
 
1224
1433
        if (aPID)
1225
1434
            *aPID = uPID;
1226
1435
    }
1227
1436
 
1228
 
    return rc;
1229
 
}
1230
 
 
1231
 
HRESULT Guest::executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout,
1232
 
                                    PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID)
1233
 
{
1234
 
    AssertPtrReturn(pExecStatus, E_INVALIDARG);
1235
 
    AssertPtrReturn(puPID, E_INVALIDARG);
1236
 
 
1237
 
    HRESULT rc = S_OK;
1238
 
 
1239
 
    /* Did we get some status? */
1240
 
    switch (pExecStatus->u32Status)
1241
 
    {
1242
 
        case PROC_STS_STARTED:
1243
 
            /* Process is (still) running; get PID. */
1244
 
            *puPID = pExecStatus->u32PID;
1245
 
            break;
1246
 
 
1247
 
        /* In any other case the process either already
1248
 
         * terminated or something else went wrong, so no PID ... */
1249
 
        case PROC_STS_TEN: /* Terminated normally. */
1250
 
        case PROC_STS_TEA: /* Terminated abnormally. */
1251
 
        case PROC_STS_TES: /* Terminated through signal. */
1252
 
        case PROC_STS_TOK:
1253
 
        case PROC_STS_TOA:
1254
 
        case PROC_STS_DWN:
1255
 
            /*
1256
 
             * Process (already) ended, but we want to get the
1257
 
             * PID anyway to retrieve the output in a later call.
1258
 
             */
1259
 
            *puPID = pExecStatus->u32PID;
1260
 
            break;
1261
 
 
1262
 
        case PROC_STS_ERROR:
1263
 
            {
1264
 
                int vrc = pExecStatus->u32Flags; /* u32Flags member contains IPRT error code. */
1265
 
                if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */
1266
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1267
 
                                       tr("The file '%s' was not found on guest"), pszCommand);
1268
 
                else if (vrc == VERR_PATH_NOT_FOUND)
1269
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1270
 
                                       tr("The path to file '%s' was not found on guest"), pszCommand);
1271
 
                else if (vrc == VERR_BAD_EXE_FORMAT)
1272
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1273
 
                                       tr("The file '%s' is not an executable format on guest"), pszCommand);
1274
 
                else if (vrc == VERR_AUTHENTICATION_FAILURE)
1275
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1276
 
                                       tr("The specified user '%s' was not able to logon on guest"), pszUser);
1277
 
                else if (vrc == VERR_TIMEOUT)
1278
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1279
 
                                       tr("The guest did not respond within time (%ums)"), ulTimeout);
1280
 
                else if (vrc == VERR_CANCELLED)
1281
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1282
 
                                       tr("The execution operation was canceled"));
1283
 
                else if (vrc == VERR_PERMISSION_DENIED)
1284
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1285
 
                                       tr("Invalid user/password credentials"));
1286
 
                else if (vrc == VERR_MAX_PROCS_REACHED)
1287
 
                    rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1288
 
                                       tr("Concurrent guest process limit is reached"));
1289
 
                else
1290
 
                {
1291
 
                    if (pExecStatus && pExecStatus->u32Status == PROC_STS_ERROR)
1292
 
                        rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1293
 
                                           tr("Process could not be started: %Rrc"), pExecStatus->u32Flags);
1294
 
                    else
1295
 
                        rc = setErrorNoLog(E_UNEXPECTED,
1296
 
                                           tr("The service call failed with error %Rrc"), vrc);
1297
 
                }
1298
 
            }
1299
 
            break;
1300
 
 
1301
 
        case PROC_STS_UNDEFINED: /* . */
1302
 
            rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1303
 
                               tr("The operation did not complete within time"));
1304
 
            break;
1305
 
 
1306
 
        default:
1307
 
            AssertReleaseMsgFailed(("Process (PID %u) reported back an undefined state!\n",
1308
 
                                    pExecStatus->u32PID));
1309
 
            rc = E_UNEXPECTED;
1310
 
            break;
1311
 
    }
1312
 
 
1313
 
    return rc;
 
1437
    return hr;
1314
1438
}
1315
1439
 
1316
1440
/**
1344
1468
 * @return  IPRT status code.
1345
1469
 * @param   aPID                    PID of process to get the output from.
1346
1470
 * @param   aFlags                  Which stream to drain (stdout or stderr).
1347
 
 * @param   stream                  Reference to guest process stream to fill.
 
1471
 * @param   pStream                 Pointer to guest process stream to fill. If NULL,
 
1472
 *                                  data goes to /dev/null.
1348
1473
 */
1349
 
int Guest::executeStreamDrain(ULONG aPID, ULONG aFlags, GuestProcessStream &stream)
 
1474
int Guest::executeStreamDrain(ULONG aPID, ULONG aFlags, GuestProcessStream *pStream)
1350
1475
{
1351
1476
    AssertReturn(aPID, VERR_INVALID_PARAMETER);
 
1477
    /* pStream is optional. */
1352
1478
 
1353
1479
    int rc = VINF_SUCCESS;
1354
1480
    for (;;)
1357
1483
        HRESULT hr = getProcessOutputInternal(aPID, aFlags,
1358
1484
                                              0 /* Infinite timeout */,
1359
1485
                                              _64K, ComSafeArrayAsOutParam(aData), &rc);
1360
 
        if (SUCCEEDED(hr))
 
1486
        if (RT_SUCCESS(rc))
1361
1487
        {
1362
 
            if (aData.size())
 
1488
            if (   pStream
 
1489
                && aData.size())
1363
1490
            {
1364
 
                rc = stream.AddData(aData.raw(), aData.size());
 
1491
                rc = pStream->AddData(aData.raw(), aData.size());
1365
1492
                if (RT_UNLIKELY(RT_FAILURE(rc)))
1366
1493
                    break;
1367
1494
            }
1376
1503
                rc = VINF_SUCCESS;
1377
1504
            }
1378
1505
 
1379
 
            /* In any case remove the (terminated/broken) process from
1380
 
             * the process table. */
1381
 
            int rc2 = processGetStatus(aPID, NULL /* PVBOXGUESTCTRL_PROCESS */,
1382
 
                                       true /* Remove from table */);
1383
 
            AssertRC(rc2);
1384
1506
            break;
1385
1507
        }
1386
1508
    }
1432
1554
                {
1433
1555
                    LogFlowFunc(("Got %ld bytes of additional data\n", aData.size()));
1434
1556
 
 
1557
                    if (RT_FAILURE(rc))
 
1558
                    {
 
1559
                        if (rc == VERR_BROKEN_PIPE)
 
1560
                             rc = VINF_SUCCESS; /* No more data because process already ended. */
 
1561
                        break;
 
1562
                    }
 
1563
 
1435
1564
                    if (aData.size())
1436
1565
                    {
1437
1566
                        rc = stream.AddData(aData.raw(), aData.size());
1522
1651
HRESULT Guest::executeStreamParse(ULONG ulPID, ULONG ulFlags, GuestCtrlStreamObjects &streamObjects)
1523
1652
{
1524
1653
    GuestProcessStream stream;
1525
 
    int rc = executeStreamDrain(ulPID, ulFlags, stream);
 
1654
    int rc = executeStreamDrain(ulPID, ulFlags, &stream);
1526
1655
    if (RT_SUCCESS(rc))
1527
1656
    {
1528
1657
        do
1560
1689
 * @param   puRetExitCode           Pointer where to store the final process
1561
1690
 *                                  exit code. Optional.
1562
1691
 */
1563
 
HRESULT Guest::executeWaitForExit(ULONG uPID, ComPtr<IProgress> pProgress, ULONG uTimeoutMS,
1564
 
                                  ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode)
 
1692
HRESULT Guest::executeWaitForExit(ULONG uPID, ComPtr<IProgress> pProgress, ULONG uTimeoutMS)
1565
1693
{
1566
1694
    HRESULT rc = S_OK;
1567
1695
 
1581
1709
                                          : uTimeoutMS);
1582
1710
        if (FAILED(rc))
1583
1711
            rc = setError(VBOX_E_IPRT_ERROR,
1584
 
                          tr("Waiting for guest process to end failed (%Rhrc)"),
1585
 
                          rc);
1586
 
    }
1587
 
 
1588
 
    if (SUCCEEDED(rc))
1589
 
    {
1590
 
        ULONG uExitCode, uRetFlags;
1591
 
        ExecuteProcessStatus_T enmStatus;
1592
 
        HRESULT hRC = GetProcessStatus(uPID, &uExitCode, &uRetFlags, &enmStatus);
1593
 
        if (FAILED(hRC))
1594
 
            return hRC;
1595
 
 
1596
 
        if (pRetStatus)
1597
 
            *pRetStatus = enmStatus;
1598
 
        if (puRetExitCode)
1599
 
            *puRetExitCode = uExitCode;
1600
 
        /** @todo Flags? */
 
1712
                          tr("Waiting for guest process to end failed (%Rhrc)"), rc);
1601
1713
    }
1602
1714
 
1603
1715
    return rc;
1696
1808
 
1697
1809
        Utf8Str Utf8UserName(aUsername);
1698
1810
        Utf8Str Utf8Password(aPassword);
 
1811
        uint32_t uHostPID = 0;
 
1812
 
1699
1813
        if (RT_SUCCESS(vrc))
1700
1814
        {
1701
1815
            uint32_t uContextID = 0;
1784
1898
 
1785
1899
            if (RT_SUCCESS(vrc))
1786
1900
            {
1787
 
                LogFlowFunc(("Waiting for HGCM callback (timeout=%RI32ms) ...\n", aTimeoutMS));
1788
 
 
1789
 
                /*
1790
 
                 * Wait for the HGCM low level callback until the process
1791
 
                 * has been started (or something went wrong). This is necessary to
1792
 
                 * get the PID.
1793
 
                 */
1794
 
 
1795
 
                PCALLBACKDATAEXECSTATUS pExecStatus = NULL;
1796
 
 
1797
 
                /*
1798
 
                 * Wait for the first stage (=0) to complete (that is starting the process).
1799
 
                 */
1800
 
                vrc = callbackWaitForCompletion(uContextID, 0 /* Stage */, aTimeoutMS);
1801
 
                if (RT_SUCCESS(vrc))
 
1901
                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
1902
 
 
1903
                /*
 
1904
                 * Generate a host-driven PID so that we immediately can return to the caller and
 
1905
                 * don't need to wait until the guest started the desired process to return the
 
1906
                 * PID generated by the guest OS.
 
1907
                 *
 
1908
                 * The guest PID will later be mapped to the host PID for later lookup.
 
1909
                 */
 
1910
                vrc = VERR_NOT_FOUND; /* We did not find a host PID yet ... */
 
1911
 
 
1912
                uint32_t uTries = 0;
 
1913
                for (;;)
1802
1914
                {
1803
 
                    vrc = callbackGetUserData(uContextID, NULL /* We know the type. */,
1804
 
                                              (void**)&pExecStatus, NULL /* Don't need the size. */);
1805
 
                    if (RT_SUCCESS(vrc))
1806
 
                    {
1807
 
                        rc = executeProcessResult(Utf8Command.c_str(), Utf8UserName.c_str(), aTimeoutMS,
1808
 
                                                  pExecStatus, aPID);
1809
 
                        callbackFreeUserData(pExecStatus);
1810
 
                    }
1811
 
                    else
1812
 
                    {
1813
 
                        rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
1814
 
                                           tr("Unable to retrieve process execution status data"));
1815
 
                    }
 
1915
                    /* Create a new context ID ... */
 
1916
                    uHostPID = ASMAtomicIncU32(&mNextHostPID);
 
1917
                    if (uHostPID == UINT32_MAX)
 
1918
                        ASMAtomicUoWriteU32(&mNextHostPID, 1000);
 
1919
                    /* Is the host PID already used? Try next PID ... */
 
1920
                    GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
 
1921
                    if (it == mGuestProcessMap.end())
 
1922
                    {
 
1923
                        /* Host PID not used (anymore), we're done here ... */
 
1924
                        vrc = VINF_SUCCESS;
 
1925
                        break;
 
1926
                    }
 
1927
 
 
1928
                    if (++uTries == UINT32_MAX)
 
1929
                        break; /* Don't try too hard. */
1816
1930
                }
1817
 
                else
1818
 
                    rc = handleErrorCompletion(vrc);
1819
 
 
1820
 
                /*
1821
 
                 * Do *not* remove the callback yet - we might wait with the IProgress object on something
1822
 
                 * else (like end of process) ...
1823
 
                 */
 
1931
 
 
1932
                if (RT_SUCCESS(vrc))
 
1933
                    vrc = processSetStatus(uHostPID, 0 /* No guest PID yet */,
 
1934
                                           ExecuteProcessStatus_Undefined /* Process not started yet */,
 
1935
                                           0 /* uExitCode */, 0 /* uFlags */);
 
1936
 
 
1937
                if (RT_SUCCESS(vrc))
 
1938
                    vrc = callbackAssignHostPID(uContextID, uHostPID);
1824
1939
            }
1825
1940
            else
1826
 
                rc = handleErrorHGCM(vrc);
 
1941
                rc = setErrorHGCM(vrc);
1827
1942
 
1828
1943
            for (unsigned i = 0; i < uNumArgs; i++)
1829
1944
                RTMemFree(papszArgv[i]);
1830
1945
            RTMemFree(papszArgv);
 
1946
 
 
1947
            if (RT_FAILURE(vrc))
 
1948
                rc = VBOX_E_IPRT_ERROR;
1831
1949
        }
1832
1950
 
1833
1951
        if (SUCCEEDED(rc))
1834
1952
        {
 
1953
            /* Return host PID. */
 
1954
            *aPID = uHostPID;
 
1955
 
1835
1956
            /* Return the progress to the caller. */
1836
1957
            pProgress.queryInterfaceTo(aProgress);
1837
1958
        }
1848
1969
    catch (std::bad_alloc &)
1849
1970
    {
1850
1971
        rc = E_OUTOFMEMORY;
 
1972
        if (pRC)
 
1973
            *pRC = VERR_NO_MEMORY;
1851
1974
    }
1852
1975
    return rc;
1853
1976
}
1884
2007
            /* PID exists; check if process is still running. */
1885
2008
            if (process.mStatus != ExecuteProcessStatus_Started)
1886
2009
                rc = setError(VBOX_E_IPRT_ERROR,
1887
 
                              Guest::tr("Cannot inject input to not running process (PID %u)"), aPID);
 
2010
                              Guest::tr("Cannot inject input to a not running process (PID %u)"), aPID);
1888
2011
        }
1889
2012
        else
1890
2013
            rc = setError(VBOX_E_IPRT_ERROR,
1891
 
                          Guest::tr("Cannot inject input to non-existent process (PID %u)"), aPID);
 
2014
                          Guest::tr("Cannot inject input to a non-existent process (PID %u)"), aPID);
1892
2015
 
1893
2016
        if (RT_SUCCESS(vrc))
1894
2017
        {
1895
2018
            uint32_t uContextID = 0;
1896
2019
 
 
2020
            uint32_t uGuestPID = processGetGuestPID(aPID);
 
2021
            Assert(uGuestPID);
 
2022
 
1897
2023
            /*
1898
2024
             * Create progress object.
1899
2025
             * This progress object, compared to the one in executeProgress() above,
1922
2048
                PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)callback.pvData;
1923
2049
 
1924
2050
                /* Save PID + output flags for later use. */
1925
 
                pData->u32PID = aPID;
 
2051
                pData->u32PID   = uGuestPID;
1926
2052
                pData->u32Flags = aFlags;
1927
2053
            }
1928
2054
 
1937
2063
                VBOXHGCMSVCPARM paParms[6];
1938
2064
                int i = 0;
1939
2065
                paParms[i++].setUInt32(uContextID);
1940
 
                paParms[i++].setUInt32(aPID);
 
2066
                paParms[i++].setUInt32(uGuestPID);
1941
2067
                paParms[i++].setUInt32(aFlags);
1942
2068
                paParms[i++].setPointer(sfaData.raw(), cbSize);
1943
2069
                paParms[i++].setUInt32(cbSize);
1961
2087
                        vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_SET_INPUT,
1962
2088
                                                   i, paParms);
1963
2089
                        if (RT_FAILURE(vrc))
1964
 
                            rc = handleErrorHGCM(vrc);
 
2090
                            rc = setErrorHGCM(vrc);
1965
2091
                    }
1966
2092
                }
1967
2093
            }
2019
2145
                    }
2020
2146
                }
2021
2147
                else
2022
 
                    rc = handleErrorCompletion(vrc);
 
2148
                    rc = setErrorCompletion(vrc);
2023
2149
            }
2024
2150
 
2025
2151
            {
2094
2220
        }
2095
2221
        else if (proc.mStatus != ExecuteProcessStatus_Started)
2096
2222
        {
2097
 
            /* If the process is still in the process table but does not run anymore
2098
 
             * don't remove it but report back an appropriate error. */
 
2223
            /* If the process is already or still in the process table but does not run yet
 
2224
             * (or anymore) don't remove it but report back an appropriate error. */
2099
2225
            vrc = VERR_BROKEN_PIPE;
2100
 
            rc = setError(VBOX_E_IPRT_ERROR,
2101
 
                          Guest::tr("Guest process (PID %u) does not run anymore"), aPID);
 
2226
            /* Not getting any output is fine, so don't report an API error (rc)
 
2227
             * and only signal something through internal error code (vrc). */
2102
2228
        }
2103
2229
 
2104
2230
        if (RT_SUCCESS(vrc))
2131
2257
            if (aFlags & ProcessOutputFlag_StdErr)
2132
2258
                uHandleID = OUTPUT_HANDLE_ID_STDERR;
2133
2259
 
 
2260
            uint32_t uGuestPID = processGetGuestPID(aPID);
 
2261
            Assert(uGuestPID);
 
2262
 
2134
2263
            /** @todo Use a buffer for next iteration if returned data is too big
2135
2264
             *        for current read.
2136
2265
             *        aSize is bogus -- will be ignored atm! */
2141
2270
                PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)callback.pvData;
2142
2271
 
2143
2272
                /* Save PID + output flags for later use. */
2144
 
                pData->u32PID = aPID;
 
2273
                pData->u32PID   = uGuestPID;
2145
2274
                pData->u32Flags = aFlags;
2146
2275
            }
2147
2276
 
2153
2282
                VBOXHGCMSVCPARM paParms[5];
2154
2283
                int i = 0;
2155
2284
                paParms[i++].setUInt32(uContextID);
2156
 
                paParms[i++].setUInt32(aPID);
 
2285
                paParms[i++].setUInt32(uGuestPID);
2157
2286
                paParms[i++].setUInt32(uHandleID);
2158
2287
                paParms[i++].setUInt32(0 /* Flags, none set yet */);
2159
2288
 
2236
2365
                    }
2237
2366
                }
2238
2367
                else
2239
 
                    rc = handleErrorCompletion(vrc);
 
2368
                    rc = setErrorCompletion(vrc);
2240
2369
            }
2241
2370
            else
2242
 
                rc = handleErrorHGCM(vrc);
 
2371
                rc = setErrorHGCM(vrc);
2243
2372
 
2244
2373
            {
2245
2374
                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2260
2389
    catch (std::bad_alloc &)
2261
2390
    {
2262
2391
        rc = E_OUTOFMEMORY;
 
2392
        if (pRC)
 
2393
            *pRC = VERR_NO_MEMORY;
2263
2394
    }
2264
2395
    return rc;
2265
2396
#endif
2412
2543
 
2413
2544
    HRESULT rc = S_OK;
2414
2545
 
2415
 
    ComObjPtr<Progress> progress;
 
2546
    ComObjPtr<Progress> pProgress;
2416
2547
    try
2417
2548
    {
2418
2549
        /* Create the progress object. */
2419
 
        progress.createObject();
 
2550
        pProgress.createObject();
2420
2551
 
2421
 
        rc = progress->init(static_cast<IGuest*>(this),
2422
 
                            Bstr(tr("Copying file from host to guest")).raw(),
2423
 
                            TRUE /* aCancelable */);
 
2552
        rc = pProgress->init(static_cast<IGuest*>(this),
 
2553
                             Bstr(tr("Copying file from host to guest")).raw(),
 
2554
                             TRUE /* aCancelable */);
2424
2555
        if (FAILED(rc)) throw rc;
2425
2556
 
2426
2557
        /* Initialize our worker task. */
2427
 
        GuestTask *pTask = new GuestTask(GuestTask::TaskType_CopyFileToGuest, this, progress);
 
2558
        GuestTask *pTask = new GuestTask(GuestTask::TaskType_CopyFileToGuest, this, pProgress);
2428
2559
        AssertPtr(pTask);
2429
2560
        std::auto_ptr<GuestTask> task(pTask);
2430
2561
 
2450
2581
    if (SUCCEEDED(rc))
2451
2582
    {
2452
2583
        /* Return progress to the caller. */
2453
 
        progress.queryInterfaceTo(aProgress);
 
2584
        pProgress.queryInterfaceTo(aProgress);
2454
2585
    }
2455
2586
    return rc;
2456
2587
#endif /* VBOX_WITH_GUEST_CONTROL */