VirtualBox

Changeset 49349 in vbox


Ignore:
Timestamp:
Oct 31, 2013 4:40:46 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
90367
Message:

Guest Control:

  • Implemented IGuestSession::DirectoryRemove, IGuestSession::DirectoryRemoveRecursive, IGuestSession::DirectoryRename + IGuestSession::FileRename.
  • Added appropriate commands to VBoxManage (basic support for now).
  • Implemented support for proper guest session process termination via SCM.
  • Implemented support for internal anonymous wait events which are not relying on the public API's VBoxEventType_T.
  • Various bugfixes.
Location:
trunk
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/user_VBoxManage.xml

    r49313 r49349  
    31623162
    31633163        <listitem>
     3164          <para><emphasis role="bold"><computeroutput>removedirectory</computeroutput></emphasis>,
     3165          which allows deletion of guest directories (only with installed Guest
     3166          Additions 4.3.2 and later).</para>
     3167
     3168          <screen>VBoxManage guestcontrol &lt;uuid|vmname&gt; removedir[ectory]|rmdir
     3169            &lt;guest directory&gt;... --username &lt;name&gt;
     3170            [--passwordfile &lt;file&gt; | --password &lt;password&gt;]
     3171            [--recursive|-R|-r] [--verbose]</screen>
     3172
     3173          <para>where the parameters mean: <glosslist>
     3174              <glossentry>
     3175                <glossterm><computeroutput>uuid|vmname</computeroutput></glossterm>
     3176
     3177                <glossdef>
     3178                  <para>The VM UUID or VM name. Mandatory.</para>
     3179                </glossdef>
     3180              </glossentry>
     3181
     3182              <glossentry>
     3183                <glossterm><computeroutput>directory to remove on guest</computeroutput></glossterm>
     3184
     3185                <glossdef>
     3186                  <para>Absolute path of directory/directories to remove on
     3187                  guest, e.g. <computeroutput>D:\Foo\Bar</computeroutput>. The
     3188                  specified user must have appropriate rights to delete the
     3189                  specified guest directories.</para>
     3190                </glossdef>
     3191              </glossentry>
     3192
     3193              <glossentry>
     3194                <glossterm><computeroutput>--username &lt;name&gt;</computeroutput></glossterm>
     3195
     3196                <glossdef>
     3197                  <para>Name of the user the copy process should run under.
     3198                  This user must exist on the guest OS.</para>
     3199                </glossdef>
     3200              </glossentry>
     3201
     3202              <glossentry>
     3203                <glossterm><computeroutput>--passwordfile &lt;file&gt;</computeroutput></glossterm>
     3204
     3205                <glossdef>
     3206                  <para>Password of the user account specified to be read from
     3207                  the given file. If not given, an empty password is
     3208                  assumed.</para>
     3209                </glossdef>
     3210              </glossentry>
     3211
     3212              <glossentry>
     3213                <glossterm><computeroutput>--password &lt;password&gt;</computeroutput></glossterm>
     3214
     3215                <glossdef>
     3216                  <para>Password of the user account specified with
     3217                  <computeroutput>--username</computeroutput>. If not given,
     3218                  an empty password is assumed.</para>
     3219                </glossdef>
     3220              </glossentry>
     3221
     3222              <glossentry>
     3223                <glossterm><computeroutput>--recursive</computeroutput></glossterm>
     3224
     3225                <glossdef>
     3226                  <para>Remove directories and their contents recursively.</para>
     3227                </glossdef>
     3228              </glossentry>
     3229
     3230              <glossentry>
     3231                <glossterm><computeroutput>--verbose</computeroutput></glossterm>
     3232
     3233                <glossdef>
     3234                  <para>Tells VBoxManage to be more verbose.</para>
     3235                </glossdef>
     3236              </glossentry>
     3237            </glosslist></para>
     3238        </listitem>
     3239
     3240        <listitem>
     3241          <para><emphasis role="bold"><computeroutput>removefile</computeroutput></emphasis>,
     3242          which allows deletion of guest files (only with installed Guest
     3243          Additions 4.3.2 and later).</para>
     3244
     3245          <screen>VBoxManage guestcontrol &lt;uuid|vmname&gt; removefile|rm
     3246            &lt;guest file&gt;... --username &lt;name&gt;
     3247            [--passwordfile &lt;file&gt; | --password &lt;password&gt;]
     3248            [--verbose]</screen>
     3249
     3250          <para>where the parameters mean: <glosslist>
     3251              <glossentry>
     3252                <glossterm><computeroutput>uuid|vmname</computeroutput></glossterm>
     3253
     3254                <glossdef>
     3255                  <para>The VM UUID or VM name. Mandatory.</para>
     3256                </glossdef>
     3257              </glossentry>
     3258
     3259              <glossentry>
     3260                <glossterm><computeroutput>file to remove on guest</computeroutput></glossterm>
     3261
     3262                <glossdef>
     3263                  <para>Absolute path of a file/files to remove on
     3264                  guest, e.g. <computeroutput>D:\Foo\Bar\text.txt</computeroutput>. The
     3265                  specified user must have appropriate rights to delete the
     3266                  specified guest files.</para>
     3267                </glossdef>
     3268              </glossentry>
     3269
     3270              <glossentry>
     3271                <glossterm><computeroutput>--username &lt;name&gt;</computeroutput></glossterm>
     3272
     3273                <glossdef>
     3274                  <para>Name of the user the copy process should run under.
     3275                  This user must exist on the guest OS.</para>
     3276                </glossdef>
     3277              </glossentry>
     3278
     3279              <glossentry>
     3280                <glossterm><computeroutput>--passwordfile &lt;file&gt;</computeroutput></glossterm>
     3281
     3282                <glossdef>
     3283                  <para>Password of the user account specified to be read from
     3284                  the given file. If not given, an empty password is
     3285                  assumed.</para>
     3286                </glossdef>
     3287              </glossentry>
     3288
     3289              <glossentry>
     3290                <glossterm><computeroutput>--password &lt;password&gt;</computeroutput></glossterm>
     3291
     3292                <glossdef>
     3293                  <para>Password of the user account specified with
     3294                  <computeroutput>--username</computeroutput>. If not given,
     3295                  an empty password is assumed.</para>
     3296                </glossdef>
     3297              </glossentry>
     3298
     3299              <glossentry>
     3300                <glossterm><computeroutput>--verbose</computeroutput></glossterm>
     3301
     3302                <glossdef>
     3303                  <para>Tells VBoxManage to be more verbose.</para>
     3304                </glossdef>
     3305              </glossentry>
     3306            </glosslist></para>
     3307        </listitem>
     3308
     3309        <listitem>
     3310          <para><emphasis role="bold"><computeroutput>ren[ame]|mv</computeroutput></emphasis>,
     3311          which allows renaming of guest files and/or directories (only with installed Guest
     3312          Additions 4.3.2 and later).</para>
     3313
     3314          <screen>VBoxManage guestcontrol &lt;uuid|vmname&gt; ren[ame]|mv
     3315            &lt;source&gt;... &lt;dest&gt; --username &lt;name&gt;
     3316            [--passwordfile &lt;file&gt; | --password &lt;password&gt;]
     3317            [--verbose]</screen>
     3318
     3319          <para>where the parameters mean: <glosslist>
     3320              <glossentry>
     3321                <glossterm><computeroutput>uuid|vmname</computeroutput></glossterm>
     3322
     3323                <glossdef>
     3324                  <para>The VM UUID or VM name. Mandatory.</para>
     3325                </glossdef>
     3326              </glossentry>
     3327
     3328              <glossentry>
     3329                <glossterm><computeroutput>source</computeroutput></glossterm>
     3330
     3331                <glossdef>
     3332                  <para>Absolute path of one or more source(s) to move to
     3333                  destination. If more than one source is specified, destination
     3334                  must be an existing directory on the guest. The specified user
     3335                  must have appropriate rights to access source and destination
     3336                  files and directories.</para>
     3337                </glossdef>
     3338              </glossentry>
     3339
     3340              <glossentry>
     3341                <glossterm><computeroutput>dest</computeroutput></glossterm>
     3342
     3343                <glossdef>
     3344                  <para>Absolute path of the destination to move the source(s)
     3345                  to. This can be a directory or a file, depending if one or more
     3346                  sources have been specified. The specified user
     3347                  must have appropriate rights to access the destination
     3348                  file and directory.</para>
     3349                </glossdef>
     3350              </glossentry>
     3351
     3352              <glossentry>
     3353                <glossterm><computeroutput>--username &lt;name&gt;</computeroutput></glossterm>
     3354
     3355                <glossdef>
     3356                  <para>Name of the user the copy process should run under.
     3357                  This user must exist on the guest OS.</para>
     3358                </glossdef>
     3359              </glossentry>
     3360
     3361              <glossentry>
     3362                <glossterm><computeroutput>--passwordfile &lt;file&gt;</computeroutput></glossterm>
     3363
     3364                <glossdef>
     3365                  <para>Password of the user account specified to be read from
     3366                  the given file. If not given, an empty password is
     3367                  assumed.</para>
     3368                </glossdef>
     3369              </glossentry>
     3370
     3371              <glossentry>
     3372                <glossterm><computeroutput>--password &lt;password&gt;</computeroutput></glossterm>
     3373
     3374                <glossdef>
     3375                  <para>Password of the user account specified with
     3376                  <computeroutput>--username</computeroutput>. If not given,
     3377                  an empty password is assumed.</para>
     3378                </glossdef>
     3379              </glossentry>
     3380
     3381              <glossentry>
     3382                <glossterm><computeroutput>--verbose</computeroutput></glossterm>
     3383
     3384                <glossdef>
     3385                  <para>Tells VBoxManage to be more verbose.</para>
     3386                </glossdef>
     3387              </glossentry>
     3388            </glosslist></para>
     3389        </listitem>
     3390
     3391        <listitem>
    31643392          <para><emphasis role="bold"><computeroutput>createtemporary</computeroutput></emphasis>,
    31653393          which allows
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r47817 r49349  
    121121
    122122/**
     123 * Guest directory removement flags.
     124 * Essentially using what IPRT's RTDIRRMREC_F_
     125 * defines have to offer.
     126 */
     127#define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
     128/** Delete the content of the directory and the directory itself. */
     129#define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
     130/** Only delete the content of the directory, omit the directory it self. */
     131#define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
     132/** Mask of valid flags. */
     133#define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
     134
     135/**
    123136 * Guest process creation flags.
    124137 * Note: Has to match Main's ProcessCreateFlag_* flags!
     
    140153#define OUTPUT_HANDLE_ID_STDOUT             1
    141154#define OUTPUT_HANDLE_ID_STDERR             2
     155
     156/**
     157 * Guest path rename flags.
     158 * Essentially using what IPRT's RTPATHRENAME_FLAGS_
     159 * defines have to offer.
     160 */
     161/** Do not replace anything. */
     162#define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
     163/** This will replace attempt any target which isn't a directory. */
     164#define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
     165/** Don't allow symbolic links as part of the path. */
     166#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
     167/** Mask of valid flags. */
     168#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
    142169
    143170/**
     
    203230                                : mParms(cParms), mpaParms(paParms) { }
    204231
     232    /** Number of HGCM parameters. */
    205233    uint32_t mParms;
     234    /** Actual HGCM parameters. */
    206235    PVBOXHGCMSVCPARM mpaParms;
    207236
     
    284313     * Gets the current file position of an opened guest file.
    285314     */
    286     HOST_FILE_TELL = 271
     315    HOST_FILE_TELL = 271,
     316    /**
     317     * Removes a directory on the guest.
     318     */
     319    HOST_DIR_REMOVE = 320,
     320    /**
     321     * Renames a path on the guest.
     322     */
     323    HOST_PATH_RENAME = 330
    287324};
    288325
     
    290327 * The service functions which are called by guest. The numbers may not change,
    291328 * so we hardcode them.
    292  *
    293  * Note: Callbacks start at 100. See CALLBACKTYPE enum.
    294329 */
    295330enum eGuestFn
     
    328363    GUEST_MSG_SKIP = 10,
    329364    /**
     365     * General reply to a host message. Only contains basic data
     366     * along with a simple payload.
     367     */
     368    GUEST_MSG_REPLY = 11,
     369    /**
     370     * General message for updating a pending progress for
     371     * a long task.
     372     */
     373    GUEST_MSG_PROGRESS_UPDATE = 12,
     374    /**
    330375     * Guest reports back a guest session status.
    331376     */
    332377    GUEST_SESSION_NOTIFY = 20,
     378    /**
     379     * Guest wants to close a specific guest session.
     380     */
     381    GUEST_SESSION_CLOSE = 21,
    333382    /**
    334383     * Guests sends output from an executed process.
     
    350399     */
    351400    GUEST_EXEC_IO_NOTIFY = 210,
     401    /**
     402     * Guest notifies the host about some directory event.
     403     */
     404    GUEST_DIR_NOTIFY = 230,
    352405    /**
    353406     * Guest notifies the host about some file event.
     
    382435
    383436/**
     437 * Guest directory notification types.
     438 * @sa HGCMMsgDirNotify.
     439 */
     440enum GUEST_DIR_NOTIFYTYPE
     441{
     442    GUEST_DIR_NOTIFYTYPE_UNKNOWN = 0,
     443    /** Something went wrong (see rc). */
     444    GUEST_DIR_NOTIFYTYPE_ERROR = 1,
     445    /** Guest directory opened. */
     446    GUEST_DIR_NOTIFYTYPE_OPEN = 10,
     447    /** Guest directory closed. */
     448    GUEST_DIR_NOTIFYTYPE_CLOSE = 20,
     449    /** Information about an open guest directory. */
     450    GUEST_DIR_NOTIFYTYPE_INFO = 40,
     451    /** Guest directory created. */
     452    GUEST_DIR_NOTIFYTYPE_CREATE = 70,
     453    /** Guest directory deleted. */
     454    GUEST_DIR_NOTIFYTYPE_REMOVE = 80
     455};
     456
     457/**
    384458 * Guest file notification types.
    385459 * @sa HGCMMsgFileNotify.
     
    421495{
    422496    VBoxGuestHGCMCallInfo hdr;
    423 
    424497    /**
    425498     * The returned command the host wants to
     
    429502    /** Number of parameters the message needs. */
    430503    HGCMFunctionParameter num_parms; /* OUT uint32_t */
    431 
    432504} HGCMMsgCmdWaitFor;
    433505
     
    441513{
    442514    VBoxGuestHGCMCallInfo hdr;
    443 
    444515    /** Value to filter for after filter mask
    445516     *  was applied. */
     
    451522    /** Filter flags; currently unused. */
    452523    HGCMFunctionParameter flags;         /* IN uint32_t */
    453 
    454524} HGCMMsgCmdFilterSet;
    455525
     
    461531{
    462532    VBoxGuestHGCMCallInfo hdr;
    463 
    464533    /** Unset flags; currently unused. */
    465534    HGCMFunctionParameter flags;    /* IN uint32_t */
     
    474543{
    475544    VBoxGuestHGCMCallInfo hdr;
    476 
    477545    /** Skip flags; currently unused. */
    478546    HGCMFunctionParameter flags;    /* IN uint32_t */
     
    487555    VBoxGuestHGCMCallInfo hdr;
    488556} HGCMMsgCancelPendingWaits;
     557
     558typedef struct HGCMMsgCmdReply
     559{
     560    VBoxGuestHGCMCallInfo hdr;
     561    /** Context ID. */
     562    HGCMFunctionParameter context;
     563    /** Message type. */
     564    HGCMFunctionParameter type;
     565    /** IPRT result of overall operation. */
     566    HGCMFunctionParameter rc;
     567    /** Optional payload to this reply. */
     568    HGCMFunctionParameter payload;
     569} HGCMMsgCmdReply;
    489570
    490571/**
     
    534615    HGCMFunctionParameter result;
    535616} HGCMMsgSessionNotify;
     617
     618typedef struct HGCMMsgPathRename
     619{
     620    VBoxGuestHGCMCallInfo hdr;
     621    /** UInt32: Context ID. */
     622    HGCMFunctionParameter context;
     623    /** Source to rename. */
     624    HGCMFunctionParameter source;
     625    /** Destination to rename source to. */
     626    HGCMFunctionParameter dest;
     627    /** UInt32: Rename flags. */
     628    HGCMFunctionParameter flags;
     629} HGCMMsgPathRename;
    536630
    537631/**
     
    575669        struct
    576670        {
    577             /** Timeout (in msec) which either specifies the
     671            /** Timeout (in ms) which either specifies the
    578672             *  overall lifetime of the process or how long it
    579673             *  can take to bring the process up and running -
     
    588682        } v2;
    589683    } u;
    590 
    591684} HGCMMsgProcExec;
    592685
     
    607700    /** Actual size of data (in bytes). */
    608701    HGCMFunctionParameter size;
    609 
    610702} HGCMMsgProcInput;
    611703
     
    627719    /** Data buffer. */
    628720    HGCMFunctionParameter data;
    629 
    630721} HGCMMsgProcOutput;
    631722
     
    646737    /** Optional data buffer (not used atm). */
    647738    HGCMFunctionParameter data;
    648 
    649739} HGCMMsgProcStatus;
    650740
     
    665755    /** Data written. */
    666756    HGCMFunctionParameter written;
    667 
    668757} HGCMMsgProcStatusInput;
    669758
     
    682771    /** The process ID (PID). */
    683772    HGCMFunctionParameter pid;
    684 
    685773} HGCMMsgProcTerminate;
    686774
     
    699787    /** Timeout (in ms). */
    700788    HGCMFunctionParameter timeout;
    701 
    702789} HGCMMsgProcWaitFor;
     790
     791typedef struct HGCMMsgDirRemove
     792{
     793    VBoxGuestHGCMCallInfo hdr;
     794    /** UInt32: Context ID. */
     795    HGCMFunctionParameter context;
     796    /** Directory to remove. */
     797    HGCMFunctionParameter path;
     798    /** UInt32: Removement flags. */
     799    HGCMFunctionParameter flags;
     800} HGCMMsgDirRemove;
    703801
    704802/**
     
    722820    /** UInt64: Initial offset. */
    723821    HGCMFunctionParameter offset;
    724 
    725822} HGCMMsgFileOpen;
    726823
     
    735832    /** File handle to close. */
    736833    HGCMFunctionParameter handle;
    737 
    738834} HGCMMsgFileClose;
    739835
     
    750846    /** Size (in bytes) to read. */
    751847    HGCMFunctionParameter size;
    752 
    753848} HGCMMsgFileRead;
    754849
     
    767862    /** Actual size of data (in bytes). */
    768863    HGCMFunctionParameter size;
    769 
    770864} HGCMMsgFileReadAt;
    771865
     
    784878    /** Data buffer to write to the file. */
    785879    HGCMFunctionParameter data;
    786 
    787880} HGCMMsgFileWrite;
    788881
     
    803896    /** Data buffer to write to the file. */
    804897    HGCMFunctionParameter data;
    805 
    806898} HGCMMsgFileWriteAt;
    807899
     
    820912    /** The seeking offset. */
    821913    HGCMFunctionParameter offset;
    822 
    823914} HGCMMsgFileSeek;
    824915
     
    833924    /** File handle to get the current position for. */
    834925    HGCMFunctionParameter handle;
    835 
    836926} HGCMMsgFileTell;
    837927
     
    877967        } tell;
    878968    } u;
    879 
    880969} HGCMReplyFileNotify;
     970
     971typedef struct HGCMReplyDirNotify
     972{
     973    VBoxGuestHGCMCallInfo hdr;
     974    /** Context ID. */
     975    HGCMFunctionParameter context;
     976    /** Notification type. */
     977    HGCMFunctionParameter type;
     978    /** IPRT result of overall operation. */
     979    HGCMFunctionParameter rc;
     980    union
     981    {
     982        struct
     983        {
     984            /** Directory information. */
     985            HGCMFunctionParameter objInfo;
     986        } info;
     987        struct
     988        {
     989            /** Guest directory handle. */
     990            HGCMFunctionParameter handle;
     991        } open;
     992        struct
     993        {
     994            /** Current read directory entry. */
     995            HGCMFunctionParameter entry;
     996            /** Extended entry object information. Optional. */
     997            HGCMFunctionParameter objInfo;
     998        } read;
     999    } u;
     1000} HGCMReplyDirNotify;
    8811001
    8821002#pragma pack ()
     
    9081028    CALLBACKDATA_HEADER hdr;
    9091029} CALLBACKDATA_CLIENT_DISCONNECTED, *PCALLBACKDATA_CLIENT_DISCONNECTED;
     1030
     1031typedef struct CALLBACKDATA_MSG_REPLY
     1032{
     1033    /** Callback data header. */
     1034    CALLBACKDATA_HEADER hdr;
     1035    /** Notification type. */
     1036    uint32_t uType;
     1037    /** Notification result. Note: int vs. uint32! */
     1038    uint32_t rc;
     1039    /** Pointer to optional payload. */
     1040    void *pvPayload;
     1041    /** Payload size (in bytes). */
     1042    uint32_t cbPayload;
     1043} CALLBACKDATA_MSG_REPLY, *PCALLBACKDATA_MSG_REPLY;
    9101044
    9111045typedef struct CALLBACKDATA_SESSION_NOTIFY
     
    9661100
    9671101/**
    968  * General guest file notification callback.
    969  */
    970 typedef struct CALLBACKDATA_FILE_NOTIFY
     1102 * General guest directory notification callback.
     1103 */
     1104typedef struct CALLBACKDATA_DIR_NOTIFY
    9711105{
    9721106    /** Callback data header. */
     
    9801114        struct
    9811115        {
     1116            /** Size (in bytes) of directory information. */
     1117            uint32_t cbObjInfo;
     1118            /** Pointer to directory information. */
     1119            void *pvObjInfo;
     1120        } info;
     1121        struct
     1122        {
     1123            /** Guest directory handle. */
     1124            uint32_t uHandle;
     1125        } open;
     1126        /** Note: Close does not have any additional data (yet). */
     1127        struct
     1128        {
     1129            /** Size (in bytes) of directory entry information. */
     1130            uint32_t cbEntry;
     1131            /** Pointer to directory entry information. */
     1132            void *pvEntry;
     1133            /** Size (in bytes) of directory entry object information. */
     1134            uint32_t cbObjInfo;
     1135            /** Pointer to directory entry object information. */
     1136            void *pvObjInfo;
     1137        } read;
     1138    } u;
     1139} CALLBACKDATA_DIR_NOTIFY, *PCALLBACKDATA_DIR_NOTIFY;
     1140
     1141/**
     1142 * General guest file notification callback.
     1143 */
     1144typedef struct CALLBACKDATA_FILE_NOTIFY
     1145{
     1146    /** Callback data header. */
     1147    CALLBACKDATA_HEADER hdr;
     1148    /** Notification type. */
     1149    uint32_t uType;
     1150    /** IPRT result of overall operation. */
     1151    uint32_t rc;
     1152    union
     1153    {
     1154        struct
     1155        {
    9821156            /** Guest file handle. */
    9831157            uint32_t uHandle;
  • trunk/include/VBox/VBoxGuestLib.h

    r47817 r49349  
    612612VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove);
    613613VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterUnset(uint32_t uClientId);
     614VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc);
     615VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType, void *pvPayload, uint32_t cbPayload);
     616VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t uClientId);
    614617VBGLR3DECL(int) VbglR3GuestCtrlMsgWaitFor(uint32_t uClientId, uint32_t *puMsg, uint32_t *puNumParms);
    615 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t uClientId);
    616618VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t u32ClientId);
    617619/* Guest session handling. */
     620VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uFlags);
    618621VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult);
    619622VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puProtocol, char *pszUser, uint32_t  cbUser, char *pszPassword, uint32_t  cbPassword, char *pszDomain, uint32_t cbDomain, uint32_t *puFlags, uint32_t *puSessionID);
    620623VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puFlags, uint32_t *puSessionID);
     624/* Guest path handling. */
     625VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszSource, uint32_t cbSource, char *pszDest, uint32_t cbDest, uint32_t *puFlags);
    621626/* Guest process execution. */
    622627VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszCmd, uint32_t cbCmd, uint32_t *puFlags, char *pszArgs, uint32_t cbArgs, uint32_t *puNumArgs, char *pszEnv, uint32_t *pcbEnv, uint32_t *puNumEnvVars, char *pszUser, uint32_t cbUser, char *pszPassword, uint32_t cbPassword, uint32_t *puTimeoutMS, uint32_t *puPriority, uint64_t *puAffinity, uint32_t cbAffinity, uint32_t *pcAffinity);
     
    625630VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puHandle, uint32_t *puFlags);
    626631VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS);
     632/* Guest native directory handling. */
     633VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *puFlags);
    627634/* Guest native file handling. */
    628635VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszFileName, uint32_t cbFileName, char *pszOpenMode, uint32_t cbOpenMode, char *pszDisposition, uint32_t cbDisposition, char *pszSharing, uint32_t cbSharing, uint32_t *puCreationMode, uint64_t *puOffset);
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp

    r47817 r49349  
    188188
    189189
     190VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx,
     191                                        int rc)
     192{
     193    return VbglR3GuestCtrlMsgReplyEx(pCtx, rc, 0 /* uType */,
     194                                     NULL /* pvPayload */, 0 /* cbPayload */);
     195}
     196
     197
     198VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx,
     199                                          int rc, uint32_t uType,
     200                                          void *pvPayload, uint32_t cbPayload)
     201{
     202    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     203    /* Everything else is optional. */
     204
     205    HGCMMsgCmdReply Msg;
     206
     207    Msg.hdr.result      = VERR_WRONG_ORDER;
     208    Msg.hdr.u32ClientID = pCtx->uClientID;
     209    Msg.hdr.u32Function = GUEST_MSG_REPLY;
     210    Msg.hdr.cParms      = 4;
     211
     212    VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
     213    VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc); /* int vs. uint32_t */
     214    VbglHGCMParmUInt32Set(&Msg.type, uType);
     215    VbglHGCMParmPtrSet(&Msg.payload, pvPayload, cbPayload);
     216
     217    int rc2 = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     218    if (RT_SUCCESS(rc))
     219    {
     220        int rc3 = Msg.hdr.result;
     221        if (RT_FAILURE(rc3))
     222            rc2 = rc3;
     223    }
     224    return rc2;
     225}
     226
     227
    190228/**
    191229 * Tells the host service to skip the current message returned by
     
    237275            rc = rc2;
    238276    }
     277    return rc;
     278}
     279
     280
     281/**
     282 * Asks a specific guest session to close.
     283 *
     284 * @return  IPRT status code.
     285 * @param   pCtx                    Host context.
     286 ** @todo Docs!
     287 */
     288VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uFlags)
     289{
     290    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     291    AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
     292
     293    HGCMMsgSessionClose Msg;
     294
     295    Msg.hdr.result      = VERR_WRONG_ORDER;
     296    Msg.hdr.u32ClientID = pCtx->uClientID;
     297    Msg.hdr.u32Function = GUEST_SESSION_CLOSE;
     298    Msg.hdr.cParms      = pCtx->uNumParms;
     299
     300    VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
     301    VbglHGCMParmUInt32Set(&Msg.flags, uFlags);
     302
     303    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     304    if (RT_SUCCESS(rc))
     305    {
     306        int rc2 = Msg.hdr.result;
     307        if (RT_FAILURE(rc2))
     308            rc = rc2;
     309    }
     310
    239311    return rc;
    240312}
     
    374446
    375447
     448VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX     pCtx,
     449                                             char     *pszSource,       uint32_t cbSource,
     450                                             char     *pszDest,         uint32_t cbDest,
     451                                             uint32_t *puFlags)
     452{
     453    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     454    AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
     455
     456    AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
     457    AssertReturn(cbSource, VERR_INVALID_PARAMETER);
     458    AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
     459    AssertReturn(cbDest, VERR_INVALID_PARAMETER);
     460    AssertPtrReturn(puFlags, VERR_INVALID_POINTER);
     461
     462    HGCMMsgPathRename Msg;
     463
     464    Msg.hdr.result      = VERR_WRONG_ORDER;
     465    Msg.hdr.u32ClientID = pCtx->uClientID;
     466    Msg.hdr.u32Function = GUEST_MSG_WAIT;
     467    Msg.hdr.cParms      = pCtx->uNumParms;
     468
     469    VbglHGCMParmUInt32Set(&Msg.context, 0);
     470    VbglHGCMParmPtrSet(&Msg.source, pszSource, cbSource);
     471    VbglHGCMParmPtrSet(&Msg.dest, pszDest, cbDest);
     472    VbglHGCMParmUInt32Set(&Msg.flags, 0);
     473
     474    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     475    if (RT_SUCCESS(rc))
     476    {
     477        int rc2 = Msg.hdr.result;
     478        if (RT_FAILURE(rc2))
     479        {
     480            rc = rc2;
     481        }
     482        else
     483        {
     484            Msg.context.GetUInt32(&pCtx->uContextID);
     485            Msg.flags.GetUInt32(puFlags);
     486        }
     487    }
     488    return rc;
     489}
     490
     491
    376492/**
    377493 * Allocates and gets host data, based on the message id.
     
    383499 ** @todo Move the parameters in an own struct!
    384500 */
    385 VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX   pCtx,
     501VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX    pCtx,
    386502                                            char     *pszCmd,         uint32_t  cbCmd,
    387503                                            uint32_t *puFlags,
     
    578694
    579695
     696VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX     pCtx,
     697                                            char     *pszPath,         uint32_t cbPath,
     698                                            uint32_t *puFlags)
     699{
     700    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     701    AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
     702
     703    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     704    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
     705    AssertPtrReturn(puFlags, VERR_INVALID_POINTER);
     706
     707    HGCMMsgDirRemove Msg;
     708
     709    Msg.hdr.result      = VERR_WRONG_ORDER;
     710    Msg.hdr.u32ClientID = pCtx->uClientID;
     711    Msg.hdr.u32Function = GUEST_MSG_WAIT;
     712    Msg.hdr.cParms      = pCtx->uNumParms;
     713
     714    VbglHGCMParmUInt32Set(&Msg.context, 0);
     715    VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
     716    VbglHGCMParmUInt32Set(&Msg.flags, 0);
     717
     718    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
     719    if (RT_SUCCESS(rc))
     720    {
     721        int rc2 = Msg.hdr.result;
     722        if (RT_FAILURE(rc2))
     723        {
     724            rc = rc2;
     725        }
     726        else
     727        {
     728            Msg.context.GetUInt32(&pCtx->uContextID);
     729            Msg.flags.GetUInt32(puFlags);
     730        }
     731    }
     732    return rc;
     733}
     734
     735
    580736VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX      pCtx,
    581737                                           char     *pszFileName,      uint32_t cbFileName,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r46506 r49349  
    216216/**
    217217 * Creates the default release logger outputting to the specified file.
     218 * Pass NULL for disabled logging.
    218219 *
    219220 * @return  IPRT status code.
     
    222223int VBoxServiceLogCreate(const char *pszLogFile)
    223224{
     225    if (!pszLogFile) /* No logging wanted? Take a shortcut. */
     226        return VINF_SUCCESS;
     227
    224228    /* Create release logger (stdout + file). */
    225229    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r47817 r49349  
    268268                     * The global session object then acts as a host for all
    269269                     * started guest processes which bring all their
    270                      * credentials with them with the actual execution call.
     270                     * credentials with them with the actual guest process
     271                     * execution call.
    271272                     */
    272273                    if (ctxHost.uProtocol == 1)
     
    407408
    408409    /*
    409      * Ask the host service to cancel all pending requests so that we can
    410      * shutdown properly here.
     410     * Ask the host service to cancel all pending requests for the main
     411     * control thread so that we can shutdown properly here.
    411412     */
    412413    if (g_uControlSvcClientID)
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp

    r47695 r49349  
    525525                                     pProcess->uPID, PROC_STS_STARTED, 0 /* u32Flags */,
    526526                                     NULL /* pvData */, 0 /* cbData */);
     527    if (RT_FAILURE(rc))
     528        VBoxServiceError("[PID %RU32]: Error reporting starting status to host, rc=%Rrc\n",
     529                         pProcess->uPID, rc);
    527530
    528531    /*
     
    576579                        if (RT_FAILURE(rc2))
    577580                            VBoxServiceError("Draining IPC notification pipe failed with rc=%Rrc\n", rc2);
    578 #ifdef DEBUG
     581
     582                        /* Process all pending requests. */
    579583                        VBoxServiceVerbose(4, "[PID %RU32]: Processing pending requests ...\n",
    580584                                           pProcess->uPID);
    581 #endif
    582                         /* Process all pending requests. */
    583585                        Assert(pProcess->hReqQueue != NIL_RTREQQUEUE);
    584586                        rc2 = RTReqQueueProcess(pProcess->hReqQueue,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r49039 r49349  
    2323#include <iprt/asm.h>
    2424#include <iprt/assert.h>
     25#include <iprt/dir.h>
    2526#include <iprt/env.h>
    2627#include <iprt/file.h>
     
    5758static DECLCALLBACK(int)    gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser);
    5859/* Host -> Guest handlers. */
     60static int                  gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
    5961static int                  gstcntlSessionHandleFileOpen(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
    6062static int                  gstcntlSessionHandleFileClose(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
     
    6365static int                  gstcntlSessionHandleFileSeek(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
    6466static int                  gstcntlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
     67static int                  gstcntlSessionHandlePathRename(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
    6568static int                  gstcntlSessionHandleProcExec(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
    6669static int                  gstcntlSessionHandleProcInput(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf);
     
    118121
    119122    return NULL;
     123}
     124
     125
     126static int gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession,
     127                                         PVBGLR3GUESTCTRLCMDCTX pHostCtx)
     128{
     129    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     130    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
     131
     132    char szDir[RTPATH_MAX];
     133    uint32_t uFlags = 0;
     134
     135    int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx,
     136                                         /* Directory to remove. */
     137                                         szDir, sizeof(szDir),
     138                                         /* Flags of type DIRREMOVE_FLAG_. */
     139                                         &uFlags);
     140    if (RT_SUCCESS(rc))
     141    {
     142        uint32_t uFlagsRemRec = 0;
     143        bool fRecursive = false;
     144
     145        if (!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK))
     146        {
     147            if (uFlags & DIRREMOVE_FLAG_RECURSIVE)
     148            {
     149                /* Note: DIRREMOVE_FLAG_RECURSIVE must be set explicitly.
     150                 *       Play safe here. */
     151                fRecursive = true;
     152            }
     153
     154            if (uFlags & DIRREMOVE_FLAG_CONTENT_AND_DIR)
     155            {
     156                /* Setting direct value is intentional. */
     157                uFlagsRemRec = RTDIRRMREC_F_CONTENT_AND_DIR;
     158            }
     159
     160            if (uFlags & DIRREMOVE_FLAG_CONTENT_ONLY)
     161            {
     162                /* Setting direct value is intentional. */
     163                uFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
     164            }
     165        }
     166        else
     167            rc = VERR_NOT_SUPPORTED;
     168
     169        VBoxServiceVerbose(4, "[Dir %s]: Removing with uFlags=0x%x, fRecursive=%RTbool\n",
     170                           szDir, uFlags, fRecursive);
     171
     172        if (RT_SUCCESS(rc))
     173        {
     174            /** @todo Add own recursive function (or a new IPRT function w/ callback?) to
     175             *        provide guest-to-host progress reporting. */
     176            if (fRecursive)
     177                rc = RTDirRemoveRecursive(szDir, uFlagsRemRec);
     178            else
     179                rc = RTDirRemove(szDir);
     180        }
     181
     182        /* Report back in any case. */
     183        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
     184        if (RT_FAILURE(rc2))
     185            VBoxServiceError("[Dir %s]: Failed to report removing status, rc=%Rrc\n",
     186                             szDir, rc2);
     187        if (RT_SUCCESS(rc))
     188            rc = rc2;
     189    }
     190
     191#ifdef DEBUG
     192    VBoxServiceVerbose(4, "Removing directory \"%s\" returned rc=%Rrc\n",
     193                       szDir, rc);
     194#endif
     195    return rc;
    120196}
    121197
     
    583659    VBoxServiceVerbose(4, "Telling file \"%s\" (handle=%RU32) returned rc=%Rrc\n",
    584660                       pFile ? pFile->szName : "<Not found>", uHandle, rc);
     661#endif
     662    return rc;
     663}
     664
     665
     666static int gstcntlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession,
     667                                          PVBGLR3GUESTCTRLCMDCTX pHostCtx)
     668{
     669    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     670    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
     671
     672    char szSource[RTPATH_MAX];
     673    char szDest[RTPATH_MAX];
     674    uint32_t uFlags = 0;
     675
     676    int rc = VbglR3GuestCtrlPathGetRename(pHostCtx,
     677                                          szSource, sizeof(szSource),
     678                                          szDest, sizeof(szDest),
     679                                          /* Flags of type PATHRENAME_FLAG_. */
     680                                          &uFlags);
     681    if (RT_SUCCESS(rc))
     682    {
     683        if (uFlags & ~PATHRENAME_FLAG_VALID_MASK)
     684            rc = VERR_NOT_SUPPORTED;
     685
     686        VBoxServiceVerbose(4, "Renaming \"%s\" to \"%s\", uFlags=0x%x, rc=%Rrc\n",
     687                           szSource, szDest, uFlags, rc);
     688
     689        if (RT_SUCCESS(rc))
     690        {
     691            if (uFlags & PATHRENAME_FLAG_NO_REPLACE)
     692                uFlags |= RTPATHRENAME_FLAGS_NO_REPLACE;
     693
     694            if (uFlags & PATHRENAME_FLAG_REPLACE)
     695                uFlags |= RTPATHRENAME_FLAGS_REPLACE;
     696
     697            if (uFlags & PATHRENAME_FLAG_NO_SYMLINKS)
     698                uFlags |= RTPATHRENAME_FLAGS_NO_SYMLINKS;
     699
     700            rc = RTPathRename(szSource, szDest, uFlags);
     701        }
     702
     703        /* Report back in any case. */
     704        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
     705        if (RT_FAILURE(rc2))
     706            VBoxServiceError("Failed to report renaming status, rc=%Rrc\n", rc2);
     707        if (RT_SUCCESS(rc))
     708            rc = rc2;
     709    }
     710
     711#ifdef DEBUG
     712    VBoxServiceVerbose(4, "Renaming \"%s\" to \"%s\" returned rc=%Rrc\n",
     713                       szSource, szDest, rc);
    585714#endif
    586715    return rc;
     
    9051034    switch (uMsg)
    9061035    {
    907         case HOST_CANCEL_PENDING_WAITS:
    908             VBoxServiceVerbose(1, "We were asked to quit ...\n");
    909             /* Fall thru is intentional. */
    9101036        case HOST_SESSION_CLOSE:
    911             /* Shutdown this fork. */
     1037            /* Shutdown (this fork). */
    9121038            rc = GstCntlSessionClose(pSession);
    9131039            *pfShutdown = true; /* Shutdown in any case. */
     1040            break;
     1041
     1042        case HOST_DIR_REMOVE:
     1043            rc = fImpersonated
     1044               ? gstcntlSessionHandleDirRemove(pSession, pHostCtx)
     1045               : VERR_NOT_SUPPORTED;
    9141046            break;
    9151047
     
    9841116            rc = fImpersonated
    9851117               ? gstcntlSessionHandleFileTell(pSession, pHostCtx)
     1118               : VERR_NOT_SUPPORTED;
     1119            break;
     1120
     1121        case HOST_PATH_RENAME:
     1122            rc = fImpersonated
     1123               ? gstcntlSessionHandlePathRename(pSession, pHostCtx)
    9861124               : VERR_NOT_SUPPORTED;
    9871125            break;
     
    10571195    if (RT_SUCCESS(rc))
    10581196    {
    1059         uint32_t uTimeoutsMS = 5 * 60 * 1000; /** @todo Make this configurable. Later. */
     1197        uint32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */
    10601198        uint64_t u64TimeoutStart = 0;
    10611199
     
    10801218                if (!u64TimeoutStart)
    10811219                {
    1082                     VBoxServiceVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit ...\n",
    1083                                        uSessionID);
     1220                    VBoxServiceVerbose(3, "Notifying guest session process (PID=%RU32, session ID=%RU32) ...\n",
     1221                                       pThread->hProcess, uSessionID);
     1222
     1223                    VBGLR3GUESTCTRLCMDCTX hostCtx = { uClientID,
     1224                                                      VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSessionID),
     1225                                                      pThread->StartupInfo.uProtocol, 2 /* uNumParms */ };
     1226                    rc = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* uFlags */);
     1227                    if (RT_FAILURE(rc))
     1228                    {
     1229                        VBoxServiceError("Unable to notify guest session process (PID=%RU32, session ID=%RU32), rc=%Rrc\n",
     1230                                         pThread->hProcess, uSessionID, rc);
     1231
     1232                        if (rc == VERR_NOT_SUPPORTED)
     1233                        {
     1234                            /* Terminate guest session process in case it's not supported by a too old host. */
     1235                            rc = RTProcTerminate(pThread->hProcess);
     1236                            VBoxServiceVerbose(3, "Terminating guest session process (PID=%RU32) ended with rc=%Rrc\n",
     1237                                               pThread->hProcess, rc);
     1238                        }
     1239                        break;
     1240                    }
     1241
     1242                    VBoxServiceVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32ms timeout) ...\n",
     1243                                       uSessionID, uTimeoutsMS);
    10841244                    u64TimeoutStart = RTTimeMilliTS();
     1245
    10851246                    continue; /* Don't waste time on waiting. */
    10861247                }
     
    12221383                                           GUEST_SESSION_NOTIFYTYPE_STARTED, VINF_SUCCESS);
    12231384    if (RT_FAILURE(rc2))
     1385    {
    12241386        VBoxServiceError("Reporting session ID=%RU32 started status failed with rc=%Rrc\n",
    12251387                         pSession->StartupInfo.uSessionID, rc2);
     1388
     1389        /*
     1390         * If session status cannot be posted to the host for
     1391         * some reason, bail out.
     1392         */
     1393        if (RT_SUCCESS(rc))
     1394            rc = rc2;
     1395    }
    12261396
    12271397    /* Allocate a scratch buffer for commands which also send
     
    12841454        RTMemFree(pvScratchBuf);
    12851455
    1286     VBoxServiceVerbose(3, "Disconnecting client ID=%RU32 ...\n", uClientID);
    1287     VbglR3GuestCtrlDisconnect(uClientID);
     1456    if (uClientID)
     1457    {
     1458        VBoxServiceVerbose(3, "Disconnecting client ID=%RU32 ...\n", uClientID);
     1459        VbglR3GuestCtrlDisconnect(uClientID);
     1460    }
    12881461
    12891462    VBoxServiceVerbose(3, "Session worker returned with rc=%Rrc\n", rc);
     
    17551928                        }
    17561929#else
     1930                        /* Include the session thread ID in the log file name. */
    17571931                        if (RTStrAPrintf(&pszLogNewSuffix, "-%RU32-%RU32-%s",
    17581932                                         pSessionStartupInfo->uSessionID,
     
    17931967                    rc = rc2;
    17941968#ifdef DEBUG
    1795                 VBoxServiceVerbose(4, "rc=%Rrc, session flags=%x\n",
     1969                VBoxServiceVerbose(4, "Argv building rc=%Rrc, session flags=%x\n",
    17961970                                   rc, g_Session.uFlags);
    17971971                char szParmDumpStdOut[32];
     
    20492223    int rc = VINF_SUCCESS;
    20502224
     2225    /*int rc = VbglR3GuestCtrlClose
     2226        if (RT_FAILURE(rc))
     2227            VBoxServiceError("Cancelling pending waits failed; rc=%Rrc\n", rc);*/
     2228
    20512229    PVBOXSERVICECTRLSESSIONTHREAD pSessionThread
    20522230         = RTListGetFirst(pList, VBOXSERVICECTRLSESSIONTHREAD, Node);
     
    21402318                break;
    21412319
     2320#ifdef DEBUG
    21422321            case VBOXSERVICESESSIONOPT_THREAD_ID:
    21432322                /* Not handled. */
    21442323                break;
    2145 
     2324#endif
    21462325            /** @todo Implement help? */
    21472326
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r49222 r49349  
    141141
    142142    PGCTLCMDCTX pCmdCtx;
    143     ComPtr<IGuestSession> pGuestSession;
    144143    bool fDryRun;
    145144    bool fHostToGuest;
     
    282281enum GETOPTDEF_RMDIR
    283282{
    284     GETOPTDEF_RMDIR_RECURSIVE = 2000
    285283};
    286284
     
    349347                 "                            [--domain <domain>] [--verbose]\n"
    350348                 "\n"
     349                 "                            ren[ame]|mv\n"
     350                 "                            <source>... <dest> --username <name>\n"
     351                 "                            [--passwordfile <file> | --password <password>]\n"
     352                 "                            [--domain <domain>] [--verbose]\n"
     353                 "\n"
    351354                 "                            createtemp[orary]|mktemp\n"
    352355                 "                            <template> --username <name>\n"
     
    729732    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    730733
     734#ifdef DEBUG_andy
     735    RTPrintf("Original argv:\n");
     736    for (int i=0; i<pArg->argc;i++)
     737        RTPrintf("\targv[%d]=%s\n", i, pArg->argv[i]);
     738#endif
     739
    731740    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    732741
     
    780789            pCtx->iArgc = 0;
    781790
     791            int iArgIdx = 2; /* Skip VM name and guest control command */
    782792            int ch;
    783793            RTGETOPTUNION ValueUnion;
     
    785795            RTGetOptInit(&GetState, pArg->argc, pArg->argv,
    786796                         s_aOptions, RT_ELEMENTS(s_aOptions),
    787                          2, /* Skip VM name and guest control command */
    788                          RTGETOPTINIT_FLAGS_OPTS_FIRST);
     797                         iArgIdx, 0);
    789798
    790799            while (   (ch = RTGetOpt(&GetState, &ValueUnion))
     
    797806                        if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    798807                            pCtx->strUsername = ValueUnion.psz;
     808                        iArgIdx = GetState.iNext;
    799809                        break;
    800810
     
    805815                                pCtx->strPassword = ValueUnion.psz;
    806816                        }
     817                        iArgIdx = GetState.iNext;
    807818                        break;
    808819
     
    811822                        if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    812823                            rcExit = readPasswordFile(ValueUnion.psz, &pCtx->strPassword);
     824                        iArgIdx = GetState.iNext;
    813825                        break;
    814826                    }
     
    817829                        if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    818830                            pCtx->strDomain = ValueUnion.psz;
     831                        iArgIdx = GetState.iNext;
    819832                        break;
    820833
    821834                    case 'v': /* Verbose */
    822835                        pCtx->fVerbose = true;
     836                        iArgIdx = GetState.iNext;
    823837                        break;
    824838
    825                     case VINF_GETOPT_NOT_OPTION:
    826                         /* Fall through is intentional. */
    827839                    default:
     840                        /* Simply skip; might be handled in a specific command
     841                         * handler later. */
     842                        break;
     843
     844                } /* switch */
     845
     846                int iArgDiff = GetState.iNext - iArgIdx;
     847                if (iArgDiff)
     848                {
     849#ifdef DEBUG_andy
     850                    RTPrintf("Not handled (iNext=%d, iArgsCur=%d):\n", GetState.iNext, iArgIdx);
     851#endif
     852                    for (int i = iArgIdx; i < GetState.iNext; i++)
    828853                    {
    829                         Assert(GetState.iNext);
    830                         char *pszArg = RTStrDup(pArg->argv[GetState.iNext - 1]);
     854                        char *pszArg = RTStrDup(pArg->argv[i]);
    831855                        if (!pszArg)
    832856                        {
     
    837861                        pCtx->ppaArgv[pCtx->iArgc] = pszArg;
    838862                        pCtx->iArgc++;
    839                         break;
     863#ifdef DEBUG_andy
     864                        RTPrintf("\targv[%d]=%s\n", i, pArg->argv[i]);
    840865                    }
    841 
    842                 } /* switch */
     866#endif
     867                    iArgIdx = GetState.iNext;
     868                }
     869
    843870            } /* while RTGetOpt */
    844871        }
     
    10771104    };
    10781105
     1106#ifdef DEBUG_andy
     1107    RTPrintf("first=%d\n", pCtx->iFirstArgc);
     1108    for (int i=0; i<pCtx->iArgc;i++)
     1109        RTPrintf("\targv[%d]=%s\n", i, pCtx->ppaArgv[i]);
     1110#endif
     1111
    10791112    int                     ch;
    10801113    RTGETOPTUNION           ValueUnion;
    10811114    RTGETOPTSTATE           GetState;
    1082     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv, s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, 0);
     1115    RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv, s_aOptions, RT_ELEMENTS(s_aOptions),
     1116                 pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    10831117
    10841118    Utf8Str                              strCmd;
     
    11741208
    11751209                default:
    1176                     return RTGetOptPrintError(ch, &ValueUnion);
     1210                    /* Note: Necessary for handling non-options (after --) which
     1211                     *       contain a single dash, e.g. "-- foo.exe -s". */
     1212                    if (GetState.argc == GetState.iNext)
     1213                        aArgs.push_back(Bstr(ValueUnion.psz).raw());
     1214                    else
     1215                        return RTGetOptPrintError(ch, &ValueUnion);
    11771216                    break;
    11781217
     
    14101449    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
    14111450
    1412     PCOPYCONTEXT pContext = new COPYCONTEXT();
    1413     AssertPtrReturn(pContext, VERR_NO_MEMORY); /**< @todo r=klaus cannot happen with new */
    1414     ComPtr<IGuestSession> pGuestSession;
    1415     HRESULT rc = pCtx->pGuest->CreateSession(Bstr(pCtx->strUsername).raw(),
    1416                                              Bstr(pCtx->strPassword).raw(),
    1417                                              Bstr(pCtx->strDomain).raw(),
    1418                                              Bstr(strSessionName).raw(),
    1419                                              pGuestSession.asOutParam());
    1420     if (FAILED(rc))
    1421         return ctrlPrintError(pCtx->pGuest, COM_IIDOF(IGuest));
    1422 
    1423     pContext->pCmdCtx = pCtx;
    1424     pContext->fDryRun = fDryRun;
    1425     pContext->fHostToGuest = fHostToGuest;
    1426     pContext->pGuestSession = pGuestSession;
    1427 
    1428     *ppContext = pContext;
    1429 
    1430     return VINF_SUCCESS;
     1451    int vrc = VINF_SUCCESS;
     1452    try
     1453    {
     1454        PCOPYCONTEXT pContext = new COPYCONTEXT();
     1455
     1456        pContext->pCmdCtx = pCtx;
     1457        pContext->fDryRun = fDryRun;
     1458        pContext->fHostToGuest = fHostToGuest;
     1459
     1460        *ppContext = pContext;
     1461    }
     1462    catch (std::bad_alloc)
     1463    {
     1464        vrc = VERR_NO_MEMORY;
     1465    }
     1466
     1467    return vrc;
    14311468}
    14321469
     
    14391476{
    14401477    if (pContext)
    1441     {
    1442         if (pContext->pGuestSession)
    1443             pContext->pGuestSession->Close();
    14441478        delete pContext;
    1445     }
    14461479}
    14471480
     
    16171650        SafeArray<DirectoryCreateFlag_T> dirCreateFlags;
    16181651        dirCreateFlags.push_back(DirectoryCreateFlag_Parents);
    1619         HRESULT rc = pContext->pGuestSession->DirectoryCreate(Bstr(pszDir).raw(),
    1620                                                               0700, ComSafeArrayAsInParam(dirCreateFlags));
     1652        HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryCreate(Bstr(pszDir).raw(),
     1653                                                                       0700, ComSafeArrayAsInParam(dirCreateFlags));
    16211654        if (FAILED(rc))
    1622             vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     1655            vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    16231656    }
    16241657    else /* ... or on the host. */
     
    16361669 * @return  IPRT status code.
    16371670 * @param   pContext                Pointer to current copy control context.
    1638  * @param   bGuest                  true if directory needs to be checked on the guest
     1671 * @param   fOnGuest                true if directory needs to be checked on the guest
    16391672 *                                  or false if on the host.
    16401673 * @param   pszDir                  Actual directory to check.
     
    16421675 *                                  given directory exists or not.
    16431676 */
    1644 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest,
     1677static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool fOnGuest,
    16451678                             const char *pszDir, bool *fExists)
    16461679{
     
    16501683
    16511684    int vrc = VINF_SUCCESS;
    1652     if (bGuest)
     1685    if (fOnGuest)
    16531686    {
    16541687        BOOL fDirExists = FALSE;
    1655         HRESULT rc = pContext->pGuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists);
     1688        HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists);
    16561689        if (FAILED(rc))
    1657             vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     1690            vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    16581691        else
    16591692            *fExists = fDirExists ? true : false;
     
    17201753    {
    17211754        BOOL fFileExists = FALSE;
    1722         HRESULT rc = pContext->pGuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists);
     1755        HRESULT rc = pContext->pCmdCtx->pGuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists);
    17231756        if (FAILED(rc))
    1724             vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     1757            vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    17251758        else
    17261759            *fExists = fFileExists ? true : false;
     
    17961829    {
    17971830        SafeArray<CopyFileFlag_T> copyFlags;
    1798         rc = pContext->pGuestSession->CopyTo(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
    1799                                              ComSafeArrayAsInParam(copyFlags),
    1800 
    1801                                              pProgress.asOutParam());
    1802     }
    1803     else
    1804     {
    1805         SafeArray<CopyFileFlag_T> copyFlags;
    1806         rc = pContext->pGuestSession->CopyFrom(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
     1831        rc = pContext->pCmdCtx->pGuestSession->CopyTo(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
    18071832                                               ComSafeArrayAsInParam(copyFlags),
    18081833                                               pProgress.asOutParam());
    18091834    }
     1835    else
     1836    {
     1837        SafeArray<CopyFileFlag_T> copyFlags;
     1838        rc = pContext->pCmdCtx->pGuestSession->CopyFrom(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
     1839                                               ComSafeArrayAsInParam(copyFlags),
     1840                                               pProgress.asOutParam());
     1841    }
    18101842
    18111843    if (FAILED(rc))
    18121844    {
    1813         vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     1845        vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    18141846    }
    18151847    else
     
    20382070    SafeArray<DirectoryOpenFlag_T> dirOpenFlags; /* No flags supported yet. */
    20392071    ComPtr<IGuestDirectory> pDirectory;
    2040     HRESULT rc = pContext->pGuestSession->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(),
     2072    HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(),
    20412073                                                        ComSafeArrayAsInParam(dirOpenFlags),
    20422074                                                        pDirectory.asOutParam());
    20432075    if (FAILED(rc))
    2044         return ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     2076        return ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    20452077    ComPtr<IFsObjInfo> dirEntry;
    20462078    while (true)
     
    23852417    PCOPYCONTEXT pContext = NULL;
    23862418    vrc = ctrlCopyContextCreate(pCtx, fDryRun, fHostToGuest,
    2387                                 "VBoxManage Guest Control Copy", &pContext);
     2419                                  fHostToGuest
     2420                                ? "VBoxManage Guest Control - Copy to guest"
     2421                                : "VBoxManage Guest Control - Copy from guest", &pContext);
    23882422    if (RT_FAILURE(vrc))
    23892423    {
     
    25442578    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    25452579
    2546     /*
    2547      * Parse arguments.
    2548      *
    2549      * Note! No direct returns here, everyone must go thru the cleanup at the
    2550      *       end of this function.
    2551      */
    25522580    static const RTGETOPTDEF s_aOptions[] =
    25532581    {
     
    26192647    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    26202648
    2621     /*
    2622      * Parse arguments.
    2623      *
    2624      * Note! No direct returns here, everyone must go thru the cleanup at the
    2625      *       end of this function.
    2626      */
    26272649    static const RTGETOPTDEF s_aOptions[] =
    26282650    {
    2629         { "--recursive",           GETOPTDEF_RMDIR_RECURSIVE,       RTGETOPT_REQ_NOTHING }
     2651        { "--recursive",           'R',                             RTGETOPT_REQ_NOTHING }
    26302652    };
    26312653
     
    26442666        switch (ch)
    26452667        {
    2646             case GETOPTDEF_RMDIR_RECURSIVE:
     2668            case 'R':
    26472669                fRecursive = true;
    26482670                break;
     
    26952717                if (SUCCEEDED(rc))
    26962718                    CHECK_PROGRESS_ERROR(pProgress, ("Directory deletion failed"));
     2719
     2720                pProgress.setNull();
    26972721            }
    26982722            else
     
    27142738{
    27152739    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    2716 
    2717     /*
    2718      * Parse arguments.
    2719      *
    2720      * Note! No direct returns here, everyone must go thru the cleanup at the
    2721      *       end of this function.
    2722      */
    2723     static const RTGETOPTDEF s_aOptions[] = { 0 };
    27242740
    27252741    int ch;
     
    27272743    RTGETOPTSTATE GetState;
    27282744    RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    2729                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     2745                 NULL /* s_aOptions */, 0 /* RT_ELEMENTS(s_aOptions) */,
     2746                 pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    27302747
    27312748    DESTDIRMAP mapDirs;
     
    27722789}
    27732790
     2791static DECLCALLBACK(RTEXITCODE) handleCtrlRename(PGCTLCMDCTX pCtx)
     2792{
     2793    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     2794
     2795    static const RTGETOPTDEF s_aOptions[] = { 0 };
     2796
     2797    int ch;
     2798    RTGETOPTUNION ValueUnion;
     2799    RTGETOPTSTATE GetState;
     2800    RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
     2801                 NULL /*s_aOptions*/, 0 /*RT_ELEMENTS(s_aOptions)*/, pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     2802
     2803    int vrc = VINF_SUCCESS;
     2804
     2805    bool fDryrun = false;
     2806    std::vector< Utf8Str > vecSources;
     2807    Utf8Str strDest;
     2808    com::SafeArray<PathRenameFlag_T> aRenameFlags;
     2809
     2810    try
     2811    {
     2812        /** @todo Make flags configurable. */
     2813        aRenameFlags.push_back(PathRenameFlag_NoReplace);
     2814
     2815        while (   (ch = RTGetOpt(&GetState, &ValueUnion))
     2816               && RT_SUCCESS(vrc))
     2817        {
     2818            /* For options that require an argument, ValueUnion has received the value. */
     2819            switch (ch)
     2820            {
     2821                /** @todo Implement a --dryrun command. */
     2822                /** @todo Implement rename flags. */
     2823
     2824                case VINF_GETOPT_NOT_OPTION:
     2825                    vecSources.push_back(Utf8Str(ValueUnion.psz));
     2826                    strDest = ValueUnion.psz;
     2827                    break;
     2828
     2829                default:
     2830                    return RTGetOptPrintError(ch, &ValueUnion);
     2831                    break;
     2832            }
     2833        }
     2834    }
     2835    catch (std::bad_alloc)
     2836    {
     2837        vrc = VERR_NO_MEMORY;
     2838    }
     2839
     2840    if (RT_FAILURE(vrc))
     2841        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize, rc=%Rrc\n", vrc);
     2842
     2843    uint32_t cSources = vecSources.size();
     2844    if (!cSources)
     2845        return errorSyntax(USAGE_GUESTCONTROL, "No source(s) to move specified!");
     2846    if (cSources < 2)
     2847        return errorSyntax(USAGE_GUESTCONTROL, "No destination specified!");
     2848
     2849    /* Delete last element, which now is the destination. */
     2850    vecSources.pop_back();
     2851    cSources = vecSources.size();
     2852
     2853    HRESULT rc = S_OK;
     2854
     2855    if (cSources > 1)
     2856    {
     2857        ComPtr<IGuestFsObjInfo> pFsObjInfo;
     2858        rc = pCtx->pGuestSession->DirectoryQueryInfo(Bstr(strDest).raw(), pFsObjInfo.asOutParam());
     2859        if (FAILED(rc))
     2860            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Destination must be a directory\n");
     2861    }
     2862
     2863    /*
     2864     * Rename (move) the entries.
     2865     */
     2866    if (pCtx->fVerbose && cSources)
     2867        RTPrintf("Renaming %RU32 %s ...\n", cSources,
     2868                   cSources > 1
     2869                 ? "entries" : "entry");
     2870
     2871    std::vector< Utf8Str >::iterator it = vecSources.begin();
     2872    while (   (it != vecSources.end())
     2873           && !g_fGuestCtrlCanceled)
     2874    {
     2875        bool fSourceIsDirectory = false;
     2876        Utf8Str strCurSource = (*it);
     2877        Utf8Str strCurDest = strDest;
     2878
     2879        /** @todo Slooooow, but works for now. */
     2880        ComPtr<IGuestFsObjInfo> pFsObjInfo;
     2881        rc = pCtx->pGuestSession->FileQueryInfo(Bstr(strCurSource).raw(), pFsObjInfo.asOutParam());
     2882        if (FAILED(rc))
     2883        {
     2884            rc = pCtx->pGuestSession->DirectoryQueryInfo(Bstr(strCurSource).raw(), pFsObjInfo.asOutParam());
     2885            fSourceIsDirectory = SUCCEEDED(rc);
     2886        }
     2887        if (FAILED(rc))
     2888        {
     2889            if (pCtx->fVerbose)
     2890                RTPrintf("Warning: Cannot stat for element \"%s\": No such element\n",
     2891                         strCurSource.c_str());
     2892            it++;
     2893            continue; /* Skip. */
     2894        }
     2895
     2896        if (!fSourceIsDirectory)
     2897        {
     2898            char *pszFileName = RTPathFilename(strCurSource.c_str());
     2899            if (!pszFileName)
     2900            {
     2901                RTMsgError("Unable to extract file name from source \"%s\"",
     2902                           strCurSource.c_str());
     2903                break;
     2904            }
     2905
     2906            char szFileDest[RTPATH_MAX];
     2907            vrc = RTPathJoin(szFileDest, sizeof(szFileDest), strDest.c_str(), pszFileName);
     2908            if (RT_FAILURE(vrc))
     2909            {
     2910                RTMsgError("Unable to build destination name for source \"%s\", rc=%Rrc",
     2911                           strCurSource.c_str(), vrc);
     2912                break;
     2913            }
     2914
     2915            strCurDest = szFileDest;
     2916        }
     2917
     2918        if (pCtx->fVerbose)
     2919            RTPrintf("Renaming %s \"%s\" to \"%s\" ...\n",
     2920                     fSourceIsDirectory ? "directory" : "file",
     2921                     strCurSource.c_str(), strCurDest.c_str());
     2922
     2923        if (!fDryrun)
     2924        {
     2925            if (fSourceIsDirectory)
     2926            {
     2927                CHECK_ERROR_BREAK(pCtx->pGuestSession, DirectoryRename(Bstr(strCurSource).raw(),
     2928                                                                       Bstr(strCurDest).raw(),
     2929                                                                       ComSafeArrayAsInParam(aRenameFlags)));
     2930
     2931                /* Break here, since it makes no sense to rename mroe than one source to
     2932                 * the same directory. */
     2933                it = vecSources.end();
     2934                break;
     2935            }
     2936            else
     2937                CHECK_ERROR_BREAK(pCtx->pGuestSession, FileRename(Bstr(strCurSource).raw(),
     2938                                                                  Bstr(strCurDest).raw(),
     2939                                                                  ComSafeArrayAsInParam(aRenameFlags)));
     2940        }
     2941
     2942        it++;
     2943    }
     2944
     2945    if (   (it != vecSources.end())
     2946        && pCtx->fVerbose)
     2947    {
     2948        RTPrintf("Warning: Not all sources were renamed\n");
     2949    }
     2950
     2951    return FAILED(rc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS;
     2952}
     2953
    27742954static DECLCALLBACK(RTEXITCODE) handleCtrlCreateTemp(PGCTLCMDCTX pCtx)
    27752955{
    27762956    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    27772957
    2778     /*
    2779      * Parse arguments.
    2780      *
    2781      * Note! No direct returns here, everyone must go thru the cleanup at the
    2782      *       end of this function.
    2783      */
    27842958    static const RTGETOPTDEF s_aOptions[] =
    27852959    {
     
    32463420        return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a PID to close");
    32473421
    3248     /*
    3249      * Parse arguments.
    3250      *
    3251      * Note! No direct returns here, everyone must go thru the cleanup at the
    3252      *       end of this function.
    3253      */
    32543422    static const RTGETOPTDEF s_aOptions[] =
    32553423    {
     
    34473615
    34483616    if (pCtx->iArgc < 1)
    3449         return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a session ID to close");
    3450 
    3451     /*
    3452      * Parse arguments.
    3453      *
    3454      * Note! No direct returns here, everyone must go thru the cleanup at the
    3455      *       end of this function.
    3456      */
     3617        return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a session to close");
     3618
    34573619    static const RTGETOPTDEF s_aOptions[] =
    34583620    {
     
    36023764    RTGETOPTSTATE GetState;
    36033765    RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3604                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3766                 NULL /*s_aOptions*/, 0 /*RT_ELEMENTS(s_aOptions)*/, pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    36053767
    36063768    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     
    37173879             || !RTStrICmp(pArg->argv[1], "removefile"))
    37183880        gctlCmd.pfnHandler = handleCtrlRemoveFile;
     3881    else if (   !RTStrICmp(pArg->argv[1], "ren")
     3882             || !RTStrICmp(pArg->argv[1], "rename")
     3883             || !RTStrICmp(pArg->argv[1], "mv"))
     3884        gctlCmd.pfnHandler = handleCtrlRename;
    37193885    else if (   !RTStrICmp(pArg->argv[1], "createtemporary")
    37203886             || !RTStrICmp(pArg->argv[1], "createtemp")
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r48724 r49349  
    388388        if (mParmCount > pConnection->mNumParms)
    389389        {
     390            LogFlowFunc(("pHostCmd=%p requires %RU32 parms, only got %RU32 from client\n",
     391                         this, mParmCount, pConnection->mNumParms));
     392
    390393            /*
    391394            * So this call apparently failed because the guest wanted to peek
     
    766769                     mID, rcPending, mIsPending, mPendingCon.mNumParms, mFlags));
    767770
     771        int rc;
    768772        if (   mIsPending
    769773            && mPendingCon.mNumParms >= 2)
     
    776780
    777781            mIsPending = false;
    778         }
    779 
    780         return VINF_SUCCESS;
     782
     783            rc = VINF_SUCCESS;
     784        }
     785        else if (mPendingCon.mNumParms < 2)
     786            rc = VERR_BUFFER_OVERFLOW;
     787        else /** @todo Enqueue command instead of dropping? */
     788            rc = VERR_WRONG_ORDER;
     789
     790        return rc;
    781791    }
    782792
     
    10151025    void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    10161026    int hostCall(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     1027    int sessionClose(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    10171028    int uninit(void);
    10181029};
     
    13061317
    13071318/**
    1308  * Processes a command receiveed from the host side and re-routes it to
     1319 * Processes a command received from the host side and re-routes it to
    13091320 * a connect client on the guest.
    13101321 *
     
    14501461                    LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", u32ClientID));
    14511462                    rc = clientSkipMsg(u32ClientID, callHandle, cParms, paParms);
     1463                    break;
     1464
     1465                /*
     1466                 * The guest wants to close specific guest session. This is handy for
     1467                 * shutting down dedicated guest session processes from another process.
     1468                 */
     1469                case GUEST_SESSION_CLOSE:
     1470                    LogFlowFunc(("[Client %RU32] GUEST_SESSION_CLOSE\n", u32ClientID));
     1471                    rc = sessionClose(u32ClientID, callHandle, cParms, paParms);
    14521472                    break;
    14531473
     
    15221542}
    15231543
     1544/**
     1545 * Client asks another client (guest) session to close.
     1546 *
     1547 * @return  IPRT status code.
     1548 * @param   u32ClientID                 The client's ID.
     1549 * @param   callHandle                  The client's call handle.
     1550 * @param   cParms                      Number of parameters.
     1551 * @param   paParms                     Array of parameters.
     1552 */
     1553int Service::sessionClose(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1554{
     1555    if (cParms < 2)
     1556        return VERR_INVALID_PARAMETER;
     1557
     1558    uint32_t uContextID, uFlags;
     1559    int rc = paParms[0].getUInt32(&uContextID);
     1560    if (RT_SUCCESS(rc))
     1561        rc = paParms[1].getUInt32(&uFlags);
     1562
     1563    uint32_t uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID);
     1564
     1565    if (RT_SUCCESS(rc))
     1566        rc = hostProcessCommand(HOST_SESSION_CLOSE, cParms, paParms);
     1567
     1568    LogFlowFunc(("Closing guest session ID=%RU32 (from client ID=%RU32) returned with rc=%Rrc\n",
     1569                 uSessionID, u32ClientID, rc));
     1570    return rc;
     1571}
     1572
    15241573int Service::uninit()
    15251574{
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r49312 r49349  
    1059110591      <desc>
    1059210592        Removes a guest directory if not empty.
    10593 
    10594         <result name="E_NOTIMPL">
    10595           The method is not implemented yet.
    10596         </result>
    1059710593      </desc>
    1059810594      <param name="path" type="wstring" dir="in">
     
    1060410600      <desc>
    1060510601        Removes a guest directory recursively.
    10606 
    10607         <result name="E_NOTIMPL">
    10608           The method is not implemented yet.
    10609         </result>
    1061010602      </desc>
    1061110603      <param name="path" type="wstring" dir="in">
     
    1061610608      </param>
    1061710609      <param name="progress" type="IProgress" dir="return">
    10618         <desc>Progress object to track the operation completion.</desc>
     10610        <desc>Progress object to track the operation completion. This is not implemented
     10611          yet and therefore this method call will block until deletion is completed.</desc>
    1061910612      </param>
    1062010613    </method>
     
    1062310616      <desc>
    1062410617        Renames a directory on the guest.
    10625 
    10626         <result name="E_NOTIMPL">
    10627           The method is not implemented yet.
    10628         </result>
    1062910618      </desc>
    1063010619      <param name="source" type="wstring" dir="in">
     
    1094010929      <desc>
    1094110930        Renames a file on the guest.
    10942 
    10943         <result name="E_NOTIMPL">
    10944           The method is not implemented yet.
    10945         </result>
    1094610931      </desc>
    1094710932      <param name="source" type="wstring" dir="in">
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r47817 r49349  
    101101
    102102    std::map <Utf8Str, Utf8Str> mEnvironment;
     103};
     104
     105
     106/**
     107 * Structure for keeping all the relevant guest directory
     108 * information around.
     109 */
     110struct GuestDirectoryOpenInfo
     111{
     112    /** The directory path. */
     113    Utf8Str                 mPath;
     114    /** Then open filter. */
     115    Utf8Str                 mFilter;
     116    /** Opening flags. */
     117    uint32_t                mFlags;
    103118};
    104119
     
    313328#endif
    314329
    315     uint32_t GetOffset();
    316 
    317     uint32_t GetSize();
     330    uint32_t GetOffset() { return m_cbOffset; }
     331
     332    size_t GetSize() { return m_cbSize; }
    318333
    319334    int ParseBlock(GuestProcessStreamBlock &streamBlock);
     
    324339    uint32_t m_cbAllocated;
    325340    /** Currently used size of allocated internal stream buffer. */
    326     uint32_t m_cbSize;
     341    size_t m_cbSize;
    327342    /** Current offset within the internal stream buffer. */
    328343    uint32_t m_cbOffset;
     
    378393};
    379394
    380 class GuestWaitEvent
    381 {
    382 
    383 public:
    384 
    385     GuestWaitEvent(uint32_t mCID, const std::list<VBoxEventType_T> &lstEvents);
    386     virtual ~GuestWaitEvent(void);
    387 
    388 public:
    389 
    390     uint32_t                         ContextID(void) { return mCID; };
    391     const ComPtr<IEvent>             Event(void) { return mEvent; };
    392     const std::list<VBoxEventType_T> Types(void) { return mEventTypes; };
    393     size_t                           TypeCount(void) { return mEventTypes.size(); }
    394     virtual int                      Signal(IEvent *pEvent);
    395     int                              Wait(RTMSINTERVAL uTimeoutMS);
     395class GuestWaitEventPayload
     396{
     397
     398public:
     399
     400    GuestWaitEventPayload(void)
     401        : uType(0),
     402          cbData(0),
     403          pvData(NULL) { }
     404
     405    GuestWaitEventPayload(uint32_t uTypePayload,
     406                          const void *pvPayload, uint32_t cbPayload)
     407    {
     408        if (cbPayload)
     409        {
     410            pvData = RTMemAlloc(cbPayload);
     411            if (pvData)
     412            {
     413                uType = uTypePayload;
     414
     415                memcpy(pvData, pvPayload, cbPayload);
     416                cbData = cbPayload;
     417            }
     418            else /* Throw IPRT error. */
     419                throw VERR_NO_MEMORY;
     420        }
     421        else
     422        {
     423            uType = uTypePayload;
     424
     425            pvData = NULL;
     426            cbData = 0;
     427        }
     428    }
     429
     430    virtual ~GuestWaitEventPayload(void)
     431    {
     432        Clear();
     433    }
     434
     435    GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that)
     436    {
     437        CopyFromDeep(that);
     438        return *this;
     439    }
     440
     441public:
     442
     443    void Clear(void)
     444    {
     445        if (pvData)
     446        {
     447            RTMemFree(pvData);
     448            cbData = 0;
     449        }
     450        uType = 0;
     451    }
     452
     453    int CopyFromDeep(const GuestWaitEventPayload &payload)
     454    {
     455        Clear();
     456
     457        int rc;
     458        if (payload.cbData)
     459        {
     460            Assert(payload.cbData);
     461            pvData = RTMemAlloc(payload.cbData);
     462            if (pvData)
     463            {
     464                memcpy(pvData, payload.pvData, payload.cbData);
     465                cbData = payload.cbData;
     466                uType = payload.uType;
     467            }
     468            else
     469                rc = VERR_NO_MEMORY;
     470        }
     471        else
     472            rc = VINF_SUCCESS;
     473
     474        return rc;
     475    }
     476
     477    const void* Raw(void) const { return pvData; }
     478
     479    size_t Size(void) const { return cbData; }
     480
     481    uint32_t Type(void) const { return uType; }
     482
     483    void* MutableRaw(void) { return pvData; }
     484
     485protected:
     486
     487    /** Type of payload. */
     488    uint32_t uType;
     489    /** Size (in bytes) of payload. */
     490    uint32_t cbData;
     491    /** Pointer to actual payload data. */
     492    void *pvData;
     493};
     494
     495class GuestWaitEventBase
     496{
     497
     498protected:
     499
     500    GuestWaitEventBase(void);
     501    virtual ~GuestWaitEventBase(void);
     502
     503public:
     504
     505    uint32_t                        ContextID(void) { return mCID; };
     506    int                             GuestResult(void) { return mGuestRc; }
     507    int                             Result(void) { return mRc; }
     508    GuestWaitEventPayload &         Payload(void) { return mPayload; }
     509    int                             SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload);
     510    int                             Wait(RTMSINTERVAL uTimeoutMS);
     511
     512protected:
     513
     514    int             Init(uint32_t uCID);
    396515
    397516protected:
    398517
    399518    /* Shutdown indicator. */
    400     bool                       fAborted;
     519    bool                       mfAborted;
    401520    /* Associated context ID (CID). */
    402521    uint32_t                   mCID;
    403     /** List of event types this event should
    404      *  be signalled on. */
    405     std::list<VBoxEventType_T> mEventTypes;
    406522    /** The event semaphore for triggering
    407523     *  the actual event. */
    408524    RTSEMEVENT                 mEventSem;
    409     /** Pointer to the actual event. */
     525    /** The event's overall result. If
     526     *  set to VERR_GSTCTL_GUEST_ERROR,
     527     *  mGuestRc will contain the actual
     528     *  error code from the guest side. */
     529    int                        mRc;
     530    /** The event'S overall result from the
     531     *  guest side. If used, mRc must be
     532     *  set to VERR_GSTCTL_GUEST_ERROR. */
     533    int                        mGuestRc;
     534    /** The event's payload data. Optional. */
     535    GuestWaitEventPayload      mPayload;
     536};
     537
     538/** List of public guest event types. */
     539typedef std::list < VBoxEventType_T > GuestEventTypes;
     540
     541class GuestWaitEvent : public GuestWaitEventBase
     542{
     543
     544public:
     545
     546    GuestWaitEvent(uint32_t uCID);
     547    GuestWaitEvent(uint32_t uCID, const GuestEventTypes &lstEvents);
     548    virtual ~GuestWaitEvent(void);
     549
     550public:
     551
     552    int                              Cancel(void);
     553    const ComPtr<IEvent>             Event(void) { return mEvent; }
     554    int                              SignalExternal(IEvent *pEvent);
     555    const GuestEventTypes            Types(void) { return mEventTypes; }
     556    size_t                           TypeCount(void) { return mEventTypes.size(); }
     557
     558protected:
     559
     560    int                              Init(uint32_t uCID);
     561
     562protected:
     563
     564    /** List of public event types this event should
     565     *  be signalled on. Optional. */
     566    GuestEventTypes            mEventTypes;
     567    /** Pointer to the actual public event, if any. */
    410568    ComPtr<IEvent>             mEvent;
    411569};
    412 typedef std::list < GuestWaitEvent* > GuestWaitEvents;
    413 typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestWaitEventTypes;
     570/** Map of pointers to guest events. The primary key
     571 *  contains the context ID. */
     572typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents;
     573/** Map of wait events per public guest event. Nice for
     574 *  faster lookups when signalling a whole event group. */
     575typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup;
    414576
    415577class GuestBase
     
    423585public:
    424586
    425     /** For external event listeners. */
    426     int signalWaitEvents(VBoxEventType_T aType, IEvent *aEvent);
    427 
     587    /** Signals a wait event using a public guest event; also used for
     588     *  for external event listeners. */
     589    int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent);
     590    /** Signals a wait event using a guest rc. */
     591    int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int guestRc, const GuestWaitEventPayload *pPayload);
     592    /** Signals a wait event without letting public guest events know,
     593     *  extended director's cut version. */
     594    int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int rc, int guestRc, const GuestWaitEventPayload *pPayload);
    428595public:
    429596
     
    431598    void baseUninit(void);
    432599    int cancelWaitEvents(void);
     600    int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
    433601    int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
    434     int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
     602    int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
     603    int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
    435604    void unregisterWaitEvent(GuestWaitEvent *pEvent);
    436605    int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
     
    448617    /** Critical section for wait events access. */
    449618    RTCRITSECT               mWaitEventCritSect;
    450     /** Map of internal events to wait for. */
    451     GuestWaitEventTypes      mWaitEvents;
     619    /** Map of registered wait events per event group. */
     620    GuestEventGroup          mWaitEventGroups;
     621    /** Map of registered wait events. */
     622    GuestWaitEvents          mWaitEvents;
    452623};
    453624
     
    476647
    477648    int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
    478     int registerWaitEvent(const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
     649    int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
    479650    int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
    480651
  • trunk/src/VBox/Main/include/GuestDirectoryImpl.h

    r43162 r49349  
    3030class ATL_NO_VTABLE GuestDirectory :
    3131    public VirtualBoxBase,
     32    public GuestObject,
    3233    VBOX_SCRIPTABLE_IMPL(IGuestDirectory)
    3334{
     
    4445    DECLARE_EMPTY_CTOR_DTOR(GuestDirectory)
    4546
    46     int     init(GuestSession *aSession, const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags);
     47    int     init(Console *pConsole, GuestSession *pSession, ULONG uDirID, const GuestDirectoryOpenInfo &openInfo);
    4748    void    uninit(void);
    4849    HRESULT FinalConstruct(void);
     
    6162    /** @name Public internal methods.
    6263     * @{ */
     64    int            callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
     65    static Utf8Str guestErrorToString(int guestRc);
     66    static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
    6367    /** @}  */
    6468
     
    7175    struct Data
    7276    {
    73         GuestSession              *mSession;
    74         Utf8Str                    mName;
    75         Utf8Str                    mFilter;
    76         uint32_t                   mFlags;
     77        /** The directory's open info. */
     78        GuestDirectoryOpenInfo     mOpenInfo;
     79        /** The directory's ID. */
     80        uint32_t                   mID;
    7781        GuestProcessTool           mProcessTool;
    7882    } mData;
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r47817 r49349  
    8282    int startProcessAsync(void);
    8383    int terminateProcess(uint32_t uTimeoutMS, int *pGuestRc);
    84     static ProcessWaitResult_T waitFlagsToResultEx(uint32_t fWaitFlags, ProcessStatus_T procStatus, uint32_t uProcFlags, uint32_t uProtocol);
     84    static ProcessWaitResult_T waitFlagsToResultEx(uint32_t fWaitFlags, ProcessStatus_T oldStatus, ProcessStatus_T newStatus, uint32_t uProcFlags, uint32_t uProtocol);
    8585    ProcessWaitResult_T waitFlagsToResult(uint32_t fWaitFlags);
    8686    int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc);
     
    135135 * Guest process tool flags.
    136136 */
    137 /** No flags specified. */
     137/** No flags specified; wait until process terminates.
     138 *  The maximum waiting time is set in the process' startup
     139 *  info. */
    138140#define GUESTPROCESSTOOL_FLAG_NONE            0
    139 /** Run until next stream block from stdout has been
     141/** Wait until next stream block from stdout has been
    140142 *  read in completely, then return.
    141143 */
     
    169171    bool IsRunning(void);
    170172
     173    static int Run(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, int *pGuestRc);
     174
     175    static int RunEx(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, GuestCtrlStreamObjects *pStrmOutObjects,
     176                     uint32_t cStrmOutObjects, int *pGuestRc);
     177
    171178    int TerminatedOk(LONG *pExitCode);
    172179
     
    175182protected:
    176183
    177     GuestSession               *pSession;
     184    ComObjPtr<GuestSession>     pSession;
    178185    ComObjPtr<GuestProcess>     pProcess;
    179186    GuestProcessStartupInfo     mStartupInfo;
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r47817 r49349  
    327327private:
    328328
    329     typedef std::vector <ComObjPtr<GuestDirectory> > SessionDirectories;
     329    /** Map of guest directories. The key specifies the internal directory ID. */
     330    typedef std::map <uint32_t, ComObjPtr<GuestDirectory> > SessionDirectories;
    330331    /** Map of guest files. The key specifies the internal file ID. */
    331332    typedef std::map <uint32_t, ComObjPtr<GuestFile> > SessionFiles;
     
    338339     * @{ */
    339340    int                     closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc);
     341    inline bool             directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir);
    340342    int                     directoryRemoveFromList(GuestDirectory *pDirectory);
     343    int                     directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags, int *pGuestRc);
    341344    int                     directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc);
    342345    int                     objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath, bool fDirectory, const Utf8Str &strName, int *pGuestRc);
    343     int                     directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
     346    int                     directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo, ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc);
    344347    int                     directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc);
     348    int                     dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
    345349    int                     dispatchToFile(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
     350    int                     dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
    346351    int                     dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
    347352    int                     dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
     
    367372    Guest                  *getParent(void) { return mParent; }
    368373    uint32_t                getProtocolVersion(void) { return mData.mProtocolVersion; }
     374    int                     pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags, int *pGuestRc);
    369375    int                     processRemoveFromList(GuestProcess *pProcess);
    370376    int                     processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProgress);
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r48342 r49349  
    297297                    break;
    298298
    299                 case GUEST_SESSION_NOTIFY:
    300                     rc = pSession->dispatchToThis(pCtxCb, pSvcCb);
    301                     break;
    302 
    303299                case GUEST_EXEC_STATUS:
    304300                case GUEST_EXEC_OUTPUT:
     
    312308                    break;
    313309
     310                case GUEST_SESSION_NOTIFY:
     311                    rc = pSession->dispatchToThis(pCtxCb, pSvcCb);
     312                    break;
     313
    314314                default:
    315                     rc = VERR_NOT_SUPPORTED;
     315                    rc = pSession->dispatchToObject(pCtxCb, pSvcCb);
     316                    if (rc == VERR_NOT_FOUND)
     317                    {
     318                        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     319
     320                        rc = pSession->dispatchGeneric(pCtxCb, pSvcCb);
     321                    }
     322#ifndef DEBUG_andy
     323                    if (rc == VERR_NOT_IMPLEMENTED)
     324                        AssertMsgFailed(("Received not handled function %RU32\n", pCtxCb->uFunction));
     325#endif
    316326                    break;
    317327            }
     
    323333        rc = VERR_NOT_FOUND;
    324334
    325     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     335    LogFlowFuncLeaveRC(rc);
    326336    return rc;
    327337}
     
    329339int Guest::sessionRemove(GuestSession *pSession)
    330340{
     341    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     342
    331343    LogFlowThisFuncEnter();
    332344
     
    364376    }
    365377
    366     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     378    LogFlowFuncLeaveRC(rc);
    367379    return rc;
    368380}
     
    445457    }
    446458
    447     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     459    LogFlowFuncLeaveRC(rc);
    448460    return rc;
    449461}
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r47627 r49349  
    680680
    681681/**
    682  * Returns the current offset of the parser within
    683  * the internal data buffer.
    684  *
    685  * @return  uint32_t            Parser offset.
    686  */
    687 uint32_t GuestProcessStream::GetOffset()
    688 {
    689     return m_cbOffset;
    690 }
    691 
    692 uint32_t GuestProcessStream::GetSize()
    693 {
    694     return m_cbSize;
    695 }
    696 
    697 /**
    698682 * Tries to parse the next upcoming pair block within the internal
    699683 * buffer.
     
    814798    if (RT_SUCCESS(rc))
    815799    {
    816         GuestWaitEventTypes::iterator itEventTypes = mWaitEvents.begin();
    817         while (itEventTypes != mWaitEvents.end())
    818         {
    819             GuestWaitEvents::iterator itEvents = itEventTypes->second.begin();
    820             while (itEvents != itEventTypes->second.end())
     800        GuestEventGroup::iterator itEventGroups = mWaitEventGroups.begin();
     801        while (itEventGroups != mWaitEventGroups.end())
     802        {
     803            GuestWaitEvents::iterator itEvents = itEventGroups->second.begin();
     804            while (itEvents != itEventGroups->second.end())
    821805            {
    822                 GuestWaitEvent *pEvent = (*itEvents);
     806                GuestWaitEvent *pEvent = itEvents->second;
    823807                AssertPtr(pEvent);
    824808
    825809                /*
    826                  * Just cancel the event and remove it from the wait events
    827                  * map. Don't delete it though, this (hopefully) is done by
    828                  * the caller using unregisterWaitEvent().
     810                 * Just cancel the event, but don't remove it from the
     811                 * wait events map. Don't delete it though, this (hopefully)
     812                 * is done by the caller using unregisterWaitEvent().
    829813                 */
    830                 int rc2 = pEvent->Signal(NULL /* Cancel */);
     814                int rc2 = pEvent->Cancel();
    831815                AssertRC(rc2);
    832                 itEvents = itEventTypes->second.erase(itEvents);
     816
     817                itEvents++;
    833818            }
    834819
    835             mWaitEvents.erase(itEventTypes);
    836             itEventTypes = mWaitEvents.begin();
     820            itEventGroups++;
    837821        }
    838822
     
    846830}
    847831
     832int GuestBase::dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     833{
     834    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     835
     836    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     837    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     838
     839    int vrc = VINF_SUCCESS;
     840
     841    try
     842    {
     843        LogFlowFunc(("uFunc=%RU32, cParms=%RU32\n",
     844                     pCtxCb->uFunction, pSvcCb->mParms));
     845
     846        switch (pCtxCb->uFunction)
     847        {
     848            case GUEST_MSG_PROGRESS_UPDATE:
     849                break;
     850
     851            case GUEST_MSG_REPLY:
     852            {
     853                if (pSvcCb->mParms >= 3)
     854                {
     855                    int idx = 1; /* Current parameter index. */
     856                    CALLBACKDATA_MSG_REPLY dataCb;
     857                    /* pSvcCb->mpaParms[0] always contains the context ID. */
     858                    vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType);
     859                    AssertRCReturn(vrc, vrc);
     860                    vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc);
     861                    AssertRCReturn(vrc, vrc);
     862                    vrc = pSvcCb->mpaParms[idx++].getPointer(&dataCb.pvPayload, &dataCb.cbPayload);
     863                    AssertRCReturn(vrc, vrc);
     864
     865                    GuestWaitEventPayload evPayload(dataCb.uType, dataCb.pvPayload, dataCb.cbPayload);
     866                    int rc2 = signalWaitEventInternal(pCtxCb, dataCb.rc, &evPayload);
     867                    AssertRC(rc2);
     868                }
     869                else
     870                    vrc = VERR_INVALID_PARAMETER;
     871                break;
     872            }
     873
     874            default:
     875                vrc = VERR_NOT_SUPPORTED;
     876                break;
     877        }
     878    }
     879    catch (std::bad_alloc)
     880    {
     881        vrc = VERR_NO_MEMORY;
     882    }
     883    catch (int rc)
     884    {
     885        vrc = rc;
     886    }
     887
     888    LogFlowFuncLeaveRC(vrc);
     889    return vrc;
     890}
     891
    848892int GuestBase::generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID)
    849893{
     
    869913
    870914int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
    871                                  const std::list<VBoxEventType_T> &lstEvents,
     915                                 GuestWaitEvent **ppEvent)
     916{
     917    GuestEventTypes eventTypesEmpty;
     918    return registerWaitEvent(uSessionID, uObjectID, eventTypesEmpty, ppEvent);
     919}
     920
     921int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
     922                                 const GuestEventTypes &lstEvents,
    872923                                 GuestWaitEvent **ppEvent)
    873924{
     
    887938            AssertPtr(pEvent);
    888939
    889             for (std::list<VBoxEventType_T>::const_iterator itEvents = lstEvents.begin();
     940            /* Insert event into matching event group. This is for faster per-group
     941             * lookup of all events later. */
     942            for (GuestEventTypes::const_iterator itEvents = lstEvents.begin();
    890943                 itEvents != lstEvents.end(); itEvents++)
    891944            {
    892                 mWaitEvents[(*itEvents)].push_back(pEvent);
     945                mWaitEventGroups[(*itEvents)].insert(
     946                   std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent));
     947                /** @todo Check for key collision. */
    893948            }
     949
     950            /* Register event in regular event list. */
     951            /** @todo Check for key collisions. */
     952            mWaitEvents[uContextID] = pEvent;
    894953
    895954            *ppEvent = pEvent;
     
    908967}
    909968
    910 int GuestBase::signalWaitEvents(VBoxEventType_T aType, IEvent *aEvent)
     969int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent)
    911970{
    912971    int rc = RTCritSectEnter(&mWaitEventCritSect);
     972#ifdef DEBUG
     973    uint32_t cEvents = 0;
     974#endif
    913975    if (RT_SUCCESS(rc))
    914976    {
    915         GuestWaitEventTypes::iterator itTypes = mWaitEvents.find(aType);
    916         if (itTypes != mWaitEvents.end())
    917         {
    918             for (GuestWaitEvents::iterator itEvents = itTypes->second.begin();
    919                  itEvents != itTypes->second.end(); itEvents++)
     977        GuestEventGroup::iterator itGroups = mWaitEventGroups.find(aType);
     978        if (itGroups != mWaitEventGroups.end())
     979        {
     980            for (GuestWaitEvents::iterator itEvents = itGroups->second.begin();
     981                 itEvents != itGroups->second.end(); itEvents++)
    920982            {
    921                 LogFlowThisFunc(("Signalling event=%p with type=%ld ...\n",
    922                                  (*itEvents), aType));
    923 
     983#ifdef DEBUG
     984                LogFlowThisFunc(("Signalling event=%p, type=%ld (CID %RU32: Sesion=%RU32, Object=%RU32, Count=%RU32) ...\n",
     985                                 itEvents->second, aType, itEvents->first,
     986                                 VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(itEvents->first),
     987                                 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(itEvents->first),
     988                                 VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(itEvents->first)));
     989#endif
    924990                ComPtr<IEvent> pThisEvent = aEvent;
    925991                Assert(!pThisEvent.isNull());
    926                 int rc2 = (*itEvents)->Signal(aEvent);
     992                int rc2 = itEvents->second->SignalExternal(aEvent);
    927993                if (RT_SUCCESS(rc))
    928994                    rc = rc2;
     995#ifdef DEBUG
     996                cEvents++;
     997#endif
    929998            }
    930999        }
     
    9351004    }
    9361005
    937     return rc;
     1006#ifdef DEBUG
     1007    LogFlowThisFunc(("Signalled %RU32 events, rc=%Rrc\n", cEvents, rc));
     1008#endif
     1009    return rc;
     1010}
     1011
     1012int GuestBase::signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx,
     1013                                       int guestRc, const GuestWaitEventPayload *pPayload)
     1014{
     1015    if (RT_SUCCESS(guestRc))
     1016        return signalWaitEventInternalEx(pCbCtx, VINF_SUCCESS,
     1017                                         0 /* Guest rc */, pPayload);
     1018
     1019    return signalWaitEventInternalEx(pCbCtx, VERR_GSTCTL_GUEST_ERROR,
     1020                                     guestRc, pPayload);
     1021}
     1022
     1023int GuestBase::signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx,
     1024                                         int rc, int guestRc,
     1025                                         const GuestWaitEventPayload *pPayload)
     1026{
     1027    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     1028    /* pPayload is optional. */
     1029
     1030    int rc2;
     1031    GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
     1032    if (itEvent != mWaitEvents.end())
     1033    {
     1034        LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
     1035                         itEvent->second, itEvent->first, rc, guestRc, pPayload));
     1036        GuestWaitEvent *pEvent = itEvent->second;
     1037        AssertPtr(pEvent);
     1038        rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
     1039    }
     1040    else
     1041        rc2 = VERR_NOT_FOUND;
     1042
     1043    return rc2;
    9381044}
    9391045
     
    9461052    if (RT_SUCCESS(rc))
    9471053    {
    948         const std::list<VBoxEventType_T> lstTypes = pEvent->Types();
    949         for (std::list<VBoxEventType_T>::const_iterator itEvents = lstTypes.begin();
     1054        const GuestEventTypes lstTypes = pEvent->Types();
     1055        for (GuestEventTypes::const_iterator itEvents = lstTypes.begin();
    9501056             itEvents != lstTypes.end(); itEvents++)
    9511057        {
    9521058            /** @todo Slow O(n) lookup. Optimize this. */
    953             GuestWaitEvents::iterator itCurEvent = mWaitEvents[(*itEvents)].begin();
    954             while (itCurEvent != mWaitEvents[(*itEvents)].end())
     1059            GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin();
     1060            while (itCurEvent != mWaitEventGroups[(*itEvents)].end())
    9551061            {
    956              if ((*itCurEvent) == pEvent)
     1062             if (itCurEvent->second == pEvent)
    9571063             {
    958                  itCurEvent = mWaitEvents[(*itEvents)].erase(itCurEvent);
     1064                 itCurEvent = mWaitEventGroups[(*itEvents)].erase(itCurEvent);
    9591065                 break;
    9601066             }
     
    9731079}
    9741080
     1081/**
     1082 * Waits for a formerly registered guest event.
     1083 *
     1084 * @return  IPRT status code.
     1085 * @param   pEvent                  Pointer to event to wait for.
     1086 * @param   uTimeoutMS              Timeout (in ms) for waiting.
     1087 * @param   pType                   Event type of following IEvent.
     1088 *                                  Optional.
     1089 * @param   ppEvent                 Pointer to IEvent which got triggered
     1090 *                                  for this event. Optional.
     1091 */
    9751092int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
    9761093                            VBoxEventType_T *pType, IEvent **ppEvent)
    9771094{
    9781095    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1096    /* pType is optional. */
     1097    /* ppEvent is optional. */
    9791098
    9801099    int vrc = pEvent->Wait(uTimeoutMS);
     
    9821101    {
    9831102        const ComPtr<IEvent> pThisEvent = pEvent->Event();
    984         Assert(!pThisEvent.isNull());
    985 
    986         if (pType)
    987         {
    988             HRESULT hr = pThisEvent->COMGETTER(Type)(pType);
    989             if (FAILED(hr))
    990                 vrc = VERR_COM_UNEXPECTED;
    991         }
    992         if (   RT_SUCCESS(vrc)
    993             && ppEvent)
    994             pThisEvent.queryInterfaceTo(ppEvent);
    995 
    996         unconst(pThisEvent).setNull();
     1103        if (!pThisEvent.isNull()) /* Having a VBoxEventType_ event is optional. */
     1104        {
     1105            if (pType)
     1106            {
     1107                HRESULT hr = pThisEvent->COMGETTER(Type)(pType);
     1108                if (FAILED(hr))
     1109                    vrc = VERR_COM_UNEXPECTED;
     1110            }
     1111            if (   RT_SUCCESS(vrc)
     1112                && ppEvent)
     1113                pThisEvent.queryInterfaceTo(ppEvent);
     1114
     1115            unconst(pThisEvent).setNull();
     1116        }
    9971117    }
    9981118
     
    10221142}
    10231143
    1024 int GuestObject::registerWaitEvent(const std::list<VBoxEventType_T> &lstEvents,
     1144int GuestObject::registerWaitEvent(const GuestEventTypes &lstEvents,
    10251145                                   GuestWaitEvent **ppEvent)
    10261146{
     
    10581178}
    10591179
    1060 GuestWaitEvent::GuestWaitEvent(uint32_t uCID,
    1061                                const std::list<VBoxEventType_T> &lstEvents)
    1062     : fAborted(false),
    1063       mCID(uCID),
    1064       mEventTypes(lstEvents),
    1065       mEventSem(NIL_RTSEMEVENT)
    1066 {
    1067     int rc = RTSemEventCreate(&mEventSem);
    1068     AssertRC(rc);
    1069     /** @todo Throw an exception on failure! */
    1070 }
    1071 
    1072 GuestWaitEvent::~GuestWaitEvent(void)
    1073 {
    1074 }
    1075 
    1076 /**
    1077  * Signals the event. Passing NULL will abort (cancel)
    1078  * the event.
    1079  *
    1080  * @return  IPRT status code.
    1081  * @param   pEvent              IEvent to associate.
    1082  */
    1083 int GuestWaitEvent::Signal(IEvent *pEvent)
    1084 {
    1085     AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    1086 
    1087     if (pEvent)
    1088         mEvent = pEvent;
     1180GuestWaitEventBase::GuestWaitEventBase(void)
     1181    : mCID(0),
     1182      mEventSem(NIL_RTSEMEVENT),
     1183      mfAborted(false),
     1184      mRc(VINF_SUCCESS),
     1185      mGuestRc(VINF_SUCCESS)
     1186{
     1187}
     1188
     1189GuestWaitEventBase::~GuestWaitEventBase(void)
     1190{
     1191}
     1192
     1193int GuestWaitEventBase::Init(uint32_t uCID)
     1194{
     1195    mCID = uCID;
     1196
     1197    return RTSemEventCreate(&mEventSem);
     1198}
     1199
     1200int GuestWaitEventBase::SignalInternal(int rc, int guestRc,
     1201                                       const GuestWaitEventPayload *pPayload)
     1202{
     1203    AssertReturn(!mfAborted, VERR_CANCELLED);
     1204
     1205#ifdef VBOX_STRICT
     1206    if (rc == VERR_GSTCTL_GUEST_ERROR)
     1207        AssertMsg(RT_FAILURE(guestRc), ("Guest error indicated but no actual guest error set (%Rrc)\n", guestRc));
    10891208    else
    1090         ASMAtomicWriteBool(&fAborted, true);
    1091 
    1092     return RTSemEventSignal(mEventSem);
    1093 }
    1094 
    1095 int GuestWaitEvent::Wait(RTMSINTERVAL uTimeoutMS)
     1209        AssertMsg(RT_SUCCESS(guestRc), ("No guest error indicated but actual guest error set (%Rrc)\n", guestRc));
     1210#endif
     1211
     1212    int rc2;
     1213    if (pPayload)
     1214        rc2 = mPayload.CopyFromDeep(*pPayload);
     1215    else
     1216        rc2 = VINF_SUCCESS;
     1217    if (RT_SUCCESS(rc2))
     1218    {
     1219        mRc = rc;
     1220        mGuestRc = guestRc;
     1221
     1222        rc2 = RTSemEventSignal(mEventSem);
     1223    }
     1224
     1225    return rc2;
     1226}
     1227
     1228int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS)
    10961229{
    10971230    int rc = VINF_SUCCESS;
    10981231
    1099     if (ASMAtomicReadBool(&fAborted))
     1232    if (ASMAtomicReadBool(&mfAborted))
    11001233        rc = VERR_CANCELLED;
    11011234
     
    11081241            msInterval = RT_INDEFINITE_WAIT;
    11091242        rc = RTSemEventWait(mEventSem, msInterval);
    1110         if (ASMAtomicReadBool(&fAborted))
     1243        if (ASMAtomicReadBool(&mfAborted))
    11111244            rc = VERR_CANCELLED;
    1112     }
    1113 
    1114     return rc;
    1115 }
    1116 
     1245        if (RT_SUCCESS(rc))
     1246        {
     1247            /* If waiting succeeded, return the overall
     1248             * result code. */
     1249            rc = mRc;
     1250        }
     1251    }
     1252
     1253    return rc;
     1254}
     1255
     1256GuestWaitEvent::GuestWaitEvent(uint32_t uCID,
     1257                               const GuestEventTypes &lstEvents)
     1258{
     1259    int rc2 = Init(uCID);
     1260    AssertRC(rc2); /** @todo Throw exception here. */
     1261
     1262    mEventTypes = lstEvents;
     1263}
     1264
     1265GuestWaitEvent::GuestWaitEvent(uint32_t uCID)
     1266{
     1267    int rc2 = Init(uCID);
     1268    AssertRC(rc2); /** @todo Throw exception here. */
     1269}
     1270
     1271GuestWaitEvent::~GuestWaitEvent(void)
     1272{
     1273
     1274}
     1275
     1276/**
     1277 * Cancels the event.
     1278 */
     1279int GuestWaitEvent::Cancel(void)
     1280{
     1281    AssertReturn(!mfAborted, VERR_CANCELLED);
     1282    ASMAtomicWriteBool(&mfAborted, true);
     1283
     1284    return RTSemEventSignal(mEventSem);
     1285}
     1286
     1287int GuestWaitEvent::Init(uint32_t uCID)
     1288{
     1289    return GuestWaitEventBase::Init(uCID);
     1290}
     1291
     1292/**
     1293 * Signals the event.
     1294 *
     1295 * @return  IPRT status code.
     1296 * @param   pEvent              Public IEvent to associate.
     1297 *                              Optional.
     1298 */
     1299int GuestWaitEvent::SignalExternal(IEvent *pEvent)
     1300{
     1301    AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
     1302
     1303    if (pEvent)
     1304        mEvent = pEvent;
     1305
     1306    return RTSemEventSignal(mEventSem);
     1307}
     1308
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r47627 r49349  
    5959/////////////////////////////////////////////////////////////////////////////
    6060
    61 int GuestDirectory::init(GuestSession *aSession,
    62                          const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags)
    63 {
    64     LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
    65                      strPath.c_str(), strFilter.c_str(), uFlags));
     61int GuestDirectory::init(Console *pConsole, GuestSession *pSession,
     62                         ULONG uDirID, const GuestDirectoryOpenInfo &openInfo)
     63{
     64    LogFlowThisFunc(("pConsole=%p, pSession=%p, uDirID=%RU32, strPath=%s, strFilter=%s, uFlags=%x\n",
     65                     pConsole, pSession, uDirID, openInfo.mPath.c_str(), openInfo.mFilter.c_str(),
     66                     openInfo.mFlags));
     67
     68    AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
     69    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    6670
    6771    /* Enclose the state transition NotReady->InInit->Ready. */
     
    6973    AssertReturn(autoInitSpan.isOk(), E_FAIL);
    7074
    71     mData.mSession = aSession;
    72     mData.mName    = strPath;
    73     mData.mFilter  = strFilter;
    74     mData.mFlags   = uFlags;
    75 
    76     /* Start the directory process on the guest. */
    77     GuestProcessStartupInfo procInfo;
    78     procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
    79     procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
    80     procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
    81     procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
    82 
    83     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    84     /* We want the long output format which contains all the object details. */
    85     procInfo.mArguments.push_back(Utf8Str("-l"));
     75#ifndef VBOX_WITH_GUEST_CONTROL
     76    autoInitSpan.setSucceeded();
     77    return VINF_SUCCESS;
     78#else
     79    int vrc = bindToSession(pConsole, pSession, uDirID /* Object ID */);
     80    if (RT_SUCCESS(vrc))
     81    {
     82        mSession = pSession;
     83
     84        mData.mID = uDirID;
     85        mData.mOpenInfo = openInfo;
     86    }
     87
     88    if (RT_SUCCESS(vrc))
     89    {
     90        /* Start the directory process on the guest. */
     91        GuestProcessStartupInfo procInfo;
     92        procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", openInfo.mPath.c_str()));
     93        procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
     94        procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
     95        procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
     96
     97        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     98        /* We want the long output format which contains all the object details. */
     99        procInfo.mArguments.push_back(Utf8Str("-l"));
    86100#if 0 /* Flags are not supported yet. */
    87     if (uFlags & DirectoryOpenFlag_NoSymlinks)
    88         procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
     101        if (uFlags & DirectoryOpenFlag_NoSymlinks)
     102            procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
    89103#endif
    90     /** @todo Recursion support? */
    91     procInfo.mArguments.push_back(strPath); /* The directory we want to open. */
    92 
    93     /*
    94      * Start the process asynchronously and keep it around so that we can use
    95      * it later in subsequent read() calls.
    96      * Note: No guest rc available because operation is asynchronous.
    97      */
    98     int rc = mData.mProcessTool.Init(mData.mSession, procInfo,
    99                                      true /* Async */, NULL /* Guest rc */);
    100     if (RT_SUCCESS(rc))
     104        /** @todo Recursion support? */
     105        procInfo.mArguments.push_back(openInfo.mPath); /* The directory we want to open. */
     106
     107        /*
     108         * Start the process asynchronously and keep it around so that we can use
     109         * it later in subsequent read() calls.
     110         * Note: No guest rc available because operation is asynchronous.
     111         */
     112        vrc = mData.mProcessTool.Init(mSession, procInfo,
     113                                      true /* Async */, NULL /* Guest rc */);
     114    }
     115
     116    if (RT_SUCCESS(vrc))
    101117    {
    102118        /* Confirm a successful initialization when it's the case. */
    103119        autoInitSpan.setSucceeded();
    104         return rc;
    105     }
    106 
    107     autoInitSpan.setFailed();
    108     return rc;
     120        return vrc;
     121    }
     122    else
     123        autoInitSpan.setFailed();
     124
     125    return vrc;
     126#endif /* VBOX_WITH_GUEST_CONTROL */
    109127}
    110128
     
    139157    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    140158
    141     mData.mName.cloneTo(aName);
     159    mData.mOpenInfo.mPath.cloneTo(aName);
    142160
    143161    return S_OK;
     
    155173    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    156174
    157     mData.mFilter.cloneTo(aFilter);
     175    mData.mOpenInfo.mFilter.cloneTo(aFilter);
    158176
    159177    return S_OK;
     
    162180// private methods
    163181/////////////////////////////////////////////////////////////////////////////
     182
     183int GuestDirectory::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     184{
     185    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     186    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     187
     188    LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
     189                     mData.mOpenInfo.mPath.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
     190
     191    int vrc;
     192    switch (pCbCtx->uFunction)
     193    {
     194        case GUEST_DIR_NOTIFY:
     195        {
     196            int idx = 1; /* Current parameter index. */
     197            CALLBACKDATA_DIR_NOTIFY dataCb;
     198            /* pSvcCb->mpaParms[0] always contains the context ID. */
     199            pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType);
     200            pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc);
     201
     202            int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
     203
     204            LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
     205                         dataCb.uType, guestRc));
     206
     207            switch (dataCb.uType)
     208            {
     209                /* Nothing here yet, nothing to dispatch further. */
     210
     211                default:
     212                    vrc = VERR_NOT_SUPPORTED;
     213                    break;
     214            }
     215            break;
     216        }
     217
     218        default:
     219            /* Silently ignore not implemented functions. */
     220            vrc = VERR_NOT_SUPPORTED;
     221            break;
     222    }
     223
     224#ifdef DEBUG
     225    LogFlowFuncLeaveRC(vrc);
     226#endif
     227    return vrc;
     228}
     229
     230/* static */
     231Utf8Str GuestDirectory::guestErrorToString(int guestRc)
     232{
     233    Utf8Str strError;
     234
     235    /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
     236    switch (guestRc)
     237    {
     238        case VERR_DIR_NOT_EMPTY:
     239            strError += Utf8StrFmt("Directoy is not empty");
     240            break;
     241
     242        default:
     243            strError += Utf8StrFmt("%Rrc", guestRc);
     244            break;
     245    }
     246
     247    return strError;
     248}
     249
     250/* static */
     251HRESULT GuestDirectory::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
     252{
     253    AssertPtr(pInterface);
     254    AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
     255
     256    return pInterface->setError(VBOX_E_IPRT_ERROR, GuestDirectory::guestErrorToString(guestRc).c_str());
     257}
    164258
    165259// implementation of public methods
     
    176270    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    177271
    178     AssertPtr(mData.mSession);
    179     int rc = mData.mSession->directoryRemoveFromList(this);
     272    AssertPtr(mSession);
     273    int rc = mSession->directoryRemoveFromList(this);
    180274    AssertRC(rc);
    181275
     
    188282        switch (rc)
    189283        {
    190            case VERR_GSTCTL_GUEST_ERROR:
     284            case VERR_GSTCTL_GUEST_ERROR:
    191285                hr = GuestProcess::setErrorExternal(this, guestRc);
    192286                break;
     
    200294                hr = setError(VBOX_E_IPRT_ERROR,
    201295                              tr("Terminating open guest directory \"%s\" failed: %Rrc"),
    202                               mData.mName.c_str(), rc);
     296                              mData.mOpenInfo.mPath.c_str(), rc);
    203297                break;
    204298        }
     
    293387            case VERR_ACCESS_DENIED:
    294388                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
    295                               mData.mName.c_str());
     389                              mData.mOpenInfo.mPath.c_str());
    296390                break;
    297391
    298392            case VERR_PATH_NOT_FOUND:
    299393                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"),
    300                               mData.mName.c_str());
     394                              mData.mOpenInfo.mPath.c_str());
    301395                break;
    302396
     
    304398                /* See SDK reference. */
    305399                hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
    306                               mData.mName.c_str());
     400                              mData.mOpenInfo.mPath.c_str());
    307401                break;
    308402
    309403            default:
    310404                hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
    311                               mData.mName.c_str(), rc);
     405                              mData.mOpenInfo.mPath.c_str(), rc);
    312406                break;
    313407        }
  • trunk/src/VBox/Main/src-client/GuestFileImpl.cpp

    r49006 r49349  
    7777            {
    7878                Assert(!mFile.isNull());
    79                 int rc2 = mFile->signalWaitEvents(aType, aEvent);
     79                int rc2 = mFile->signalWaitEvent(aType, aEvent);
    8080#ifdef DEBUG_andy
    8181                LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n",
     
    411411int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
    412412{
    413 #ifdef DEBUG
     413    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     414    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     415
    414416    LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
    415417                     mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
    416 #endif
    417     AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
    418418
    419419    int vrc;
     
    447447
    448448    GuestWaitEvent *pEvent = NULL;
    449     std::list < VBoxEventType_T > eventTypes;
     449    GuestEventTypes eventTypes;
    450450    try
    451451    {
     
    539539        AssertRC(rc2);
    540540
     541        rc2 = signalWaitEventInternal(pCbCtx,
     542                                      guestRc, NULL /* pPayload */);
     543        AssertRC(rc2);
     544
    541545        return VINF_SUCCESS; /* Report to the guest. */
    542546    }
     
    548552            int rc2 = setFileStatus(FileStatus_Error, guestRc);
    549553            AssertRC(rc2);
     554
    550555            break;
    551556        }
     
    561566                    AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
    562567                              ("File ID %RU32 does not match context ID %RU32\n", mData.mID,
    563                                VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
     568                              VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
    564569
    565570                    /* Set the initial offset. On the guest the whole opening operation
     
    570575                /* Set the process status. */
    571576                int rc2 = setFileStatus(FileStatus_Open, guestRc);
    572                 if (RT_SUCCESS(vrc))
    573                     vrc = rc2;
     577                AssertRC(rc2);
    574578            }
    575579            else
     
    678682    }
    679683
     684    if (RT_SUCCESS(vrc))
     685    {
     686        GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb));
     687        int rc2 = signalWaitEventInternal(pCbCtx, guestRc, &payload);
     688        AssertRC(rc2);
     689    }
     690
    680691    LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n",
    681692                     dataCb.uType, dataCb.rc));
     
    708719
    709720    GuestWaitEvent *pEvent = NULL;
    710     std::list < VBoxEventType_T > eventTypes;
     721    GuestEventTypes eventTypes;
    711722    try
    712723    {
     
    765776
    766777    GuestWaitEvent *pEvent = NULL;
    767     std::list < VBoxEventType_T > eventTypes;
     778    GuestEventTypes eventTypes;
    768779    try
    769780    {
     
    820831
    821832    GuestWaitEvent *pEvent = NULL;
    822     std::list < VBoxEventType_T > eventTypes;
     833    GuestEventTypes eventTypes;
    823834    try
    824835    {
     
    876887
    877888    GuestWaitEvent *pEvent = NULL;
    878     std::list < VBoxEventType_T > eventTypes;
     889    GuestEventTypes eventTypes;
    879890    try
    880891    {
     
    970981    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    971982
    972     VBoxEventType_T evtType;
    973     ComPtr<IEvent> pIEvent;
    974983    int vrc = waitForEvent(pEvent, uTimeoutMS,
    975                            &evtType, pIEvent.asOutParam());
    976     if (RT_SUCCESS(vrc))
    977     {
    978         if (evtType == VBoxEventType_OnGuestFileOffsetChanged)
    979         {
    980             if (puOffset)
    981             {
    982                 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent;
    983                 Assert(!pFileEvent.isNull());
    984 
    985                 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset);
    986                 ComAssertComRC(hr);
    987             }
     984                           NULL /* Event type */, NULL /* IEvent */);
     985    if (RT_SUCCESS(vrc))
     986    {
     987        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     988        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     989            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     990        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_SEEK);
     991
     992        if (puOffset)
     993            *puOffset = pvCbData->u.seek.uOffActual;
     994    }
     995
     996    return vrc;
     997}
     998
     999int GuestFile::waitForRead(GuestWaitEvent *pEvent,
     1000                           uint32_t uTimeoutMS,
     1001                           void *pvData, size_t cbData, uint32_t *pcbRead)
     1002{
     1003    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1004
     1005    int vrc = waitForEvent(pEvent, uTimeoutMS,
     1006                           NULL /* Event type */, NULL /* IEvent */);
     1007    if (RT_SUCCESS(vrc))
     1008    {
     1009        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1010        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1011            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1012        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_READ);
     1013
     1014        uint32_t cbRead = pvCbData->u.read.cbData;
     1015        if (   cbRead
     1016            && cbRead <= cbData)
     1017        {
     1018            memcpy(pvData,
     1019                   pvCbData->u.read.pvData, cbRead);
    9881020        }
    9891021        else
    990             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
    991     }
    992 
    993     return vrc;
    994 }
    995 
    996 int GuestFile::waitForRead(GuestWaitEvent *pEvent,
    997                            uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead)
    998 {
    999     AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    1000 
    1001     VBoxEventType_T evtType;
    1002     ComPtr<IEvent> pIEvent;
    1003     int vrc = waitForEvent(pEvent, uTimeoutMS,
    1004                            &evtType, pIEvent.asOutParam());
    1005     if (RT_SUCCESS(vrc))
    1006     {
    1007         if (evtType == VBoxEventType_OnGuestFileRead)
    1008         {
    1009             ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent;
    1010             Assert(!pFileEvent.isNull());
    1011 
    1012             HRESULT hr;
    1013             if (pvData)
    1014             {
    1015                 com::SafeArray <BYTE> data;
    1016                 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
    1017                 ComAssertComRC(hr);
    1018                 size_t cbRead = data.size();
    1019                 if (   cbRead
    1020                     && cbRead <= cbData)
    1021                 {
    1022                     memcpy(pvData, data.raw(), data.size());
    1023                 }
    1024                 else
    1025                     vrc = VERR_BUFFER_OVERFLOW;
    1026             }
    1027             if (pcbRead)
    1028             {
    1029                 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead);
    1030                 ComAssertComRC(hr);
    1031             }
    1032         }
    1033         else
    1034             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
     1022            vrc = VERR_BUFFER_OVERFLOW;
     1023
     1024        if (pcbRead)
     1025            *pcbRead = cbRead;
    10351026    }
    10361027
     
    10421033{
    10431034    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    1044     /* pFileStatus is optional. */
    1045 
    1046     VBoxEventType_T evtType;
    1047     ComPtr<IEvent> pIEvent;
     1035
    10481036    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1049                            &evtType, pIEvent.asOutParam());
    1050     if (RT_SUCCESS(vrc))
    1051     {
    1052         Assert(evtType == VBoxEventType_OnGuestFileStateChanged);
    1053         ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent;
    1054         Assert(!pFileEvent.isNull());
    1055 
    1056         HRESULT hr;
    1057         if (pFileStatus)
    1058         {
    1059             hr = pFileEvent->COMGETTER(Status)(pFileStatus);
    1060             ComAssertComRC(hr);
    1061         }
    1062 
    1063         ComPtr<IVirtualBoxErrorInfo> errorInfo;
    1064         hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam());
    1065         ComAssertComRC(hr);
    1066 
    1067         LONG lGuestRc;
    1068         hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
    1069         ComAssertComRC(hr);
    1070 
    1071         LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
    1072                          lGuestRc, lGuestRc));
    1073 
    1074         if (RT_FAILURE((int)lGuestRc))
    1075             vrc = VERR_GSTCTL_GUEST_ERROR;
     1037                           NULL /* Event type */, NULL /* IEvent */);
     1038    if (RT_SUCCESS(vrc))
     1039    {
     1040        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1041        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1042            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1043        /* Note: pvCbData->uType can be different types. */;
     1044
     1045
    10761046
    10771047        if (pGuestRc)
    1078             *pGuestRc = (int)lGuestRc;
     1048            *pGuestRc = pvCbData->rc; /* int vs. uint32_t */
    10791049    }
    10801050
     
    10871057    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    10881058
    1089     VBoxEventType_T evtType;
    1090     ComPtr<IEvent> pIEvent;
    10911059    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1092                            &evtType, pIEvent.asOutParam());
    1093     if (RT_SUCCESS(vrc))
    1094     {
    1095         if (evtType == VBoxEventType_OnGuestFileWrite)
    1096         {
    1097             if (pcbWritten)
    1098             {
    1099                 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent;
    1100                 Assert(!pFileEvent.isNull());
    1101 
    1102                 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten);
    1103                 ComAssertComRC(hr);
    1104             }
    1105         }
    1106         else
    1107             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
     1060                           NULL /* Event type */, NULL /* IEvent */);
     1061    if (RT_SUCCESS(vrc))
     1062    {
     1063        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1064        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1065            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1066        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_WRITE);
     1067
     1068        if (pcbWritten)
     1069            *pcbWritten = pvCbData->u.write.cbWritten;
    11081070    }
    11091071
     
    11251087
    11261088    GuestWaitEvent *pEvent = NULL;
    1127     std::list < VBoxEventType_T > eventTypes;
     1089    GuestEventTypes eventTypes;
    11281090    try
    11291091    {
     
    11841146
    11851147    GuestWaitEvent *pEvent = NULL;
    1186     std::list < VBoxEventType_T > eventTypes;
     1148    GuestEventTypes eventTypes;
    11871149    try
    11881150    {
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r48770 r49349  
    116116            {
    117117                Assert(!mProcess.isNull());
    118                 int rc2 = mProcess->signalWaitEvents(aType, aEvent);
    119 #ifdef DEBUG_andy
     118                int rc2 = mProcess->signalWaitEvent(aType, aEvent);
     119#ifdef DEBUG
    120120                LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n",
    121121                                 aType, mProcess, rc2));
     
    512512
    513513#ifdef DEBUG
    514     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     514    LogFlowFuncLeaveRC(vrc);
    515515#endif
    516516    return vrc;
     
    647647    int vrc = setProcessStatus(ProcessStatus_Down, VINF_SUCCESS);
    648648
    649     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     649    LogFlowFuncLeaveRC(vrc);
    650650    return vrc;
    651651}
     
    714714    }
    715715
    716     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     716    LogFlowFuncLeaveRC(vrc);
    717717    return vrc;
    718718}
     
    832832    }
    833833
    834     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     834    LogFlowFuncLeaveRC(vrc);
    835835    return vrc;
    836836}
     
    868868    }
    869869
    870     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     870    LogFlowFuncLeaveRC(vrc);
    871871    return vrc;
    872872}
     
    904904
    905905    GuestWaitEvent *pEvent = NULL;
    906     std::list < VBoxEventType_T > eventTypes;
     906    GuestEventTypes eventTypes;
    907907    try
    908908    {
     
    948948    unregisterWaitEvent(pEvent);
    949949
    950     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     950    LogFlowFuncLeaveRC(vrc);
    951951    return vrc;
    952952}
     
    10411041
    10421042    GuestWaitEvent *pEvent = NULL;
    1043     std::list < VBoxEventType_T > eventTypes;
     1043    GuestEventTypes eventTypes;
    10441044    try
    10451045    {
     
    11681168    unregisterWaitEvent(pEvent);
    11691169
    1170     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1170    LogFlowFuncLeaveRC(vrc);
    11711171    return vrc;
    11721172}
     
    12001200    }
    12011201
    1202     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1202    LogFlowFuncLeaveRC(vrc);
    12031203    return vrc;
    12041204}
     
    12501250    {
    12511251        GuestWaitEvent *pEvent = NULL;
    1252         std::list < VBoxEventType_T > eventTypes;
     1252        GuestEventTypes eventTypes;
    12531253        try
    12541254        {
     
    12791279    }
    12801280
    1281     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1281    LogFlowFuncLeaveRC(vrc);
    12821282    return vrc;
    12831283}
     
    12851285/* static */
    12861286ProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags,
    1287                                                       ProcessStatus_T procStatus, uint32_t uProcFlags,
    1288                                                       uint32_t uProtocol)
     1287                                                      ProcessStatus_T oldStatus, ProcessStatus_T newStatus,
     1288                                                      uint32_t uProcFlags, uint32_t uProtocol)
    12891289{
    12901290    ProcessWaitResult_T waitResult = ProcessWaitResult_None;
    12911291
    1292     if (   (fWaitFlags & ProcessWaitForFlag_Terminate)
    1293         || (fWaitFlags & ProcessWaitForFlag_StdIn)
    1294         || (fWaitFlags & ProcessWaitForFlag_StdOut)
    1295         || (fWaitFlags & ProcessWaitForFlag_StdErr))
    1296     {
    1297         switch (procStatus)
    1298         {
    1299             case ProcessStatus_TerminatedNormally:
    1300             case ProcessStatus_TerminatedSignal:
    1301             case ProcessStatus_TerminatedAbnormally:
    1302             case ProcessStatus_Down:
    1303                 waitResult = ProcessWaitResult_Terminate;
    1304                 break;
    1305 
    1306             case ProcessStatus_TimedOutKilled:
    1307             case ProcessStatus_TimedOutAbnormally:
    1308                 waitResult = ProcessWaitResult_Timeout;
    1309                 break;
    1310 
    1311             case ProcessStatus_Error:
    1312                 /* Handled above. */
    1313                 break;
    1314 
    1315             case ProcessStatus_Started:
     1292    switch (newStatus)
     1293    {
     1294        case ProcessStatus_TerminatedNormally:
     1295        case ProcessStatus_TerminatedSignal:
     1296        case ProcessStatus_TerminatedAbnormally:
     1297            waitResult = ProcessWaitResult_Terminate;
     1298            break;
     1299        case ProcessStatus_Down:
     1300            waitResult = ProcessWaitResult_Terminate;
     1301            break;
     1302
     1303        case ProcessStatus_TimedOutKilled:
     1304            /* Fall through is intentional. */
     1305        case ProcessStatus_TimedOutAbnormally:
     1306            waitResult = ProcessWaitResult_Timeout;
     1307            break;
     1308
     1309        case ProcessStatus_Error:
     1310            waitResult = ProcessWaitResult_Error;
     1311            break;
     1312
     1313        case ProcessStatus_Started:
     1314        {
     1315            switch (oldStatus)
    13161316            {
    1317                 /*
    1318                  * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
    1319                  * caller is not interested in getting further process statuses -- so just don't notify
    1320                  * anything here anymore and return.
    1321                  */
    1322                 if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
    1323                     waitResult = ProcessWaitResult_Start;
    1324                 break;
     1317                case ProcessStatus_Starting:
     1318                    if (fWaitFlags & ProcessWaitForFlag_Start)
     1319                    {
     1320                        waitResult = ProcessWaitResult_Start;
     1321                    }
     1322                    else
     1323                    {
     1324                        /*
     1325                         * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
     1326                         * caller is not interested in getting further process statuses -- so just don't notify
     1327                         * anything here anymore and return.
     1328                         */
     1329                        if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
     1330                            waitResult = ProcessWaitResult_Start;
     1331                    }
     1332                    break;
     1333
     1334                default:
     1335                    /* No result available (yet). */
     1336                    break;
    13251337            }
    1326 
    1327             case ProcessStatus_Undefined:
    1328             case ProcessStatus_Starting:
    1329                 /* No result available yet. */
    1330                 break;
    1331 
    1332             default:
    1333                 AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
    1334                 break;
    1335         }
    1336     }
    1337     else if (fWaitFlags & ProcessWaitForFlag_Start)
    1338     {
    1339         switch (procStatus)
    1340         {
    1341             case ProcessStatus_Started:
    1342             case ProcessStatus_Paused:
    1343             case ProcessStatus_Terminating:
    1344             case ProcessStatus_TerminatedNormally:
    1345             case ProcessStatus_TerminatedSignal:
    1346             case ProcessStatus_TerminatedAbnormally:
    1347             case ProcessStatus_Down:
    1348                 waitResult = ProcessWaitResult_Start;
    1349                 break;
    1350 
    1351             case ProcessStatus_Error:
    1352                 waitResult = ProcessWaitResult_Error;
    1353                 break;
    1354 
    1355             case ProcessStatus_TimedOutKilled:
    1356             case ProcessStatus_TimedOutAbnormally:
    1357                 waitResult = ProcessWaitResult_Timeout;
    1358                 break;
    1359 
    1360             case ProcessStatus_Undefined:
    1361             case ProcessStatus_Starting:
    1362                 /* No result available yet. */
    1363                 break;
    1364 
    1365             default:
    1366                 AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
    1367                 break;
    1368         }
    1369     }
    1370 
    1371     /* Filter out waits which are *not* supported using
    1372      * older guest control Guest Additions.
    1373      *
    1374      ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
    1375      */
    1376     if (uProtocol < 99) /* See @todo above. */
    1377     {
    1378         if (   waitResult == ProcessWaitResult_None
    1379             /* We don't support waiting for stdin, out + err,
    1380              * just skip waiting then. */
    1381             && (   (fWaitFlags & ProcessWaitForFlag_StdIn)
    1382                 || (fWaitFlags & ProcessWaitForFlag_StdOut)
    1383                 || (fWaitFlags & ProcessWaitForFlag_StdErr)
     1338            break;
     1339        }
     1340
     1341        case ProcessStatus_Undefined:
     1342        case ProcessStatus_Starting:
     1343            /* No result available yet. */
     1344            break;
     1345
     1346        default:
     1347            AssertMsgFailed(("Unhandled process status %ld\n", newStatus));
     1348            break;
     1349    }
     1350
     1351    if (newStatus == ProcessStatus_Started)
     1352    {
     1353        /* Filter out waits which are *not* supported using
     1354         * older guest control Guest Additions.
     1355         *
     1356         ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
     1357         */
     1358        if (uProtocol < 99) /* See @todo above. */
     1359        {
     1360            if (   waitResult == ProcessWaitResult_None
     1361                /* We don't support waiting for stdin, out + err,
     1362                 * just skip waiting then. */
     1363                && (   (fWaitFlags & ProcessWaitForFlag_StdIn)
     1364                    || (fWaitFlags & ProcessWaitForFlag_StdOut)
     1365                    || (fWaitFlags & ProcessWaitForFlag_StdErr)
     1366                   )
    13841367               )
    1385            )
    1386         {
    1387             /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
    1388             waitResult = ProcessWaitResult_WaitFlagNotSupported;
    1389         }
    1390     }
    1391 
     1368            {
     1369                /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
     1370                waitResult = ProcessWaitResult_WaitFlagNotSupported;
     1371            }
     1372        }
     1373    }
     1374
     1375#ifdef DEBUG
     1376    LogFlowFunc(("oldStatus=%ld, newStatus=%ld, fWaitFlags=0x%x, waitResult=%ld\n",
     1377                 oldStatus, newStatus, fWaitFlags, waitResult));
     1378#endif
    13921379    return waitResult;
    13931380}
     
    13961383{
    13971384    AssertPtr(mSession);
    1398     return GuestProcess::waitFlagsToResultEx(fWaitFlags, mData.mStatus, mData.mProcess.mFlags,
    1399                                              mSession->getProtocolVersion());
    1400 }
    1401 
    1402 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
     1385    return GuestProcess::waitFlagsToResultEx(fWaitFlags,
     1386                                             mData.mStatus /* curStatus */, mData.mStatus /* newStatus */,
     1387                                             mData.mProcess.mFlags, mSession->getProtocolVersion());
     1388}
     1389
     1390int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS,
     1391                          ProcessWaitResult_T &waitResult, int *pGuestRc)
    14031392{
    14041393    AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
    14051394
    1406     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1395    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    14071396
    14081397    LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, procStatus=%RU32, procRc=%Rrc, pGuestRc=%p\n",
     
    14101399
    14111400    /* Did some error occur before? Then skip waiting and return. */
    1412     if (mData.mStatus == ProcessStatus_Error)
     1401    ProcessStatus_T curStatus = mData.mStatus;
     1402    if (curStatus == ProcessStatus_Error)
    14131403    {
    14141404        waitResult = ProcessWaitResult_Error;
     
    14201410
    14211411    waitResult = waitFlagsToResult(fWaitFlags);
    1422     LogFlowThisFunc(("waitFlagToResult=%ld\n", waitResult));
    14231412
    14241413    /* No waiting needed? Return immediately using the last set error. */
     
    14351424
    14361425    GuestWaitEvent *pEvent = NULL;
    1437     std::list < VBoxEventType_T > eventTypes;
     1426    GuestEventTypes eventTypes;
    14381427    try
    14391428    {
     
    14531442     * Do the actual waiting.
    14541443     */
    1455     ProcessStatus_T processStatus = ProcessStatus_Undefined;
     1444    ProcessStatus_T newStatus = ProcessStatus_Undefined;
    14561445    uint64_t u64StartMS = RTTimeMilliTS();
    14571446    for (;;)
     
    14681457                                    uTimeoutMS == RT_INDEFINITE_WAIT
    14691458                                  ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS,
    1470                                   &processStatus, pGuestRc);
     1459                                  &newStatus, pGuestRc);
    14711460        if (RT_SUCCESS(vrc))
    14721461        {
    14731462            alock.acquire();
    14741463
    1475             waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,
     1464            waitResult = waitFlagsToResultEx(fWaitFlags, curStatus, newStatus,
    14761465                                             mData.mProcess.mFlags, mSession->getProtocolVersion());
    1477             LogFlowThisFunc(("Got new status change: waitResult=%ld, processStatus=%ld\n",
    1478                              waitResult, processStatus));
     1466#ifdef DEBUG
     1467            LogFlowThisFunc(("Got new status change: fWaitFlags=0x%x, newStatus=%ld, waitResult=%ld\n",
     1468                             fWaitFlags, newStatus, waitResult));
     1469#endif
    14791470            if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */
    14801471                break;
     
    14881479    unregisterWaitEvent(pEvent);
    14891480
    1490     LogFlowThisFunc(("Returned waitResult=%ld, processStatus=%ld, rc=%Rrc\n",
    1491                      waitResult, processStatus, vrc));
     1481    LogFlowThisFunc(("Returned waitResult=%ld, newStatus=%ld, rc=%Rrc\n",
     1482                     waitResult, newStatus, vrc));
    14921483    return vrc;
    14931484}
     
    15011492    ComPtr<IEvent> pIEvent;
    15021493    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1503                            &evtType, pIEvent.asOutParam());
     1494                                 &evtType, pIEvent.asOutParam());
    15041495    if (RT_SUCCESS(vrc))
    15051496    {
     
    15471538    {
    15481539        vrc = waitForEvent(pEvent, uTimeoutMS,
    1549                            &evtType, pIEvent.asOutParam());
     1540                                 &evtType, pIEvent.asOutParam());
    15501541        if (RT_SUCCESS(vrc))
    15511542        {
    1552 #ifdef DEBUG_andy
    1553             LogFlowThisFunc(("pEvent=%p, evtType=%ld\n", pEvent, evtType));
    1554 #endif
    15551543            if (evtType == VBoxEventType_OnGuestProcessOutput)
    15561544            {
     
    15601548                ULONG uHandleEvent;
    15611549                HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent);
    1562                 LogFlowThisFunc(("Received output, uHandle=%RU32\n", uHandleEvent));
    15631550                if (   SUCCEEDED(hr)
    15641551                    && uHandleEvent == uHandle)
     
    15791566                            else
    15801567                                vrc = VERR_BUFFER_OVERFLOW;
     1568
     1569                            LogFlowThisFunc(("Read %zu bytes (uHandle=%RU32), rc=%Rrc\n",
     1570                                             cbRead, uHandleEvent, vrc));
    15811571                        }
    15821572                    }
     
    16081598    }
    16091599
    1610     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1600    LogFlowFuncLeaveRC(vrc);
    16111601    return vrc;
    16121602}
     
    16291619        Assert(!pProcessEvent.isNull());
    16301620
    1631         HRESULT hr;
     1621        ProcessStatus_T procStatus;
     1622        HRESULT hr = pProcessEvent->COMGETTER(Status)(&procStatus);
     1623        ComAssertComRC(hr);
    16321624        if (pProcessStatus)
    1633         {
    1634             hr = pProcessEvent->COMGETTER(Status)(pProcessStatus);
    1635             ComAssertComRC(hr);
    1636         }
     1625            *pProcessStatus = procStatus;
    16371626
    16381627        ComPtr<IVirtualBoxErrorInfo> errorInfo;
     
    16441633        ComAssertComRC(hr);
    16451634
    1646         LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
    1647                          lGuestRc, lGuestRc));
     1635        LogFlowThisFunc(("procStatus=%RU32, resultDetail=%RI32 (rc=%Rrc)\n",
     1636                         procStatus, lGuestRc, lGuestRc));
    16481637
    16491638        if (RT_FAILURE((int)lGuestRc))
     
    16541643    }
    16551644
    1656     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1645    LogFlowFuncLeaveRC(vrc);
    16571646    return vrc;
    16581647}
     
    17101699
    17111700    GuestWaitEvent *pEvent = NULL;
    1712     std::list < VBoxEventType_T > eventTypes;
     1701    GuestEventTypes eventTypes;
    17131702    try
    17141703    {
     
    18141803    LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead));
    18151804
    1816     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1805    LogFlowFuncLeaveRC(vrc);
    18171806    return hr;
    18181807#endif /* VBOX_WITH_GUEST_CONTROL */
     
    18611850    mSession->processRemoveFromList(this);
    18621851
    1863     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1852    LogFlowFuncLeaveRC(vrc);
    18641853    return hr;
    18651854#endif /* VBOX_WITH_GUEST_CONTROL */
     
    19091898    }
    19101899
    1911     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1900    LogFlowFuncLeaveRC(vrc);
    19121901    return hr;
    19131902#endif /* VBOX_WITH_GUEST_CONTROL */
     
    19781967    *aWritten = (ULONG)cbWritten;
    19791968
    1980     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1969    LogFlowFuncLeaveRC(vrc);
    19811970    return hr;
    19821971#endif /* VBOX_WITH_GUEST_CONTROL */
     
    20292018    AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
    20302019
    2031     pSession     = pGuestSession;
     2020    pSession = pGuestSession;
    20322021    mStartupInfo = startupInfo;
    20332022
     
    20502039    }
    20512040
    2052     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     2041    LogFlowFuncLeaveRC(vrc);
    20532042    return vrc;
    20542043}
     
    20972086}
    20982087
     2088/* static */
     2089int GuestProcessTool::Run(      GuestSession            *pGuestSession,
     2090                          const GuestProcessStartupInfo &startupInfo,
     2091                                int                     *pGuestRc)
     2092{
     2093    return RunEx(pGuestSession, startupInfo,
     2094                 NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
     2095                 pGuestRc);
     2096}
     2097
     2098/* static */
     2099int GuestProcessTool::RunEx(      GuestSession            *pGuestSession,
     2100                            const GuestProcessStartupInfo &startupInfo,
     2101                                  GuestCtrlStreamObjects  *pStrmOutObjects,
     2102                                  uint32_t                 cStrmOutObjects,
     2103                                  int                     *pGuestRc)
     2104{
     2105    GuestProcessTool procTool; int guestRc;
     2106    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc);
     2107    if (RT_SUCCESS(vrc))
     2108    {
     2109        while (cStrmOutObjects--)
     2110        {
     2111            try
     2112            {
     2113                GuestProcessStreamBlock strmBlk;
     2114                vrc = procTool.WaitEx(  pStrmOutObjects
     2115                                      ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK
     2116                                      : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc);
     2117                if (pStrmOutObjects)
     2118                    pStrmOutObjects->push_back(strmBlk);
     2119            }
     2120            catch (std::bad_alloc)
     2121            {
     2122                vrc = VERR_NO_MEMORY;
     2123            }
     2124        }
     2125    }
     2126
     2127    if (RT_SUCCESS(vrc))
     2128    {
     2129        /* Make sure the process runs until completion. */
     2130        vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
     2131
     2132        Assert(RT_SUCCESS(guestRc));
     2133        guestRc = procTool.TerminatedOk(NULL /* Exit code */);
     2134        if (pGuestRc)
     2135            *pGuestRc = guestRc;
     2136    }
     2137    else if (vrc == VERR_GSTCTL_GUEST_ERROR)
     2138    {
     2139        if (pGuestRc)
     2140            *pGuestRc = guestRc;
     2141    }
     2142
     2143    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
     2144    return vrc;
     2145}
     2146
    20992147int GuestProcessTool::TerminatedOk(LONG *pExitCode)
    21002148{
     
    21022150    /* pExitCode is optional. */
    21032151
     2152    int vrc;
    21042153    if (!IsRunning())
    21052154    {
     
    21112160            *pExitCode = exitCode;
    21122161
    2113         if (exitCode != 0)
    2114             return VERR_NOT_EQUAL; /** @todo Special guest control rc needed! */
    2115         return VINF_SUCCESS;
    2116     }
    2117 
    2118     return VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
     2162        vrc = (exitCode != 0)
     2163              /** @todo Special guest control rc needed! */
     2164            ? VERR_NOT_EQUAL : VINF_SUCCESS;
     2165    }
     2166    else
     2167        vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
     2168
     2169    LogFlowFuncLeaveRC(vrc);
     2170    return vrc;
    21192171}
    21202172
    21212173int GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc)
    21222174{
    2123     return WaitEx(fFlags, NULL /* pStreamBlock */, pGuestRc);
    2124 }
    2125 
    2126 int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc)
    2127 {
    2128     LogFlowThisFunc(("pSession=%p, fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
    2129                      pSession, fFlags, pStreamBlock, pGuestRc));
    2130 
    2131     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    2132     Assert(!pProcess.isNull());
    2133     /* Other parameters are optional. */
     2175    return WaitEx(fFlags, NULL /* pStrmBlkOut */, pGuestRc);
     2176}
     2177
     2178int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pGuestRc)
     2179{
     2180    LogFlowThisFunc(("fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
     2181                     fFlags, pStrmBlkOut, pGuestRc));
    21342182
    21352183    /* Can we parse the next block without waiting? */
     
    21372185    if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)
    21382186    {
    2139         AssertPtr(pStreamBlock);
    2140         vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
     2187        AssertPtr(pStrmBlkOut);
     2188        vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut);
    21412189        if (RT_SUCCESS(vrc))
    21422190            return vrc;
     
    21512199        fWaitFlags |= ProcessWaitForFlag_StdErr;
    21522200
    2153     LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));
    2154 
    21552201    /** @todo Decrease timeout while running. */
     2202    uint64_t u64StartMS = RTTimeMilliTS();
    21562203    uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
    21572204
     
    21652212    bool fHandleStdErr = false;
    21662213
     2214    /**
     2215     * Updates the elapsed time and checks if a
     2216     * timeout happened, then breaking out of the loop.
     2217     */
     2218#define UPDATE_AND_CHECK_ELAPSED_TIME()          \
     2219    u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \
     2220    if (   uTimeoutMS   != RT_INDEFINITE_WAIT    \
     2221        && u64ElapsedMS >= uTimeoutMS)           \
     2222    {                                            \
     2223        vrc = VERR_TIMEOUT;                      \
     2224        break;                                   \
     2225    }
     2226
     2227    /**
     2228     * Returns the remaining time (in ms).
     2229     */
     2230#define GET_REMAINING_TIME                                     \
     2231      uTimeoutMS == RT_INDEFINITE_WAIT                         \
     2232    ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS \
     2233
    21672234    ProcessWaitResult_T waitRes;
    21682235    do
    21692236    {
    2170         vrc = pProcess->waitFor(fWaitFlags,
    2171                                 uTimeoutMS, waitRes, &guestRc);
     2237        uint64_t u64ElapsedMS;
     2238        UPDATE_AND_CHECK_ELAPSED_TIME();
     2239
     2240        vrc = pProcess->waitFor(fWaitFlags, GET_REMAINING_TIME,
     2241                                waitRes, &guestRc);
    21722242        if (RT_FAILURE(vrc))
    21732243            break;
     
    22192289        }
    22202290
     2291        if (RT_FAILURE(vrc))
     2292            break;
     2293
    22212294        if (fHandleStdOut)
    22222295        {
     2296            UPDATE_AND_CHECK_ELAPSED_TIME();
     2297
    22232298            cbRead = 0;
    22242299            vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
    2225                                      uTimeoutMS, byBuf, sizeof(byBuf),
     2300                                     GET_REMAINING_TIME,
     2301                                     byBuf, sizeof(byBuf),
    22262302                                     &cbRead, &guestRc);
    2227             if (RT_FAILURE(vrc))
     2303            if (   RT_FAILURE(vrc)
     2304                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    22282305                break;
    22292306
     
    22362313                    && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK))
    22372314                {
    2238                     AssertPtr(pStreamBlock);
    2239                     vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
     2315                    AssertPtr(pStrmBlkOut);
     2316                    vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut);
     2317
     2318                    /* When successful, break out of the loop because we're done
     2319                     * with reading the first stream block. */
    22402320                    if (RT_SUCCESS(vrc))
    22412321                        fDone = true;
     
    22482328        if (fHandleStdErr)
    22492329        {
     2330            UPDATE_AND_CHECK_ELAPSED_TIME();
     2331
    22502332            cbRead = 0;
    22512333            vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf),
    2252                                      uTimeoutMS, byBuf, sizeof(byBuf),
     2334                                     GET_REMAINING_TIME,
     2335                                     byBuf, sizeof(byBuf),
    22532336                                     &cbRead, &guestRc);
    2254             if (RT_FAILURE(vrc))
     2337            if (   RT_FAILURE(vrc)
     2338                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    22552339                break;
    22562340
     
    22662350    } while (!fDone && RT_SUCCESS(vrc));
    22672351
     2352#undef UPDATE_AND_CHECK_ELAPSED_TIME
     2353#undef GET_REMAINING_TIME
     2354
    22682355    LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n",
    22692356                     vrc, guestRc, waitRes));
     
    22712358        *pGuestRc = guestRc;
    22722359
    2273     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     2360    LogFlowFuncLeaveRC(vrc);
    22742361    return vrc;
    22752362}
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r48342 r49349  
    114114            {
    115115                Assert(!mSession.isNull());
    116                 int rc2 = mSession->signalWaitEvents(aType, aEvent);
     116                int rc2 = mSession->signalWaitEvent(aType, aEvent);
    117117#ifdef DEBUG_andy
    118118                LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n",
     
    289289         itDirs != mData.mDirectories.end(); ++itDirs)
    290290    {
    291         (*itDirs)->Release();
     291        itDirs->second->Release();
    292292    }
    293293    mData.mDirectories.clear();
     
    665665
    666666    GuestWaitEvent *pEvent = NULL;
    667     std::list < VBoxEventType_T > eventTypes;
     667    GuestEventTypes eventTypes;
    668668    try
    669669    {
     
    702702}
    703703
     704int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
     705                                          uint32_t uFlags, int *pGuestRc)
     706{
     707    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
     708                     strPath.c_str(), uMode, uFlags));
     709
     710    int vrc = VINF_SUCCESS;
     711
     712    GuestProcessStartupInfo procInfo;
     713    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
     714    procInfo.mFlags   = ProcessCreateFlag_Hidden;
     715
     716    try
     717    {
     718        /* Construct arguments. */
     719        if (uFlags & DirectoryCreateFlag_Parents)
     720            procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
     721        if (uMode)
     722        {
     723            procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
     724
     725            char szMode[16];
     726            if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
     727            {
     728                procInfo.mArguments.push_back(Utf8Str(szMode));
     729            }
     730            else
     731                vrc = VERR_BUFFER_OVERFLOW;
     732        }
     733        procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
     734    }
     735    catch (std::bad_alloc)
     736    {
     737        vrc = VERR_NO_MEMORY;
     738    }
     739
     740    if (RT_SUCCESS(vrc))
     741        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
     742
     743    LogFlowFuncLeaveRC(vrc);
     744    return vrc;
     745}
     746
     747inline bool GuestSession::directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir)
     748{
     749    SessionDirectories::const_iterator it = mData.mDirectories.find(uDirID);
     750    if (it != mData.mDirectories.end())
     751    {
     752        if (pDir)
     753            *pDir = it->second;
     754        return true;
     755    }
     756    return false;
     757}
     758
     759int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
     760{
     761    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
     762
     763    int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
     764    if (RT_SUCCESS(vrc))
     765    {
     766        vrc = objData.mType == FsObjType_Directory
     767            ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
     768    }
     769
     770    LogFlowFuncLeaveRC(vrc);
     771    return vrc;
     772}
     773
    704774int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory)
    705775{
     
    709779         itDirs != mData.mDirectories.end(); ++itDirs)
    710780    {
    711         if (pDirectory == (*itDirs))
     781        if (pDirectory == itDirs->second)
    712782        {
    713783            Bstr strName;
    714             HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());
     784            HRESULT hr = itDirs->second->COMGETTER(DirectoryName)(strName.asOutParam());
    715785            ComAssertComRC(hr);
    716786
     
    727797}
    728798
    729 int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc)
    730 {
    731     /* pGuestRc is optional. */
    732 
    733     LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
    734                      strPath.c_str(), uMode, uFlags));
    735 
    736     GuestProcessStartupInfo procInfo;
    737     procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
    738     procInfo.mFlags   = ProcessCreateFlag_Hidden;
    739 
    740     int vrc = VINF_SUCCESS;
    741 
    742     /* Construct arguments. */
    743     if (uFlags & DirectoryCreateFlag_Parents)
    744         procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
    745     if (uMode)
    746     {
    747         procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
    748 
    749         char szMode[16];
    750         if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
    751         {
    752             procInfo.mArguments.push_back(Utf8Str(szMode));
    753         }
    754         else
    755             vrc = VERR_BUFFER_OVERFLOW;
    756     }
    757     procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
    758 
     799int GuestSession::directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags,
     800                                          int *pGuestRc)
     801{
     802    AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     803
     804    LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
     805
     806    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     807
     808    GuestWaitEvent *pEvent = NULL;
     809    int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     810                                &pEvent);
     811    if (RT_FAILURE(vrc))
     812        return vrc;
     813
     814    /* Prepare HGCM call. */
     815    VBOXHGCMSVCPARM paParms[8];
     816    int i = 0;
     817    paParms[i++].setUInt32(pEvent->ContextID());
     818    paParms[i++].setPointer((void*)strPath.c_str(),
     819                            (ULONG)strPath.length() + 1);
     820    paParms[i++].setUInt32(uFlags);
     821
     822    alock.release(); /* Drop write lock before sending. */
     823
     824    vrc = sendCommand(HOST_DIR_REMOVE, i, paParms);
    759825    if (RT_SUCCESS(vrc))
    760826    {
    761         int guestRc;
    762         GuestProcessTool procTool;
    763         vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
    764         if (RT_SUCCESS(vrc))
    765         {
    766             if (RT_SUCCESS(guestRc))
    767                 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    768         }
    769 
    770         if (RT_SUCCESS(vrc))
    771         {
    772             if (RT_SUCCESS(guestRc))
    773                 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    774         }
    775 
     827        vrc = pEvent->Wait(30 * 1000);
    776828        if (   vrc == VERR_GSTCTL_GUEST_ERROR
    777829            && pGuestRc)
    778         {
    779             *pGuestRc = guestRc;
    780         }
    781     }
     830            *pGuestRc = pEvent->GuestResult();
     831    }
     832
     833    unregisterWaitEvent(pEvent);
    782834
    783835    LogFlowFuncLeaveRC(vrc);
     
    785837}
    786838
    787 int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
    788 {
    789     LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    790 
    791     int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
    792     if (RT_SUCCESS(vrc))
    793     {
    794         vrc = objData.mType == FsObjType_Directory
    795             ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
    796     }
    797 
    798     LogFlowFuncLeaveRC(vrc);
    799     return vrc;
    800 }
    801 
    802839int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
    803840                                           bool fDirectory, const Utf8Str &strName, int *pGuestRc)
    804841{
     842    LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool, strName=%s\n",
     843                     strTemplate.c_str(), strPath.c_str(), fDirectory, strName.c_str()));
     844
     845    int vrc = VINF_SUCCESS;
     846
    805847    GuestProcessStartupInfo procInfo;
    806848    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
    807849    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    808     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    809     if (fDirectory)
    810         procInfo.mArguments.push_back(Utf8Str("-d"));
    811     if (strPath.length()) /* Otherwise use /tmp or equivalent. */
    812     {
    813         procInfo.mArguments.push_back(Utf8Str("-t"));
    814         procInfo.mArguments.push_back(strPath);
    815     }
    816     procInfo.mArguments.push_back(strTemplate);
    817 
    818     GuestProcessTool procTool; int guestRc;
    819     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     850
     851    try
     852    {
     853        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     854        if (fDirectory)
     855            procInfo.mArguments.push_back(Utf8Str("-d"));
     856        if (strPath.length()) /* Otherwise use /tmp or equivalent. */
     857        {
     858            procInfo.mArguments.push_back(Utf8Str("-t"));
     859            procInfo.mArguments.push_back(strPath);
     860        }
     861        procInfo.mArguments.push_back(strTemplate);
     862    }
     863    catch (std::bad_alloc)
     864    {
     865        vrc = VERR_NO_MEMORY;
     866    }
     867
    820868    if (RT_SUCCESS(vrc))
    821     {
    822         if (RT_SUCCESS(guestRc))
    823             vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    824     }
    825 
    826     if (RT_SUCCESS(vrc))
    827     {
    828         if (RT_SUCCESS(guestRc))
    829             guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    830     }
    831 
    832     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    833         && pGuestRc)
    834     {
    835         *pGuestRc = guestRc;
    836     }
     869        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
    837870
    838871    LogFlowFuncLeaveRC(vrc);
     
    840873}
    841874
    842 int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,
    843                                         uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
     875int GuestSession::directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo,
     876                                        ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
    844877{
    845878    LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
    846                      strPath.c_str(), strFilter.c_str(), uFlags));
     879                     openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
    847880
    848881    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     882
     883    int rc = VERR_MAX_PROCS_REACHED;
     884    if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
     885        return rc;
     886
     887    /* Create a new (host-based) directory ID and assign it. */
     888    uint32_t uNewDirID = 0;
     889    ULONG uTries = 0;
     890
     891    for (;;)
     892    {
     893        /* Is the directory ID already used? */
     894        if (!directoryExists(uNewDirID, NULL /* pDirectory */))
     895        {
     896            /* Callback with context ID was not found. This means
     897             * we can use this context ID for our new callback we want
     898             * to add below. */
     899            rc = VINF_SUCCESS;
     900            break;
     901        }
     902        uNewDirID++;
     903        if (uNewDirID == VBOX_GUESTCTRL_MAX_OBJECTS)
     904            uNewDirID = 0;
     905
     906        if (++uTries == UINT32_MAX)
     907            break; /* Don't try too hard. */
     908    }
     909
     910    if (RT_FAILURE(rc))
     911        return rc;
    849912
    850913    /* Create the directory object. */
     
    853916        return VERR_COM_UNEXPECTED;
    854917
    855     int vrc = pDirectory->init(this /* Parent */,
    856                                strPath, strFilter, uFlags);
     918    Console *pConsole = mParent->getConsole();
     919    AssertPtr(pConsole);
     920
     921    int vrc = pDirectory->init(pConsole, this /* Parent */,
     922                               uNewDirID, openInfo);
    857923    if (RT_FAILURE(vrc))
    858924        return vrc;
    859925
    860     /* Add the created directory to our vector. */
    861     mData.mDirectories.push_back(pDirectory);
    862 
    863     LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
    864                  strPath.c_str(), mData.mSession.mID));
     926    /*
     927     * Since this is a synchronous guest call we have to
     928     * register the file object first, releasing the session's
     929     * lock and then proceed with the actual opening command
     930     * -- otherwise the file's opening callback would hang
     931     * because the session's lock still is in place.
     932     */
     933    try
     934    {
     935        /* Add the created directory to our map. */
     936        mData.mDirectories[uNewDirID] = pDirectory;
     937        mData.mNumObjects++;
     938        Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
     939
     940        LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %ld dirs, %ld objects)\n",
     941                     openInfo.mPath.c_str(), mData.mSession.mID, mData.mFiles.size(), mData.mNumObjects));
     942
     943        alock.release(); /* Release lock before firing off event. */
     944
     945        /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */
     946    }
     947    catch (std::bad_alloc &)
     948    {
     949        rc = VERR_NO_MEMORY;
     950    }
     951
     952    if (RT_SUCCESS(rc))
     953    {
     954        /* Nothing further to do here yet. */
     955        if (pGuestRc)
     956            *pGuestRc = VINF_SUCCESS;
     957    }
    865958
    866959    LogFlowFuncLeaveRC(vrc);
    867960    return vrc;
     961}
     962
     963int GuestSession::dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     964{
     965    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     966
     967    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     968    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     969
     970    if (pSvcCb->mParms < 3)
     971        return VERR_INVALID_PARAMETER;
     972
     973    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     974
     975    uint32_t uDirID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
     976#ifdef DEBUG
     977    LogFlowFunc(("uDirID=%RU32 (%RU32 total)\n",
     978                 uDirID, mData.mFiles.size()));
     979#endif
     980    int rc;
     981    SessionDirectories::const_iterator itDir
     982        = mData.mDirectories.find(uDirID);
     983    if (itDir != mData.mDirectories.end())
     984    {
     985        ComObjPtr<GuestDirectory> pDirectory(itDir->second);
     986        Assert(!pDirectory.isNull());
     987
     988        alock.release();
     989
     990        rc = pDirectory->callbackDispatcher(pCtxCb, pSvcCb);
     991    }
     992    else
     993        rc = VERR_NOT_FOUND;
     994
     995    LogFlowFuncLeaveRC(rc);
     996    return rc;
    868997}
    869998
     
    9011030}
    9021031
     1032int GuestSession::dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     1033{
     1034    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     1035
     1036    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     1037    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     1038
     1039    int rc;
     1040    uint32_t uObjectID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
     1041
     1042    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1043
     1044    /* Since we don't know which type the object is, we need to through all
     1045     * all objects. */
     1046    /** @todo Speed this up by adding an object type to the callback context! */
     1047    SessionProcesses::const_iterator itProc = mData.mProcesses.find(uObjectID);
     1048    if (itProc == mData.mProcesses.end())
     1049    {
     1050        SessionFiles::const_iterator itFile = mData.mFiles.find(uObjectID);
     1051        if (itFile != mData.mFiles.end())
     1052        {
     1053            alock.release();
     1054
     1055            rc = dispatchToFile(pCtxCb, pSvcCb);
     1056        }
     1057        else
     1058        {
     1059            SessionDirectories::const_iterator itDir = mData.mDirectories.find(uObjectID);
     1060            if (itDir != mData.mDirectories.end())
     1061            {
     1062                alock.release();
     1063
     1064                rc = dispatchToDirectory(pCtxCb, pSvcCb);
     1065            }
     1066            else
     1067                rc = VERR_NOT_FOUND;
     1068        }
     1069    }
     1070    else
     1071    {
     1072        alock.release();
     1073
     1074        rc = dispatchToProcess(pCtxCb, pSvcCb);
     1075    }
     1076
     1077    LogFlowFuncLeaveRC(rc);
     1078    return rc;
     1079}
     1080
    9031081int GuestSession::dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
    9041082{
     
    9491127#endif
    9501128
    951     int rc = VINF_SUCCESS;
     1129    int rc;
    9521130    switch (pCbCtx->uFunction)
    9531131    {
     
    9561134            break;
    9571135
    958         case GUEST_SESSION_NOTIFY:
     1136        case GUEST_SESSION_NOTIFY: /* Guest Additions >= 4.3.0. */
    9591137        {
    9601138            rc = onSessionStatusChange(pCbCtx, pSvcCb);
     
    10241202int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc)
    10251203{
     1204    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
     1205
     1206    int vrc = VINF_SUCCESS;
     1207
    10261208    GuestProcessStartupInfo procInfo;
    10271209    GuestProcessStream      streamOut;
     
    10291211    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM);
    10301212    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    1031     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    1032     procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
    1033 
    1034     GuestProcessTool procTool; int guestRc;
    1035     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     1213
     1214    try
     1215    {
     1216        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1217        procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
     1218    }
     1219    catch (std::bad_alloc)
     1220    {
     1221        vrc = VERR_NO_MEMORY;
     1222    }
     1223
    10361224    if (RT_SUCCESS(vrc))
    1037         vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    1038 
    1039     if (RT_SUCCESS(vrc))
    1040     {
    1041         if (RT_SUCCESS(guestRc))
    1042             guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    1043     }
    1044 
    1045     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    1046         && pGuestRc)
    1047     {
    1048         *pGuestRc = guestRc;
    1049     }
     1225        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
    10501226
    10511227    LogFlowFuncLeaveRC(vrc);
     
    10531229}
    10541230
    1055 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc)
     1231int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo,
     1232                                   ComObjPtr<GuestFile> &pFile, int *pGuestRc)
    10561233{
    10571234    LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n",
     
    10801257    {
    10811258        /* Is the file ID already used? */
    1082         if (!fileExists(uNewFileID, NULL /* pProgress */))
     1259        if (!fileExists(uNewFileID, NULL /* pFile */))
    10831260        {
    10841261            /* Callback with context ID was not found. This means
     
    11851362    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    11861363
     1364    int vrc = VINF_SUCCESS;
     1365
    11871366    /** @todo Merge this with IGuestFile::queryInfo(). */
    11881367    GuestProcessStartupInfo procInfo;
     
    11901369    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    11911370
    1192     /* Construct arguments. */
    1193     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    1194     procInfo.mArguments.push_back(strPath);
    1195 
    1196     GuestProcessTool procTool; int guestRc;
    1197     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     1371    try
     1372    {
     1373        /* Construct arguments. */
     1374        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1375        procInfo.mArguments.push_back(strPath);
     1376    }
     1377    catch (std::bad_alloc)
     1378    {
     1379        vrc = VERR_NO_MEMORY;
     1380    }
     1381
     1382    int guestRc; GuestCtrlStreamObjects stdOut;
    11981383    if (RT_SUCCESS(vrc))
    1199         vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    1200     if (RT_SUCCESS(vrc))
    1201     {
    1202         guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    1203         if (RT_SUCCESS(guestRc))
    1204         {
    1205             GuestProcessStreamBlock curBlock;
    1206             vrc = procTool.GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT,  curBlock);
    1207             /** @todo Check for more / validate blocks! */
    1208             if (RT_SUCCESS(vrc))
    1209                 vrc = objData.FromStat(curBlock);
    1210         }
    1211     }
    1212 
    1213     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    1214         && pGuestRc)
    1215     {
    1216         *pGuestRc = guestRc;
     1384        vrc = GuestProcessTool::RunEx(this, procInfo,
     1385                                      &stdOut, 1 /* cStrmOutObjects */,
     1386                                      &guestRc);
     1387    if (   RT_SUCCESS(vrc)
     1388        && RT_SUCCESS(guestRc))
     1389    {
     1390        if (!stdOut.empty())
     1391            vrc = objData.FromStat(stdOut.at(0));
     1392        else
     1393            vrc = VERR_NO_DATA;
    12171394    }
    12181395
     
    14031580    /* Set current session status. */
    14041581    mData.mStatus = GuestSessionStatus_Starting;
     1582    mData.mRC = VINF_SUCCESS; /* Clear previous error, if any. */
    14051583
    14061584    int vrc;
    14071585
    14081586    GuestWaitEvent *pEvent = NULL;
    1409     std::list < VBoxEventType_T > eventTypes;
     1587    GuestEventTypes eventTypes;
    14101588    try
    14111589    {
     
    14401618    vrc = sendCommand(HOST_SESSION_CREATE, i, paParms);
    14411619    if (RT_SUCCESS(vrc))
     1620    {
    14421621        vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start,
    14431622                                  30 * 1000 /* 30s timeout */,
    14441623                                  NULL /* Session status */, pGuestRc);
     1624    }
     1625    else
     1626    {
     1627        /*
     1628         * Unable to start guest session - update its current state.
     1629         * Since there is no (official API) way to recover a failed guest session
     1630         * this also marks the end state. Internally just calling this
     1631         * same function again will work though.
     1632         */
     1633        mData.mStatus = GuestSessionStatus_Error;
     1634        mData.mRC = vrc;
     1635    }
    14451636
    14461637    unregisterWaitEvent(pEvent);
     
    14981689    int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */);
    14991690    /* Nothing to do here anymore. */
     1691
     1692    LogFlowFuncLeaveRC(vrc);
     1693    return vrc;
     1694}
     1695
     1696int GuestSession::pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest,
     1697                                     uint32_t uFlags, int *pGuestRc)
     1698{
     1699    AssertReturn(!(uFlags & ~PATHRENAME_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     1700
     1701    LogFlowThisFunc(("strSource=%s, strDest=%s, uFlags=0x%x\n",
     1702                     strSource.c_str(), strDest.c_str(), uFlags));
     1703
     1704    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1705
     1706    GuestWaitEvent *pEvent = NULL;
     1707    int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     1708                                &pEvent);
     1709    if (RT_FAILURE(vrc))
     1710        return vrc;
     1711
     1712    /* Prepare HGCM call. */
     1713    VBOXHGCMSVCPARM paParms[8];
     1714    int i = 0;
     1715    paParms[i++].setUInt32(pEvent->ContextID());
     1716    paParms[i++].setPointer((void*)strSource.c_str(),
     1717                            (ULONG)strSource.length() + 1);
     1718    paParms[i++].setPointer((void*)strDest.c_str(),
     1719                            (ULONG)strDest.length() + 1);
     1720    paParms[i++].setUInt32(uFlags);
     1721
     1722    alock.release(); /* Drop write lock before sending. */
     1723
     1724    vrc = sendCommand(HOST_PATH_RENAME, i, paParms);
     1725    if (RT_SUCCESS(vrc))
     1726    {
     1727        vrc = pEvent->Wait(30 * 1000);
     1728        if (   vrc == VERR_GSTCTL_GUEST_ERROR
     1729            && pGuestRc)
     1730            *pGuestRc = pEvent->GuestResult();
     1731    }
     1732
     1733    unregisterWaitEvent(pEvent);
    15001734
    15011735    LogFlowFuncLeaveRC(vrc);
     
    16251859    {
    16261860        /* Is the context ID already used? */
    1627         if (!processExists(uNewProcessID, NULL /* pProgress */))
     1861        if (!processExists(uNewProcessID, NULL /* pProcess */))
    16281862        {
    16291863            /* Callback with context ID was not found. This means
     
    19882222
    19892223    GuestWaitEvent *pEvent = NULL;
    1990     std::list < VBoxEventType_T > eventTypes;
     2224    GuestEventTypes eventTypes;
    19912225    try
    19922226    {
     
    21102344    /* Remove ourselves from the session list. */
    21112345    int rc2 = mParent->sessionRemove(this);
     2346    if (rc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */
     2347        rc2 = VINF_SUCCESS;
     2348
    21122349    if (RT_SUCCESS(rc))
    21132350        rc = rc2;
     
    24182655    HRESULT hr = S_OK;
    24192656
    2420     ComObjPtr <GuestDirectory> pDirectory;
    2421     int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
     2657    GuestDirectoryOpenInfo openInfo;
     2658    openInfo.mPath = Utf8Str(aPath);
     2659    openInfo.mFilter = Utf8Str(aFilter);
     2660    openInfo.mFlags = fFlags;
     2661
     2662    ComObjPtr <GuestDirectory> pDirectory; int guestRc;
     2663    int rc = directoryOpenInternal(openInfo, pDirectory, &guestRc);
    24222664    if (RT_SUCCESS(rc))
    24232665    {
     
    24332675                                                   Utf8Str(aPath).c_str()));
    24342676               break;
     2677
     2678            case VERR_GSTCTL_GUEST_ERROR:
     2679                hr = GuestDirectory::setErrorExternal(this, guestRc);
     2680                break;
    24352681
    24362682            default:
     
    25112757    LogFlowThisFuncEnter();
    25122758
    2513     AutoCaller autoCaller(this);
    2514     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2515 
    2516     ReturnComNotImplemented();
     2759    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
     2760        return setError(E_INVALIDARG, tr("No directory to remove specified"));
     2761
     2762    AutoCaller autoCaller(this);
     2763    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2764
     2765    HRESULT hr = isReadyExternal();
     2766    if (FAILED(hr))
     2767        return hr;
     2768
     2769    /* No flags; only remove the directory when empty. */
     2770    uint32_t uFlags = 0;
     2771
     2772    int guestRc;
     2773    int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
     2774    if (RT_FAILURE(vrc))
     2775    {
     2776        switch (vrc)
     2777        {
     2778            case VERR_NOT_SUPPORTED:
     2779                hr = setError(VBOX_E_IPRT_ERROR,
     2780                              tr("Handling removing guest directories not supported by installed Guest Additions"));
     2781                break;
     2782
     2783            case VERR_GSTCTL_GUEST_ERROR:
     2784                hr = GuestDirectory::setErrorExternal(this, guestRc);
     2785                break;
     2786
     2787            default:
     2788                hr = setError(VBOX_E_IPRT_ERROR, tr("Removing guest directory \"%s\" failed: %Rrc"),
     2789                              Utf8Str(aPath).c_str(), vrc);
     2790                break;
     2791        }
     2792    }
     2793
     2794    return hr;
    25172795#endif /* VBOX_WITH_GUEST_CONTROL */
    25182796}
     
    25252803    LogFlowThisFuncEnter();
    25262804
    2527     AutoCaller autoCaller(this);
    2528     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2529 
    2530     ReturnComNotImplemented();
     2805    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
     2806        return setError(E_INVALIDARG, tr("No directory to remove recursively specified"));
     2807
     2808    AutoCaller autoCaller(this);
     2809    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2810
     2811    HRESULT hr = isReadyExternal();
     2812    if (FAILED(hr))
     2813        return hr;
     2814
     2815    ComObjPtr<Progress> pProgress;
     2816    hr = pProgress.createObject();
     2817    if (SUCCEEDED(hr))
     2818        hr = pProgress->init(static_cast<IGuestSession *>(this),
     2819                             Bstr(tr("Removing guest directory")).raw(),
     2820                             TRUE /*aCancelable*/);
     2821    if (FAILED(hr))
     2822        return hr;
     2823
     2824    /* Note: At the moment we don't supply progress information while
     2825     *       deleting a guest directory recursively. So just complete
     2826     *       the progress object right now. */
     2827     /** @todo Implement progress reporting on guest directory deletion! */
     2828    hr = pProgress->notifyComplete(S_OK);
     2829    if (FAILED(hr))
     2830        return hr;
     2831
     2832    /* Remove the directory + all its contents. */
     2833    uint32_t uFlags = DIRREMOVE_FLAG_RECURSIVE
     2834                    | DIRREMOVE_FLAG_CONTENT_AND_DIR;
     2835    int guestRc;
     2836    int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
     2837    if (RT_FAILURE(vrc))
     2838    {
     2839        switch (vrc)
     2840        {
     2841            case VERR_NOT_SUPPORTED:
     2842                hr = setError(VBOX_E_IPRT_ERROR,
     2843                              tr("Handling removing guest directories recursively not supported by installed Guest Additions"));
     2844                break;
     2845
     2846            case VERR_GSTCTL_GUEST_ERROR:
     2847                hr = GuestFile::setErrorExternal(this, guestRc);
     2848                break;
     2849
     2850            default:
     2851                hr = setError(VBOX_E_IPRT_ERROR, tr("Recursively removing guest directory \"%s\" failed: %Rrc"),
     2852                              Utf8Str(aPath).c_str(), vrc);
     2853                break;
     2854        }
     2855    }
     2856    else
     2857    {
     2858        pProgress.queryInterfaceTo(aProgress);
     2859    }
     2860
     2861    return hr;
    25312862#endif /* VBOX_WITH_GUEST_CONTROL */
    25322863}
     
    25392870    LogFlowThisFuncEnter();
    25402871
    2541     AutoCaller autoCaller(this);
    2542     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2543 
    2544     ReturnComNotImplemented();
     2872    if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
     2873        return setError(E_INVALIDARG, tr("No source directory to rename specified"));
     2874
     2875    if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
     2876        return setError(E_INVALIDARG, tr("No destination directory to rename the source to specified"));
     2877
     2878    AutoCaller autoCaller(this);
     2879    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2880
     2881    HRESULT hr = isReadyExternal();
     2882    if (FAILED(hr))
     2883        return hr;
     2884
     2885    /* No flags; only remove the directory when empty. */
     2886    uint32_t uFlags = 0;
     2887
     2888    int guestRc;
     2889    int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
     2890    if (RT_FAILURE(vrc))
     2891    {
     2892        switch (vrc)
     2893        {
     2894            case VERR_NOT_SUPPORTED:
     2895                hr = setError(VBOX_E_IPRT_ERROR,
     2896                              tr("Handling renaming guest directories not supported by installed Guest Additions"));
     2897                break;
     2898
     2899            case VERR_GSTCTL_GUEST_ERROR:
     2900                hr = setError(VBOX_E_IPRT_ERROR,
     2901                              tr("Renaming guest directory failed: %Rrc"), guestRc);
     2902                break;
     2903
     2904            default:
     2905                hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest directory \"%s\" failed: %Rrc"),
     2906                              Utf8Str(aSource).c_str(), vrc);
     2907                break;
     2908        }
     2909    }
     2910
     2911    return hr;
    25452912#endif /* VBOX_WITH_GUEST_CONTROL */
    25462913}
     
    29303297    LogFlowThisFuncEnter();
    29313298
    2932     AutoCaller autoCaller(this);
    2933     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2934 
    2935     ReturnComNotImplemented();
     3299    if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
     3300        return setError(E_INVALIDARG, tr("No source file to rename specified"));
     3301
     3302    if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
     3303        return setError(E_INVALIDARG, tr("No destination file to rename the source to specified"));
     3304
     3305    AutoCaller autoCaller(this);
     3306    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     3307
     3308    HRESULT hr = isReadyExternal();
     3309    if (FAILED(hr))
     3310        return hr;
     3311
     3312    /* No flags; only remove the directory when empty. */
     3313    uint32_t uFlags = 0;
     3314
     3315    int guestRc;
     3316    int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
     3317    if (RT_FAILURE(vrc))
     3318    {
     3319        switch (vrc)
     3320        {
     3321            case VERR_NOT_SUPPORTED:
     3322                hr = setError(VBOX_E_IPRT_ERROR,
     3323                              tr("Handling renaming guest files not supported by installed Guest Additions"));
     3324                break;
     3325
     3326            case VERR_GSTCTL_GUEST_ERROR:
     3327                /** @todo Proper guestRc to text translation needed. */
     3328                hr = setError(VBOX_E_IPRT_ERROR,
     3329                              tr("Renaming guest file failed: %Rrc"), guestRc);
     3330                break;
     3331
     3332            default:
     3333                hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest file \"%s\" failed: %Rrc"),
     3334                              Utf8Str(aSource).c_str(), vrc);
     3335                break;
     3336        }
     3337    }
     3338
     3339    return hr;
    29363340#endif /* VBOX_WITH_GUEST_CONTROL */
    29373341}
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r47905 r49349  
    627627        {
    628628            GuestProcessStartupInfo procInfo;
    629             procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
    630                                                             mSource.c_str(), mDest.c_str(), objData.mObjectSize);
     629            procInfo.mName      = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
     630                                                              mSource.c_str(), mDest.c_str(), objData.mObjectSize);
    631631            procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_CAT);
    632632            procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette