Changeset 49349 in vbox
- Timestamp:
- Oct 31, 2013 4:40:46 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 90367
- Location:
- trunk
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/en_US/user_VBoxManage.xml
r49313 r49349 3162 3162 3163 3163 <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 <uuid|vmname> removedir[ectory]|rmdir 3169 <guest directory>... --username <name> 3170 [--passwordfile <file> | --password <password>] 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 <name></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 <file></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 <password></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 <uuid|vmname> removefile|rm 3246 <guest file>... --username <name> 3247 [--passwordfile <file> | --password <password>] 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 <name></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 <file></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 <password></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 <uuid|vmname> ren[ame]|mv 3315 <source>... <dest> --username <name> 3316 [--passwordfile <file> | --password <password>] 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 <name></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 <file></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 <password></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> 3164 3392 <para><emphasis role="bold"><computeroutput>createtemporary</computeroutput></emphasis>, 3165 3393 which allows -
trunk/include/VBox/HostServices/GuestControlSvc.h
r47817 r49349 121 121 122 122 /** 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 /** 123 136 * Guest process creation flags. 124 137 * Note: Has to match Main's ProcessCreateFlag_* flags! … … 140 153 #define OUTPUT_HANDLE_ID_STDOUT 1 141 154 #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) 142 169 143 170 /** … … 203 230 : mParms(cParms), mpaParms(paParms) { } 204 231 232 /** Number of HGCM parameters. */ 205 233 uint32_t mParms; 234 /** Actual HGCM parameters. */ 206 235 PVBOXHGCMSVCPARM mpaParms; 207 236 … … 284 313 * Gets the current file position of an opened guest file. 285 314 */ 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 287 324 }; 288 325 … … 290 327 * The service functions which are called by guest. The numbers may not change, 291 328 * so we hardcode them. 292 *293 * Note: Callbacks start at 100. See CALLBACKTYPE enum.294 329 */ 295 330 enum eGuestFn … … 328 363 GUEST_MSG_SKIP = 10, 329 364 /** 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 /** 330 375 * Guest reports back a guest session status. 331 376 */ 332 377 GUEST_SESSION_NOTIFY = 20, 378 /** 379 * Guest wants to close a specific guest session. 380 */ 381 GUEST_SESSION_CLOSE = 21, 333 382 /** 334 383 * Guests sends output from an executed process. … … 350 399 */ 351 400 GUEST_EXEC_IO_NOTIFY = 210, 401 /** 402 * Guest notifies the host about some directory event. 403 */ 404 GUEST_DIR_NOTIFY = 230, 352 405 /** 353 406 * Guest notifies the host about some file event. … … 382 435 383 436 /** 437 * Guest directory notification types. 438 * @sa HGCMMsgDirNotify. 439 */ 440 enum 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 /** 384 458 * Guest file notification types. 385 459 * @sa HGCMMsgFileNotify. … … 421 495 { 422 496 VBoxGuestHGCMCallInfo hdr; 423 424 497 /** 425 498 * The returned command the host wants to … … 429 502 /** Number of parameters the message needs. */ 430 503 HGCMFunctionParameter num_parms; /* OUT uint32_t */ 431 432 504 } HGCMMsgCmdWaitFor; 433 505 … … 441 513 { 442 514 VBoxGuestHGCMCallInfo hdr; 443 444 515 /** Value to filter for after filter mask 445 516 * was applied. */ … … 451 522 /** Filter flags; currently unused. */ 452 523 HGCMFunctionParameter flags; /* IN uint32_t */ 453 454 524 } HGCMMsgCmdFilterSet; 455 525 … … 461 531 { 462 532 VBoxGuestHGCMCallInfo hdr; 463 464 533 /** Unset flags; currently unused. */ 465 534 HGCMFunctionParameter flags; /* IN uint32_t */ … … 474 543 { 475 544 VBoxGuestHGCMCallInfo hdr; 476 477 545 /** Skip flags; currently unused. */ 478 546 HGCMFunctionParameter flags; /* IN uint32_t */ … … 487 555 VBoxGuestHGCMCallInfo hdr; 488 556 } HGCMMsgCancelPendingWaits; 557 558 typedef 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; 489 570 490 571 /** … … 534 615 HGCMFunctionParameter result; 535 616 } HGCMMsgSessionNotify; 617 618 typedef 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; 536 630 537 631 /** … … 575 669 struct 576 670 { 577 /** Timeout (in ms ec) which either specifies the671 /** Timeout (in ms) which either specifies the 578 672 * overall lifetime of the process or how long it 579 673 * can take to bring the process up and running - … … 588 682 } v2; 589 683 } u; 590 591 684 } HGCMMsgProcExec; 592 685 … … 607 700 /** Actual size of data (in bytes). */ 608 701 HGCMFunctionParameter size; 609 610 702 } HGCMMsgProcInput; 611 703 … … 627 719 /** Data buffer. */ 628 720 HGCMFunctionParameter data; 629 630 721 } HGCMMsgProcOutput; 631 722 … … 646 737 /** Optional data buffer (not used atm). */ 647 738 HGCMFunctionParameter data; 648 649 739 } HGCMMsgProcStatus; 650 740 … … 665 755 /** Data written. */ 666 756 HGCMFunctionParameter written; 667 668 757 } HGCMMsgProcStatusInput; 669 758 … … 682 771 /** The process ID (PID). */ 683 772 HGCMFunctionParameter pid; 684 685 773 } HGCMMsgProcTerminate; 686 774 … … 699 787 /** Timeout (in ms). */ 700 788 HGCMFunctionParameter timeout; 701 702 789 } HGCMMsgProcWaitFor; 790 791 typedef 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; 703 801 704 802 /** … … 722 820 /** UInt64: Initial offset. */ 723 821 HGCMFunctionParameter offset; 724 725 822 } HGCMMsgFileOpen; 726 823 … … 735 832 /** File handle to close. */ 736 833 HGCMFunctionParameter handle; 737 738 834 } HGCMMsgFileClose; 739 835 … … 750 846 /** Size (in bytes) to read. */ 751 847 HGCMFunctionParameter size; 752 753 848 } HGCMMsgFileRead; 754 849 … … 767 862 /** Actual size of data (in bytes). */ 768 863 HGCMFunctionParameter size; 769 770 864 } HGCMMsgFileReadAt; 771 865 … … 784 878 /** Data buffer to write to the file. */ 785 879 HGCMFunctionParameter data; 786 787 880 } HGCMMsgFileWrite; 788 881 … … 803 896 /** Data buffer to write to the file. */ 804 897 HGCMFunctionParameter data; 805 806 898 } HGCMMsgFileWriteAt; 807 899 … … 820 912 /** The seeking offset. */ 821 913 HGCMFunctionParameter offset; 822 823 914 } HGCMMsgFileSeek; 824 915 … … 833 924 /** File handle to get the current position for. */ 834 925 HGCMFunctionParameter handle; 835 836 926 } HGCMMsgFileTell; 837 927 … … 877 967 } tell; 878 968 } u; 879 880 969 } HGCMReplyFileNotify; 970 971 typedef 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; 881 1001 882 1002 #pragma pack () … … 908 1028 CALLBACKDATA_HEADER hdr; 909 1029 } CALLBACKDATA_CLIENT_DISCONNECTED, *PCALLBACKDATA_CLIENT_DISCONNECTED; 1030 1031 typedef 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; 910 1044 911 1045 typedef struct CALLBACKDATA_SESSION_NOTIFY … … 966 1100 967 1101 /** 968 * General guest filenotification callback.969 */ 970 typedef struct CALLBACKDATA_ FILE_NOTIFY1102 * General guest directory notification callback. 1103 */ 1104 typedef struct CALLBACKDATA_DIR_NOTIFY 971 1105 { 972 1106 /** Callback data header. */ … … 980 1114 struct 981 1115 { 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 */ 1144 typedef 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 { 982 1156 /** Guest file handle. */ 983 1157 uint32_t uHandle; -
trunk/include/VBox/VBoxGuestLib.h
r47817 r49349 612 612 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove); 613 613 VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterUnset(uint32_t uClientId); 614 VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc); 615 VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType, void *pvPayload, uint32_t cbPayload); 616 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t uClientId); 614 617 VBGLR3DECL(int) VbglR3GuestCtrlMsgWaitFor(uint32_t uClientId, uint32_t *puMsg, uint32_t *puNumParms); 615 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t uClientId);616 618 VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t u32ClientId); 617 619 /* Guest session handling. */ 620 VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uFlags); 618 621 VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, uint32_t uResult); 619 622 VBGLR3DECL(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); 620 623 VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puFlags, uint32_t *puSessionID); 624 /* Guest path handling. */ 625 VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszSource, uint32_t cbSource, char *pszDest, uint32_t cbDest, uint32_t *puFlags); 621 626 /* Guest process execution. */ 622 627 VBGLR3DECL(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); … … 625 630 VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puHandle, uint32_t *puFlags); 626 631 VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS); 632 /* Guest native directory handling. */ 633 VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *puFlags); 627 634 /* Guest native file handling. */ 628 635 VBGLR3DECL(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 188 188 189 189 190 VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx, 191 int rc) 192 { 193 return VbglR3GuestCtrlMsgReplyEx(pCtx, rc, 0 /* uType */, 194 NULL /* pvPayload */, 0 /* cbPayload */); 195 } 196 197 198 VBGLR3DECL(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 190 228 /** 191 229 * Tells the host service to skip the current message returned by … … 237 275 rc = rc2; 238 276 } 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 */ 288 VBGLR3DECL(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 239 311 return rc; 240 312 } … … 374 446 375 447 448 VBGLR3DECL(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 376 492 /** 377 493 * Allocates and gets host data, based on the message id. … … 383 499 ** @todo Move the parameters in an own struct! 384 500 */ 385 VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx,501 VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, 386 502 char *pszCmd, uint32_t cbCmd, 387 503 uint32_t *puFlags, … … 578 694 579 695 696 VBGLR3DECL(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 580 736 VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, 581 737 char *pszFileName, uint32_t cbFileName, -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r46506 r49349 216 216 /** 217 217 * Creates the default release logger outputting to the specified file. 218 * Pass NULL for disabled logging. 218 219 * 219 220 * @return IPRT status code. … … 222 223 int VBoxServiceLogCreate(const char *pszLogFile) 223 224 { 225 if (!pszLogFile) /* No logging wanted? Take a shortcut. */ 226 return VINF_SUCCESS; 227 224 228 /* Create release logger (stdout + file). */ 225 229 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r47817 r49349 268 268 * The global session object then acts as a host for all 269 269 * 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. 271 272 */ 272 273 if (ctxHost.uProtocol == 1) … … 407 408 408 409 /* 409 * Ask the host service to cancel all pending requests so that we can410 * 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. 411 412 */ 412 413 if (g_uControlSvcClientID) -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
r47695 r49349 525 525 pProcess->uPID, PROC_STS_STARTED, 0 /* u32Flags */, 526 526 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); 527 530 528 531 /* … … 576 579 if (RT_FAILURE(rc2)) 577 580 VBoxServiceError("Draining IPC notification pipe failed with rc=%Rrc\n", rc2); 578 #ifdef DEBUG 581 582 /* Process all pending requests. */ 579 583 VBoxServiceVerbose(4, "[PID %RU32]: Processing pending requests ...\n", 580 584 pProcess->uPID); 581 #endif582 /* Process all pending requests. */583 585 Assert(pProcess->hReqQueue != NIL_RTREQQUEUE); 584 586 rc2 = RTReqQueueProcess(pProcess->hReqQueue, -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r49039 r49349 23 23 #include <iprt/asm.h> 24 24 #include <iprt/assert.h> 25 #include <iprt/dir.h> 25 26 #include <iprt/env.h> 26 27 #include <iprt/file.h> … … 57 58 static DECLCALLBACK(int) gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser); 58 59 /* Host -> Guest handlers. */ 60 static int gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 59 61 static int gstcntlSessionHandleFileOpen(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 60 62 static int gstcntlSessionHandleFileClose(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); … … 63 65 static int gstcntlSessionHandleFileSeek(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 64 66 static int gstcntlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 67 static int gstcntlSessionHandlePathRename(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 65 68 static int gstcntlSessionHandleProcExec(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx); 66 69 static int gstcntlSessionHandleProcInput(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf); … … 118 121 119 122 return NULL; 123 } 124 125 126 static 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; 120 196 } 121 197 … … 583 659 VBoxServiceVerbose(4, "Telling file \"%s\" (handle=%RU32) returned rc=%Rrc\n", 584 660 pFile ? pFile->szName : "<Not found>", uHandle, rc); 661 #endif 662 return rc; 663 } 664 665 666 static 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); 585 714 #endif 586 715 return rc; … … 905 1034 switch (uMsg) 906 1035 { 907 case HOST_CANCEL_PENDING_WAITS:908 VBoxServiceVerbose(1, "We were asked to quit ...\n");909 /* Fall thru is intentional. */910 1036 case HOST_SESSION_CLOSE: 911 /* Shutdown this fork. */1037 /* Shutdown (this fork). */ 912 1038 rc = GstCntlSessionClose(pSession); 913 1039 *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; 914 1046 break; 915 1047 … … 984 1116 rc = fImpersonated 985 1117 ? gstcntlSessionHandleFileTell(pSession, pHostCtx) 1118 : VERR_NOT_SUPPORTED; 1119 break; 1120 1121 case HOST_PATH_RENAME: 1122 rc = fImpersonated 1123 ? gstcntlSessionHandlePathRename(pSession, pHostCtx) 986 1124 : VERR_NOT_SUPPORTED; 987 1125 break; … … 1057 1195 if (RT_SUCCESS(rc)) 1058 1196 { 1059 uint32_t uTimeoutsMS = 5 * 60 * 1000; /** @todo Make this configurable. Later. */1197 uint32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */ 1060 1198 uint64_t u64TimeoutStart = 0; 1061 1199 … … 1080 1218 if (!u64TimeoutStart) 1081 1219 { 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); 1084 1244 u64TimeoutStart = RTTimeMilliTS(); 1245 1085 1246 continue; /* Don't waste time on waiting. */ 1086 1247 } … … 1222 1383 GUEST_SESSION_NOTIFYTYPE_STARTED, VINF_SUCCESS); 1223 1384 if (RT_FAILURE(rc2)) 1385 { 1224 1386 VBoxServiceError("Reporting session ID=%RU32 started status failed with rc=%Rrc\n", 1225 1387 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 } 1226 1396 1227 1397 /* Allocate a scratch buffer for commands which also send … … 1284 1454 RTMemFree(pvScratchBuf); 1285 1455 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 } 1288 1461 1289 1462 VBoxServiceVerbose(3, "Session worker returned with rc=%Rrc\n", rc); … … 1755 1928 } 1756 1929 #else 1930 /* Include the session thread ID in the log file name. */ 1757 1931 if (RTStrAPrintf(&pszLogNewSuffix, "-%RU32-%RU32-%s", 1758 1932 pSessionStartupInfo->uSessionID, … … 1793 1967 rc = rc2; 1794 1968 #ifdef DEBUG 1795 VBoxServiceVerbose(4, " rc=%Rrc, session flags=%x\n",1969 VBoxServiceVerbose(4, "Argv building rc=%Rrc, session flags=%x\n", 1796 1970 rc, g_Session.uFlags); 1797 1971 char szParmDumpStdOut[32]; … … 2049 2223 int rc = VINF_SUCCESS; 2050 2224 2225 /*int rc = VbglR3GuestCtrlClose 2226 if (RT_FAILURE(rc)) 2227 VBoxServiceError("Cancelling pending waits failed; rc=%Rrc\n", rc);*/ 2228 2051 2229 PVBOXSERVICECTRLSESSIONTHREAD pSessionThread 2052 2230 = RTListGetFirst(pList, VBOXSERVICECTRLSESSIONTHREAD, Node); … … 2140 2318 break; 2141 2319 2320 #ifdef DEBUG 2142 2321 case VBOXSERVICESESSIONOPT_THREAD_ID: 2143 2322 /* Not handled. */ 2144 2323 break; 2145 2324 #endif 2146 2325 /** @todo Implement help? */ 2147 2326 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r49222 r49349 141 141 142 142 PGCTLCMDCTX pCmdCtx; 143 ComPtr<IGuestSession> pGuestSession;144 143 bool fDryRun; 145 144 bool fHostToGuest; … … 282 281 enum GETOPTDEF_RMDIR 283 282 { 284 GETOPTDEF_RMDIR_RECURSIVE = 2000285 283 }; 286 284 … … 349 347 " [--domain <domain>] [--verbose]\n" 350 348 "\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" 351 354 " createtemp[orary]|mktemp\n" 352 355 " <template> --username <name>\n" … … 729 732 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 730 733 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 731 740 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 732 741 … … 780 789 pCtx->iArgc = 0; 781 790 791 int iArgIdx = 2; /* Skip VM name and guest control command */ 782 792 int ch; 783 793 RTGETOPTUNION ValueUnion; … … 785 795 RTGetOptInit(&GetState, pArg->argc, pArg->argv, 786 796 s_aOptions, RT_ELEMENTS(s_aOptions), 787 2, /* Skip VM name and guest control command */ 788 RTGETOPTINIT_FLAGS_OPTS_FIRST); 797 iArgIdx, 0); 789 798 790 799 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) … … 797 806 if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS)) 798 807 pCtx->strUsername = ValueUnion.psz; 808 iArgIdx = GetState.iNext; 799 809 break; 800 810 … … 805 815 pCtx->strPassword = ValueUnion.psz; 806 816 } 817 iArgIdx = GetState.iNext; 807 818 break; 808 819 … … 811 822 if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS)) 812 823 rcExit = readPasswordFile(ValueUnion.psz, &pCtx->strPassword); 824 iArgIdx = GetState.iNext; 813 825 break; 814 826 } … … 817 829 if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS)) 818 830 pCtx->strDomain = ValueUnion.psz; 831 iArgIdx = GetState.iNext; 819 832 break; 820 833 821 834 case 'v': /* Verbose */ 822 835 pCtx->fVerbose = true; 836 iArgIdx = GetState.iNext; 823 837 break; 824 838 825 case VINF_GETOPT_NOT_OPTION:826 /* Fall through is intentional. */827 839 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++) 828 853 { 829 Assert(GetState.iNext); 830 char *pszArg = RTStrDup(pArg->argv[GetState.iNext - 1]); 854 char *pszArg = RTStrDup(pArg->argv[i]); 831 855 if (!pszArg) 832 856 { … … 837 861 pCtx->ppaArgv[pCtx->iArgc] = pszArg; 838 862 pCtx->iArgc++; 839 break; 863 #ifdef DEBUG_andy 864 RTPrintf("\targv[%d]=%s\n", i, pArg->argv[i]); 840 865 } 841 842 } /* switch */ 866 #endif 867 iArgIdx = GetState.iNext; 868 } 869 843 870 } /* while RTGetOpt */ 844 871 } … … 1077 1104 }; 1078 1105 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 1079 1112 int ch; 1080 1113 RTGETOPTUNION ValueUnion; 1081 1114 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); 1083 1117 1084 1118 Utf8Str strCmd; … … 1174 1208 1175 1209 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); 1177 1216 break; 1178 1217 … … 1410 1449 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1411 1450 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; 1431 1468 } 1432 1469 … … 1439 1476 { 1440 1477 if (pContext) 1441 {1442 if (pContext->pGuestSession)1443 pContext->pGuestSession->Close();1444 1478 delete pContext; 1445 }1446 1479 } 1447 1480 … … 1617 1650 SafeArray<DirectoryCreateFlag_T> dirCreateFlags; 1618 1651 dirCreateFlags.push_back(DirectoryCreateFlag_Parents); 1619 HRESULT rc = pContext->p GuestSession->DirectoryCreate(Bstr(pszDir).raw(),1620 0700, ComSafeArrayAsInParam(dirCreateFlags));1652 HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryCreate(Bstr(pszDir).raw(), 1653 0700, ComSafeArrayAsInParam(dirCreateFlags)); 1621 1654 if (FAILED(rc)) 1622 vrc = ctrlPrintError(pContext->p GuestSession, COM_IIDOF(IGuestSession));1655 vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1623 1656 } 1624 1657 else /* ... or on the host. */ … … 1636 1669 * @return IPRT status code. 1637 1670 * @param pContext Pointer to current copy control context. 1638 * @param bGuesttrue if directory needs to be checked on the guest1671 * @param fOnGuest true if directory needs to be checked on the guest 1639 1672 * or false if on the host. 1640 1673 * @param pszDir Actual directory to check. … … 1642 1675 * given directory exists or not. 1643 1676 */ 1644 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest,1677 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool fOnGuest, 1645 1678 const char *pszDir, bool *fExists) 1646 1679 { … … 1650 1683 1651 1684 int vrc = VINF_SUCCESS; 1652 if ( bGuest)1685 if (fOnGuest) 1653 1686 { 1654 1687 BOOL fDirExists = FALSE; 1655 HRESULT rc = pContext->p GuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists);1688 HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists); 1656 1689 if (FAILED(rc)) 1657 vrc = ctrlPrintError(pContext->p GuestSession, COM_IIDOF(IGuestSession));1690 vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1658 1691 else 1659 1692 *fExists = fDirExists ? true : false; … … 1720 1753 { 1721 1754 BOOL fFileExists = FALSE; 1722 HRESULT rc = pContext->p GuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists);1755 HRESULT rc = pContext->pCmdCtx->pGuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists); 1723 1756 if (FAILED(rc)) 1724 vrc = ctrlPrintError(pContext->p GuestSession, COM_IIDOF(IGuestSession));1757 vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1725 1758 else 1726 1759 *fExists = fFileExists ? true : false; … … 1796 1829 { 1797 1830 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(), 1807 1832 ComSafeArrayAsInParam(copyFlags), 1808 1833 pProgress.asOutParam()); 1809 1834 } 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 } 1810 1842 1811 1843 if (FAILED(rc)) 1812 1844 { 1813 vrc = ctrlPrintError(pContext->p GuestSession, COM_IIDOF(IGuestSession));1845 vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession)); 1814 1846 } 1815 1847 else … … 2038 2070 SafeArray<DirectoryOpenFlag_T> dirOpenFlags; /* No flags supported yet. */ 2039 2071 ComPtr<IGuestDirectory> pDirectory; 2040 HRESULT rc = pContext->p GuestSession->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(),2072 HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(), 2041 2073 ComSafeArrayAsInParam(dirOpenFlags), 2042 2074 pDirectory.asOutParam()); 2043 2075 if (FAILED(rc)) 2044 return ctrlPrintError(pContext->p GuestSession, COM_IIDOF(IGuestSession));2076 return ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession)); 2045 2077 ComPtr<IFsObjInfo> dirEntry; 2046 2078 while (true) … … 2385 2417 PCOPYCONTEXT pContext = NULL; 2386 2418 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); 2388 2422 if (RT_FAILURE(vrc)) 2389 2423 { … … 2544 2578 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 2545 2579 2546 /*2547 * Parse arguments.2548 *2549 * Note! No direct returns here, everyone must go thru the cleanup at the2550 * end of this function.2551 */2552 2580 static const RTGETOPTDEF s_aOptions[] = 2553 2581 { … … 2619 2647 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 2620 2648 2621 /*2622 * Parse arguments.2623 *2624 * Note! No direct returns here, everyone must go thru the cleanup at the2625 * end of this function.2626 */2627 2649 static const RTGETOPTDEF s_aOptions[] = 2628 2650 { 2629 { "--recursive", GETOPTDEF_RMDIR_RECURSIVE,RTGETOPT_REQ_NOTHING }2651 { "--recursive", 'R', RTGETOPT_REQ_NOTHING } 2630 2652 }; 2631 2653 … … 2644 2666 switch (ch) 2645 2667 { 2646 case GETOPTDEF_RMDIR_RECURSIVE:2668 case 'R': 2647 2669 fRecursive = true; 2648 2670 break; … … 2695 2717 if (SUCCEEDED(rc)) 2696 2718 CHECK_PROGRESS_ERROR(pProgress, ("Directory deletion failed")); 2719 2720 pProgress.setNull(); 2697 2721 } 2698 2722 else … … 2714 2738 { 2715 2739 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 2716 2717 /*2718 * Parse arguments.2719 *2720 * Note! No direct returns here, everyone must go thru the cleanup at the2721 * end of this function.2722 */2723 static const RTGETOPTDEF s_aOptions[] = { 0 };2724 2740 2725 2741 int ch; … … 2727 2743 RTGETOPTSTATE GetState; 2728 2744 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); 2730 2747 2731 2748 DESTDIRMAP mapDirs; … … 2772 2789 } 2773 2790 2791 static 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 2774 2954 static DECLCALLBACK(RTEXITCODE) handleCtrlCreateTemp(PGCTLCMDCTX pCtx) 2775 2955 { 2776 2956 AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); 2777 2957 2778 /*2779 * Parse arguments.2780 *2781 * Note! No direct returns here, everyone must go thru the cleanup at the2782 * end of this function.2783 */2784 2958 static const RTGETOPTDEF s_aOptions[] = 2785 2959 { … … 3246 3420 return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a PID to close"); 3247 3421 3248 /*3249 * Parse arguments.3250 *3251 * Note! No direct returns here, everyone must go thru the cleanup at the3252 * end of this function.3253 */3254 3422 static const RTGETOPTDEF s_aOptions[] = 3255 3423 { … … 3447 3615 3448 3616 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 3457 3619 static const RTGETOPTDEF s_aOptions[] = 3458 3620 { … … 3602 3764 RTGETOPTSTATE GetState; 3603 3765 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); 3605 3767 3606 3768 while ((ch = RTGetOpt(&GetState, &ValueUnion))) … … 3717 3879 || !RTStrICmp(pArg->argv[1], "removefile")) 3718 3880 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; 3719 3885 else if ( !RTStrICmp(pArg->argv[1], "createtemporary") 3720 3886 || !RTStrICmp(pArg->argv[1], "createtemp") -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r48724 r49349 388 388 if (mParmCount > pConnection->mNumParms) 389 389 { 390 LogFlowFunc(("pHostCmd=%p requires %RU32 parms, only got %RU32 from client\n", 391 this, mParmCount, pConnection->mNumParms)); 392 390 393 /* 391 394 * So this call apparently failed because the guest wanted to peek … … 766 769 mID, rcPending, mIsPending, mPendingCon.mNumParms, mFlags)); 767 770 771 int rc; 768 772 if ( mIsPending 769 773 && mPendingCon.mNumParms >= 2) … … 776 780 777 781 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; 781 791 } 782 792 … … 1015 1025 void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1016 1026 int hostCall(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1027 int sessionClose(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 1017 1028 int uninit(void); 1018 1029 }; … … 1306 1317 1307 1318 /** 1308 * Processes a command receive ed from the host side and re-routes it to1319 * Processes a command received from the host side and re-routes it to 1309 1320 * a connect client on the guest. 1310 1321 * … … 1450 1461 LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", u32ClientID)); 1451 1462 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); 1452 1472 break; 1453 1473 … … 1522 1542 } 1523 1543 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 */ 1553 int 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 1524 1573 int Service::uninit() 1525 1574 { -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r49312 r49349 10591 10591 <desc> 10592 10592 Removes a guest directory if not empty. 10593 10594 <result name="E_NOTIMPL">10595 The method is not implemented yet.10596 </result>10597 10593 </desc> 10598 10594 <param name="path" type="wstring" dir="in"> … … 10604 10600 <desc> 10605 10601 Removes a guest directory recursively. 10606 10607 <result name="E_NOTIMPL">10608 The method is not implemented yet.10609 </result>10610 10602 </desc> 10611 10603 <param name="path" type="wstring" dir="in"> … … 10616 10608 </param> 10617 10609 <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> 10619 10612 </param> 10620 10613 </method> … … 10623 10616 <desc> 10624 10617 Renames a directory on the guest. 10625 10626 <result name="E_NOTIMPL">10627 The method is not implemented yet.10628 </result>10629 10618 </desc> 10630 10619 <param name="source" type="wstring" dir="in"> … … 10940 10929 <desc> 10941 10930 Renames a file on the guest. 10942 10943 <result name="E_NOTIMPL">10944 The method is not implemented yet.10945 </result>10946 10931 </desc> 10947 10932 <param name="source" type="wstring" dir="in"> -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r47817 r49349 101 101 102 102 std::map <Utf8Str, Utf8Str> mEnvironment; 103 }; 104 105 106 /** 107 * Structure for keeping all the relevant guest directory 108 * information around. 109 */ 110 struct GuestDirectoryOpenInfo 111 { 112 /** The directory path. */ 113 Utf8Str mPath; 114 /** Then open filter. */ 115 Utf8Str mFilter; 116 /** Opening flags. */ 117 uint32_t mFlags; 103 118 }; 104 119 … … 313 328 #endif 314 329 315 uint32_t GetOffset() ;316 317 uint32_t GetSize();330 uint32_t GetOffset() { return m_cbOffset; } 331 332 size_t GetSize() { return m_cbSize; } 318 333 319 334 int ParseBlock(GuestProcessStreamBlock &streamBlock); … … 324 339 uint32_t m_cbAllocated; 325 340 /** Currently used size of allocated internal stream buffer. */ 326 uint32_t m_cbSize;341 size_t m_cbSize; 327 342 /** Current offset within the internal stream buffer. */ 328 343 uint32_t m_cbOffset; … … 378 393 }; 379 394 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); 395 class GuestWaitEventPayload 396 { 397 398 public: 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 441 public: 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 485 protected: 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 495 class GuestWaitEventBase 496 { 497 498 protected: 499 500 GuestWaitEventBase(void); 501 virtual ~GuestWaitEventBase(void); 502 503 public: 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 512 protected: 513 514 int Init(uint32_t uCID); 396 515 397 516 protected: 398 517 399 518 /* Shutdown indicator. */ 400 bool fAborted;519 bool mfAborted; 401 520 /* Associated context ID (CID). */ 402 521 uint32_t mCID; 403 /** List of event types this event should404 * be signalled on. */405 std::list<VBoxEventType_T> mEventTypes;406 522 /** The event semaphore for triggering 407 523 * the actual event. */ 408 524 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. */ 539 typedef std::list < VBoxEventType_T > GuestEventTypes; 540 541 class GuestWaitEvent : public GuestWaitEventBase 542 { 543 544 public: 545 546 GuestWaitEvent(uint32_t uCID); 547 GuestWaitEvent(uint32_t uCID, const GuestEventTypes &lstEvents); 548 virtual ~GuestWaitEvent(void); 549 550 public: 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 558 protected: 559 560 int Init(uint32_t uCID); 561 562 protected: 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. */ 410 568 ComPtr<IEvent> mEvent; 411 569 }; 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. */ 572 typedef 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. */ 575 typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup; 414 576 415 577 class GuestBase … … 423 585 public: 424 586 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); 428 595 public: 429 596 … … 431 598 void baseUninit(void); 432 599 int cancelWaitEvents(void); 600 int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 433 601 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); 435 604 void unregisterWaitEvent(GuestWaitEvent *pEvent); 436 605 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent); … … 448 617 /** Critical section for wait events access. */ 449 618 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; 452 623 }; 453 624 … … 476 647 477 648 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); 479 650 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms); 480 651 -
trunk/src/VBox/Main/include/GuestDirectoryImpl.h
r43162 r49349 30 30 class ATL_NO_VTABLE GuestDirectory : 31 31 public VirtualBoxBase, 32 public GuestObject, 32 33 VBOX_SCRIPTABLE_IMPL(IGuestDirectory) 33 34 { … … 44 45 DECLARE_EMPTY_CTOR_DTOR(GuestDirectory) 45 46 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); 47 48 void uninit(void); 48 49 HRESULT FinalConstruct(void); … … 61 62 /** @name Public internal methods. 62 63 * @{ */ 64 int callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 65 static Utf8Str guestErrorToString(int guestRc); 66 static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc); 63 67 /** @} */ 64 68 … … 71 75 struct Data 72 76 { 73 GuestSession *mSession;74 Utf8Str mName;75 Utf8Str mFilter;76 uint32_t m Flags;77 /** The directory's open info. */ 78 GuestDirectoryOpenInfo mOpenInfo; 79 /** The directory's ID. */ 80 uint32_t mID; 77 81 GuestProcessTool mProcessTool; 78 82 } mData; -
trunk/src/VBox/Main/include/GuestProcessImpl.h
r47817 r49349 82 82 int startProcessAsync(void); 83 83 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); 85 85 ProcessWaitResult_T waitFlagsToResult(uint32_t fWaitFlags); 86 86 int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc); … … 135 135 * Guest process tool flags. 136 136 */ 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. */ 138 140 #define GUESTPROCESSTOOL_FLAG_NONE 0 139 /** Rununtil next stream block from stdout has been141 /** Wait until next stream block from stdout has been 140 142 * read in completely, then return. 141 143 */ … … 169 171 bool IsRunning(void); 170 172 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 171 178 int TerminatedOk(LONG *pExitCode); 172 179 … … 175 182 protected: 176 183 177 GuestSession *pSession;184 ComObjPtr<GuestSession> pSession; 178 185 ComObjPtr<GuestProcess> pProcess; 179 186 GuestProcessStartupInfo mStartupInfo; -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r47817 r49349 327 327 private: 328 328 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; 330 331 /** Map of guest files. The key specifies the internal file ID. */ 331 332 typedef std::map <uint32_t, ComObjPtr<GuestFile> > SessionFiles; … … 338 339 * @{ */ 339 340 int closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc); 341 inline bool directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir); 340 342 int directoryRemoveFromList(GuestDirectory *pDirectory); 343 int directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags, int *pGuestRc); 341 344 int directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc); 342 345 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); 344 347 int directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc); 348 int dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 345 349 int dispatchToFile(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 350 int dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 346 351 int dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); 347 352 int dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); … … 367 372 Guest *getParent(void) { return mParent; } 368 373 uint32_t getProtocolVersion(void) { return mData.mProtocolVersion; } 374 int pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags, int *pGuestRc); 369 375 int processRemoveFromList(GuestProcess *pProcess); 370 376 int processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProgress); -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r48342 r49349 297 297 break; 298 298 299 case GUEST_SESSION_NOTIFY:300 rc = pSession->dispatchToThis(pCtxCb, pSvcCb);301 break;302 303 299 case GUEST_EXEC_STATUS: 304 300 case GUEST_EXEC_OUTPUT: … … 312 308 break; 313 309 310 case GUEST_SESSION_NOTIFY: 311 rc = pSession->dispatchToThis(pCtxCb, pSvcCb); 312 break; 313 314 314 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 316 326 break; 317 327 } … … 323 333 rc = VERR_NOT_FOUND; 324 334 325 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));335 LogFlowFuncLeaveRC(rc); 326 336 return rc; 327 337 } … … 329 339 int Guest::sessionRemove(GuestSession *pSession) 330 340 { 341 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 342 331 343 LogFlowThisFuncEnter(); 332 344 … … 364 376 } 365 377 366 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));378 LogFlowFuncLeaveRC(rc); 367 379 return rc; 368 380 } … … 445 457 } 446 458 447 LogFlow ThisFunc(("Returning rc=%Rrc\n", rc));459 LogFlowFuncLeaveRC(rc); 448 460 return rc; 449 461 } -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r47627 r49349 680 680 681 681 /** 682 * Returns the current offset of the parser within683 * 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 /**698 682 * Tries to parse the next upcoming pair block within the internal 699 683 * buffer. … … 814 798 if (RT_SUCCESS(rc)) 815 799 { 816 Guest WaitEventTypes::iterator itEventTypes = mWaitEvents.begin();817 while (itEvent Types != mWaitEvents.end())818 { 819 GuestWaitEvents::iterator itEvents = itEvent Types->second.begin();820 while (itEvents != itEvent Types->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()) 821 805 { 822 GuestWaitEvent *pEvent = (*itEvents);806 GuestWaitEvent *pEvent = itEvents->second; 823 807 AssertPtr(pEvent); 824 808 825 809 /* 826 * Just cancel the event and remove it from the wait events827 * map. Don't delete it though, this (hopefully) is done by828 * 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(). 829 813 */ 830 int rc2 = pEvent-> Signal(NULL /* Cancel */);814 int rc2 = pEvent->Cancel(); 831 815 AssertRC(rc2); 832 itEvents = itEventTypes->second.erase(itEvents); 816 817 itEvents++; 833 818 } 834 819 835 mWaitEvents.erase(itEventTypes); 836 itEventTypes = mWaitEvents.begin(); 820 itEventGroups++; 837 821 } 838 822 … … 846 830 } 847 831 832 int 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 848 892 int GuestBase::generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID) 849 893 { … … 869 913 870 914 int 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 921 int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, 922 const GuestEventTypes &lstEvents, 872 923 GuestWaitEvent **ppEvent) 873 924 { … … 887 938 AssertPtr(pEvent); 888 939 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(); 890 943 itEvents != lstEvents.end(); itEvents++) 891 944 { 892 mWaitEvents[(*itEvents)].push_back(pEvent); 945 mWaitEventGroups[(*itEvents)].insert( 946 std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent)); 947 /** @todo Check for key collision. */ 893 948 } 949 950 /* Register event in regular event list. */ 951 /** @todo Check for key collisions. */ 952 mWaitEvents[uContextID] = pEvent; 894 953 895 954 *ppEvent = pEvent; … … 908 967 } 909 968 910 int GuestBase::signalWaitEvent s(VBoxEventType_T aType, IEvent *aEvent)969 int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent) 911 970 { 912 971 int rc = RTCritSectEnter(&mWaitEventCritSect); 972 #ifdef DEBUG 973 uint32_t cEvents = 0; 974 #endif 913 975 if (RT_SUCCESS(rc)) 914 976 { 915 Guest WaitEventTypes::iterator itTypes = mWaitEvents.find(aType);916 if (it Types != mWaitEvents.end())917 { 918 for (GuestWaitEvents::iterator itEvents = it Types->second.begin();919 itEvents != it Types->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++) 920 982 { 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 924 990 ComPtr<IEvent> pThisEvent = aEvent; 925 991 Assert(!pThisEvent.isNull()); 926 int rc2 = (*itEvents)->Signal(aEvent);992 int rc2 = itEvents->second->SignalExternal(aEvent); 927 993 if (RT_SUCCESS(rc)) 928 994 rc = rc2; 995 #ifdef DEBUG 996 cEvents++; 997 #endif 929 998 } 930 999 } … … 935 1004 } 936 1005 937 return rc; 1006 #ifdef DEBUG 1007 LogFlowThisFunc(("Signalled %RU32 events, rc=%Rrc\n", cEvents, rc)); 1008 #endif 1009 return rc; 1010 } 1011 1012 int 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 1023 int 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; 938 1044 } 939 1045 … … 946 1052 if (RT_SUCCESS(rc)) 947 1053 { 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(); 950 1056 itEvents != lstTypes.end(); itEvents++) 951 1057 { 952 1058 /** @todo Slow O(n) lookup. Optimize this. */ 953 GuestWaitEvents::iterator itCurEvent = mWaitEvent s[(*itEvents)].begin();954 while (itCurEvent != mWaitEvent s[(*itEvents)].end())1059 GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin(); 1060 while (itCurEvent != mWaitEventGroups[(*itEvents)].end()) 955 1061 { 956 if ( (*itCurEvent)== pEvent)1062 if (itCurEvent->second == pEvent) 957 1063 { 958 itCurEvent = mWaitEvent s[(*itEvents)].erase(itCurEvent);1064 itCurEvent = mWaitEventGroups[(*itEvents)].erase(itCurEvent); 959 1065 break; 960 1066 } … … 973 1079 } 974 1080 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 */ 975 1092 int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, 976 1093 VBoxEventType_T *pType, IEvent **ppEvent) 977 1094 { 978 1095 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1096 /* pType is optional. */ 1097 /* ppEvent is optional. */ 979 1098 980 1099 int vrc = pEvent->Wait(uTimeoutMS); … … 982 1101 { 983 1102 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 } 997 1117 } 998 1118 … … 1022 1142 } 1023 1143 1024 int GuestObject::registerWaitEvent(const std::list<VBoxEventType_T>&lstEvents,1144 int GuestObject::registerWaitEvent(const GuestEventTypes &lstEvents, 1025 1145 GuestWaitEvent **ppEvent) 1026 1146 { … … 1058 1178 } 1059 1179 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; 1180 GuestWaitEventBase::GuestWaitEventBase(void) 1181 : mCID(0), 1182 mEventSem(NIL_RTSEMEVENT), 1183 mfAborted(false), 1184 mRc(VINF_SUCCESS), 1185 mGuestRc(VINF_SUCCESS) 1186 { 1187 } 1188 1189 GuestWaitEventBase::~GuestWaitEventBase(void) 1190 { 1191 } 1192 1193 int GuestWaitEventBase::Init(uint32_t uCID) 1194 { 1195 mCID = uCID; 1196 1197 return RTSemEventCreate(&mEventSem); 1198 } 1199 1200 int 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)); 1089 1208 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 1228 int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS) 1096 1229 { 1097 1230 int rc = VINF_SUCCESS; 1098 1231 1099 if (ASMAtomicReadBool(& fAborted))1232 if (ASMAtomicReadBool(&mfAborted)) 1100 1233 rc = VERR_CANCELLED; 1101 1234 … … 1108 1241 msInterval = RT_INDEFINITE_WAIT; 1109 1242 rc = RTSemEventWait(mEventSem, msInterval); 1110 if (ASMAtomicReadBool(& fAborted))1243 if (ASMAtomicReadBool(&mfAborted)) 1111 1244 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 1256 GuestWaitEvent::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 1265 GuestWaitEvent::GuestWaitEvent(uint32_t uCID) 1266 { 1267 int rc2 = Init(uCID); 1268 AssertRC(rc2); /** @todo Throw exception here. */ 1269 } 1270 1271 GuestWaitEvent::~GuestWaitEvent(void) 1272 { 1273 1274 } 1275 1276 /** 1277 * Cancels the event. 1278 */ 1279 int GuestWaitEvent::Cancel(void) 1280 { 1281 AssertReturn(!mfAborted, VERR_CANCELLED); 1282 ASMAtomicWriteBool(&mfAborted, true); 1283 1284 return RTSemEventSignal(mEventSem); 1285 } 1286 1287 int 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 */ 1299 int 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 59 59 ///////////////////////////////////////////////////////////////////////////// 60 60 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)); 61 int 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); 66 70 67 71 /* Enclose the state transition NotReady->InInit->Ready. */ … … 69 73 AssertReturn(autoInitSpan.isOk(), E_FAIL); 70 74 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")); 86 100 #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? */ 89 103 #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)) 101 117 { 102 118 /* Confirm a successful initialization when it's the case. */ 103 119 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 */ 109 127 } 110 128 … … 139 157 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 140 158 141 mData.m Name.cloneTo(aName);159 mData.mOpenInfo.mPath.cloneTo(aName); 142 160 143 161 return S_OK; … … 155 173 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 156 174 157 mData.m Filter.cloneTo(aFilter);175 mData.mOpenInfo.mFilter.cloneTo(aFilter); 158 176 159 177 return S_OK; … … 162 180 // private methods 163 181 ///////////////////////////////////////////////////////////////////////////// 182 183 int 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 */ 231 Utf8Str 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 */ 251 HRESULT 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 } 164 258 165 259 // implementation of public methods … … 176 270 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 177 271 178 AssertPtr(m Data.mSession);179 int rc = m Data.mSession->directoryRemoveFromList(this);272 AssertPtr(mSession); 273 int rc = mSession->directoryRemoveFromList(this); 180 274 AssertRC(rc); 181 275 … … 188 282 switch (rc) 189 283 { 190 case VERR_GSTCTL_GUEST_ERROR:284 case VERR_GSTCTL_GUEST_ERROR: 191 285 hr = GuestProcess::setErrorExternal(this, guestRc); 192 286 break; … … 200 294 hr = setError(VBOX_E_IPRT_ERROR, 201 295 tr("Terminating open guest directory \"%s\" failed: %Rrc"), 202 mData.m Name.c_str(), rc);296 mData.mOpenInfo.mPath.c_str(), rc); 203 297 break; 204 298 } … … 293 387 case VERR_ACCESS_DENIED: 294 388 hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"), 295 mData.m Name.c_str());389 mData.mOpenInfo.mPath.c_str()); 296 390 break; 297 391 298 392 case VERR_PATH_NOT_FOUND: 299 393 hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"), 300 mData.m Name.c_str());394 mData.mOpenInfo.mPath.c_str()); 301 395 break; 302 396 … … 304 398 /* See SDK reference. */ 305 399 hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""), 306 mData.m Name.c_str());400 mData.mOpenInfo.mPath.c_str()); 307 401 break; 308 402 309 403 default: 310 404 hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"), 311 mData.m Name.c_str(), rc);405 mData.mOpenInfo.mPath.c_str(), rc); 312 406 break; 313 407 } -
trunk/src/VBox/Main/src-client/GuestFileImpl.cpp
r49006 r49349 77 77 { 78 78 Assert(!mFile.isNull()); 79 int rc2 = mFile->signalWaitEvent s(aType, aEvent);79 int rc2 = mFile->signalWaitEvent(aType, aEvent); 80 80 #ifdef DEBUG_andy 81 81 LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n", … … 411 411 int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 412 412 { 413 #ifdef DEBUG 413 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER); 414 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER); 415 414 416 LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n", 415 417 mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb)); 416 #endif417 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);418 418 419 419 int vrc; … … 447 447 448 448 GuestWaitEvent *pEvent = NULL; 449 std::list < VBoxEventType_T >eventTypes;449 GuestEventTypes eventTypes; 450 450 try 451 451 { … … 539 539 AssertRC(rc2); 540 540 541 rc2 = signalWaitEventInternal(pCbCtx, 542 guestRc, NULL /* pPayload */); 543 AssertRC(rc2); 544 541 545 return VINF_SUCCESS; /* Report to the guest. */ 542 546 } … … 548 552 int rc2 = setFileStatus(FileStatus_Error, guestRc); 549 553 AssertRC(rc2); 554 550 555 break; 551 556 } … … 561 566 AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID), 562 567 ("File ID %RU32 does not match context ID %RU32\n", mData.mID, 563 568 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID))); 564 569 565 570 /* Set the initial offset. On the guest the whole opening operation … … 570 575 /* Set the process status. */ 571 576 int rc2 = setFileStatus(FileStatus_Open, guestRc); 572 if (RT_SUCCESS(vrc)) 573 vrc = rc2; 577 AssertRC(rc2); 574 578 } 575 579 else … … 678 682 } 679 683 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 680 691 LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n", 681 692 dataCb.uType, dataCb.rc)); … … 708 719 709 720 GuestWaitEvent *pEvent = NULL; 710 std::list < VBoxEventType_T >eventTypes;721 GuestEventTypes eventTypes; 711 722 try 712 723 { … … 765 776 766 777 GuestWaitEvent *pEvent = NULL; 767 std::list < VBoxEventType_T >eventTypes;778 GuestEventTypes eventTypes; 768 779 try 769 780 { … … 820 831 821 832 GuestWaitEvent *pEvent = NULL; 822 std::list < VBoxEventType_T >eventTypes;833 GuestEventTypes eventTypes; 823 834 try 824 835 { … … 876 887 877 888 GuestWaitEvent *pEvent = NULL; 878 std::list < VBoxEventType_T >eventTypes;889 GuestEventTypes eventTypes; 879 890 try 880 891 { … … 970 981 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 971 982 972 VBoxEventType_T evtType;973 ComPtr<IEvent> pIEvent;974 983 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 999 int 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); 988 1020 } 989 1021 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; 1035 1026 } 1036 1027 … … 1042 1033 { 1043 1034 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1044 /* pFileStatus is optional. */ 1045 1046 VBoxEventType_T evtType; 1047 ComPtr<IEvent> pIEvent; 1035 1048 1036 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 1076 1046 1077 1047 if (pGuestRc) 1078 *pGuestRc = (int)lGuestRc;1048 *pGuestRc = pvCbData->rc; /* int vs. uint32_t */ 1079 1049 } 1080 1050 … … 1087 1057 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1088 1058 1089 VBoxEventType_T evtType;1090 ComPtr<IEvent> pIEvent;1091 1059 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; 1108 1070 } 1109 1071 … … 1125 1087 1126 1088 GuestWaitEvent *pEvent = NULL; 1127 std::list < VBoxEventType_T >eventTypes;1089 GuestEventTypes eventTypes; 1128 1090 try 1129 1091 { … … 1184 1146 1185 1147 GuestWaitEvent *pEvent = NULL; 1186 std::list < VBoxEventType_T >eventTypes;1148 GuestEventTypes eventTypes; 1187 1149 try 1188 1150 { -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r48770 r49349 116 116 { 117 117 Assert(!mProcess.isNull()); 118 int rc2 = mProcess->signalWaitEvent s(aType, aEvent);119 #ifdef DEBUG _andy118 int rc2 = mProcess->signalWaitEvent(aType, aEvent); 119 #ifdef DEBUG 120 120 LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n", 121 121 aType, mProcess, rc2)); … … 512 512 513 513 #ifdef DEBUG 514 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));514 LogFlowFuncLeaveRC(vrc); 515 515 #endif 516 516 return vrc; … … 647 647 int vrc = setProcessStatus(ProcessStatus_Down, VINF_SUCCESS); 648 648 649 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));649 LogFlowFuncLeaveRC(vrc); 650 650 return vrc; 651 651 } … … 714 714 } 715 715 716 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));716 LogFlowFuncLeaveRC(vrc); 717 717 return vrc; 718 718 } … … 832 832 } 833 833 834 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));834 LogFlowFuncLeaveRC(vrc); 835 835 return vrc; 836 836 } … … 868 868 } 869 869 870 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));870 LogFlowFuncLeaveRC(vrc); 871 871 return vrc; 872 872 } … … 904 904 905 905 GuestWaitEvent *pEvent = NULL; 906 std::list < VBoxEventType_T >eventTypes;906 GuestEventTypes eventTypes; 907 907 try 908 908 { … … 948 948 unregisterWaitEvent(pEvent); 949 949 950 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));950 LogFlowFuncLeaveRC(vrc); 951 951 return vrc; 952 952 } … … 1041 1041 1042 1042 GuestWaitEvent *pEvent = NULL; 1043 std::list < VBoxEventType_T >eventTypes;1043 GuestEventTypes eventTypes; 1044 1044 try 1045 1045 { … … 1168 1168 unregisterWaitEvent(pEvent); 1169 1169 1170 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1170 LogFlowFuncLeaveRC(vrc); 1171 1171 return vrc; 1172 1172 } … … 1200 1200 } 1201 1201 1202 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1202 LogFlowFuncLeaveRC(vrc); 1203 1203 return vrc; 1204 1204 } … … 1250 1250 { 1251 1251 GuestWaitEvent *pEvent = NULL; 1252 std::list < VBoxEventType_T >eventTypes;1252 GuestEventTypes eventTypes; 1253 1253 try 1254 1254 { … … 1279 1279 } 1280 1280 1281 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1281 LogFlowFuncLeaveRC(vrc); 1282 1282 return vrc; 1283 1283 } … … 1285 1285 /* static */ 1286 1286 ProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags, 1287 ProcessStatus_T procStatus, uint32_t uProcFlags,1288 uint32_t uPro tocol)1287 ProcessStatus_T oldStatus, ProcessStatus_T newStatus, 1288 uint32_t uProcFlags, uint32_t uProtocol) 1289 1289 { 1290 1290 ProcessWaitResult_T waitResult = ProcessWaitResult_None; 1291 1291 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) 1316 1316 { 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; 1325 1337 } 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 ) 1384 1367 ) 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 1392 1379 return waitResult; 1393 1380 } … … 1396 1383 { 1397 1384 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 1390 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, 1391 ProcessWaitResult_T &waitResult, int *pGuestRc) 1403 1392 { 1404 1393 AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER); 1405 1394 1406 Auto WriteLock alock(this COMMA_LOCKVAL_SRC_POS);1395 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1407 1396 1408 1397 LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, procStatus=%RU32, procRc=%Rrc, pGuestRc=%p\n", … … 1410 1399 1411 1400 /* 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) 1413 1403 { 1414 1404 waitResult = ProcessWaitResult_Error; … … 1420 1410 1421 1411 waitResult = waitFlagsToResult(fWaitFlags); 1422 LogFlowThisFunc(("waitFlagToResult=%ld\n", waitResult));1423 1412 1424 1413 /* No waiting needed? Return immediately using the last set error. */ … … 1435 1424 1436 1425 GuestWaitEvent *pEvent = NULL; 1437 std::list < VBoxEventType_T >eventTypes;1426 GuestEventTypes eventTypes; 1438 1427 try 1439 1428 { … … 1453 1442 * Do the actual waiting. 1454 1443 */ 1455 ProcessStatus_T processStatus = ProcessStatus_Undefined;1444 ProcessStatus_T newStatus = ProcessStatus_Undefined; 1456 1445 uint64_t u64StartMS = RTTimeMilliTS(); 1457 1446 for (;;) … … 1468 1457 uTimeoutMS == RT_INDEFINITE_WAIT 1469 1458 ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS, 1470 & processStatus, pGuestRc);1459 &newStatus, pGuestRc); 1471 1460 if (RT_SUCCESS(vrc)) 1472 1461 { 1473 1462 alock.acquire(); 1474 1463 1475 waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,1464 waitResult = waitFlagsToResultEx(fWaitFlags, curStatus, newStatus, 1476 1465 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 1479 1470 if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */ 1480 1471 break; … … 1488 1479 unregisterWaitEvent(pEvent); 1489 1480 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)); 1492 1483 return vrc; 1493 1484 } … … 1501 1492 ComPtr<IEvent> pIEvent; 1502 1493 int vrc = waitForEvent(pEvent, uTimeoutMS, 1503 &evtType, pIEvent.asOutParam());1494 &evtType, pIEvent.asOutParam()); 1504 1495 if (RT_SUCCESS(vrc)) 1505 1496 { … … 1547 1538 { 1548 1539 vrc = waitForEvent(pEvent, uTimeoutMS, 1549 &evtType, pIEvent.asOutParam());1540 &evtType, pIEvent.asOutParam()); 1550 1541 if (RT_SUCCESS(vrc)) 1551 1542 { 1552 #ifdef DEBUG_andy1553 LogFlowThisFunc(("pEvent=%p, evtType=%ld\n", pEvent, evtType));1554 #endif1555 1543 if (evtType == VBoxEventType_OnGuestProcessOutput) 1556 1544 { … … 1560 1548 ULONG uHandleEvent; 1561 1549 HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent); 1562 LogFlowThisFunc(("Received output, uHandle=%RU32\n", uHandleEvent));1563 1550 if ( SUCCEEDED(hr) 1564 1551 && uHandleEvent == uHandle) … … 1579 1566 else 1580 1567 vrc = VERR_BUFFER_OVERFLOW; 1568 1569 LogFlowThisFunc(("Read %zu bytes (uHandle=%RU32), rc=%Rrc\n", 1570 cbRead, uHandleEvent, vrc)); 1581 1571 } 1582 1572 } … … 1608 1598 } 1609 1599 1610 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1600 LogFlowFuncLeaveRC(vrc); 1611 1601 return vrc; 1612 1602 } … … 1629 1619 Assert(!pProcessEvent.isNull()); 1630 1620 1631 HRESULT hr; 1621 ProcessStatus_T procStatus; 1622 HRESULT hr = pProcessEvent->COMGETTER(Status)(&procStatus); 1623 ComAssertComRC(hr); 1632 1624 if (pProcessStatus) 1633 { 1634 hr = pProcessEvent->COMGETTER(Status)(pProcessStatus); 1635 ComAssertComRC(hr); 1636 } 1625 *pProcessStatus = procStatus; 1637 1626 1638 1627 ComPtr<IVirtualBoxErrorInfo> errorInfo; … … 1644 1633 ComAssertComRC(hr); 1645 1634 1646 LogFlowThisFunc((" resultDetail=%RI32 (rc=%Rrc)\n",1647 lGuestRc, lGuestRc));1635 LogFlowThisFunc(("procStatus=%RU32, resultDetail=%RI32 (rc=%Rrc)\n", 1636 procStatus, lGuestRc, lGuestRc)); 1648 1637 1649 1638 if (RT_FAILURE((int)lGuestRc)) … … 1654 1643 } 1655 1644 1656 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1645 LogFlowFuncLeaveRC(vrc); 1657 1646 return vrc; 1658 1647 } … … 1710 1699 1711 1700 GuestWaitEvent *pEvent = NULL; 1712 std::list < VBoxEventType_T >eventTypes;1701 GuestEventTypes eventTypes; 1713 1702 try 1714 1703 { … … 1814 1803 LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead)); 1815 1804 1816 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1805 LogFlowFuncLeaveRC(vrc); 1817 1806 return hr; 1818 1807 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1861 1850 mSession->processRemoveFromList(this); 1862 1851 1863 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1852 LogFlowFuncLeaveRC(vrc); 1864 1853 return hr; 1865 1854 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1909 1898 } 1910 1899 1911 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1900 LogFlowFuncLeaveRC(vrc); 1912 1901 return hr; 1913 1902 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 1978 1967 *aWritten = (ULONG)cbWritten; 1979 1968 1980 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));1969 LogFlowFuncLeaveRC(vrc); 1981 1970 return hr; 1982 1971 #endif /* VBOX_WITH_GUEST_CONTROL */ … … 2029 2018 AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER); 2030 2019 2031 pSession 2020 pSession = pGuestSession; 2032 2021 mStartupInfo = startupInfo; 2033 2022 … … 2050 2039 } 2051 2040 2052 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));2041 LogFlowFuncLeaveRC(vrc); 2053 2042 return vrc; 2054 2043 } … … 2097 2086 } 2098 2087 2088 /* static */ 2089 int 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 */ 2099 int 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 2099 2147 int GuestProcessTool::TerminatedOk(LONG *pExitCode) 2100 2148 { … … 2102 2150 /* pExitCode is optional. */ 2103 2151 2152 int vrc; 2104 2153 if (!IsRunning()) 2105 2154 { … … 2111 2160 *pExitCode = exitCode; 2112 2161 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; 2119 2171 } 2120 2172 2121 2173 int GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc) 2122 2174 { 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 2178 int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pGuestRc) 2179 { 2180 LogFlowThisFunc(("fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n", 2181 fFlags, pStrmBlkOut, pGuestRc)); 2134 2182 2135 2183 /* Can we parse the next block without waiting? */ … … 2137 2185 if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK) 2138 2186 { 2139 AssertPtr(pStr eamBlock);2140 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStr eamBlock);2187 AssertPtr(pStrmBlkOut); 2188 vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut); 2141 2189 if (RT_SUCCESS(vrc)) 2142 2190 return vrc; … … 2151 2199 fWaitFlags |= ProcessWaitForFlag_StdErr; 2152 2200 2153 LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));2154 2155 2201 /** @todo Decrease timeout while running. */ 2202 uint64_t u64StartMS = RTTimeMilliTS(); 2156 2203 uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS; 2157 2204 … … 2165 2212 bool fHandleStdErr = false; 2166 2213 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 2167 2234 ProcessWaitResult_T waitRes; 2168 2235 do 2169 2236 { 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); 2172 2242 if (RT_FAILURE(vrc)) 2173 2243 break; … … 2219 2289 } 2220 2290 2291 if (RT_FAILURE(vrc)) 2292 break; 2293 2221 2294 if (fHandleStdOut) 2222 2295 { 2296 UPDATE_AND_CHECK_ELAPSED_TIME(); 2297 2223 2298 cbRead = 0; 2224 2299 vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf), 2225 uTimeoutMS, byBuf, sizeof(byBuf), 2300 GET_REMAINING_TIME, 2301 byBuf, sizeof(byBuf), 2226 2302 &cbRead, &guestRc); 2227 if (RT_FAILURE(vrc)) 2303 if ( RT_FAILURE(vrc) 2304 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2228 2305 break; 2229 2306 … … 2236 2313 && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)) 2237 2314 { 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. */ 2240 2320 if (RT_SUCCESS(vrc)) 2241 2321 fDone = true; … … 2248 2328 if (fHandleStdErr) 2249 2329 { 2330 UPDATE_AND_CHECK_ELAPSED_TIME(); 2331 2250 2332 cbRead = 0; 2251 2333 vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf), 2252 uTimeoutMS, byBuf, sizeof(byBuf), 2334 GET_REMAINING_TIME, 2335 byBuf, sizeof(byBuf), 2253 2336 &cbRead, &guestRc); 2254 if (RT_FAILURE(vrc)) 2337 if ( RT_FAILURE(vrc) 2338 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED) 2255 2339 break; 2256 2340 … … 2266 2350 } while (!fDone && RT_SUCCESS(vrc)); 2267 2351 2352 #undef UPDATE_AND_CHECK_ELAPSED_TIME 2353 #undef GET_REMAINING_TIME 2354 2268 2355 LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n", 2269 2356 vrc, guestRc, waitRes)); … … 2271 2358 *pGuestRc = guestRc; 2272 2359 2273 LogFlow ThisFunc(("Returning rc=%Rrc\n", vrc));2360 LogFlowFuncLeaveRC(vrc); 2274 2361 return vrc; 2275 2362 } -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r48342 r49349 114 114 { 115 115 Assert(!mSession.isNull()); 116 int rc2 = mSession->signalWaitEvent s(aType, aEvent);116 int rc2 = mSession->signalWaitEvent(aType, aEvent); 117 117 #ifdef DEBUG_andy 118 118 LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n", … … 289 289 itDirs != mData.mDirectories.end(); ++itDirs) 290 290 { 291 (*itDirs)->Release();291 itDirs->second->Release(); 292 292 } 293 293 mData.mDirectories.clear(); … … 665 665 666 666 GuestWaitEvent *pEvent = NULL; 667 std::list < VBoxEventType_T >eventTypes;667 GuestEventTypes eventTypes; 668 668 try 669 669 { … … 702 702 } 703 703 704 int 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 747 inline 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 759 int 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 704 774 int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory) 705 775 { … … 709 779 itDirs != mData.mDirectories.end(); ++itDirs) 710 780 { 711 if (pDirectory == (*itDirs))781 if (pDirectory == itDirs->second) 712 782 { 713 783 Bstr strName; 714 HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());784 HRESULT hr = itDirs->second->COMGETTER(DirectoryName)(strName.asOutParam()); 715 785 ComAssertComRC(hr); 716 786 … … 727 797 } 728 798 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 799 int 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); 759 825 if (RT_SUCCESS(vrc)) 760 826 { 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); 776 828 if ( vrc == VERR_GSTCTL_GUEST_ERROR 777 829 && pGuestRc) 778 {779 *pGuestRc = guestRc;780 } 781 }830 *pGuestRc = pEvent->GuestResult(); 831 } 832 833 unregisterWaitEvent(pEvent); 782 834 783 835 LogFlowFuncLeaveRC(vrc); … … 785 837 } 786 838 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_Directory795 ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;796 }797 798 LogFlowFuncLeaveRC(vrc);799 return vrc;800 }801 802 839 int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath, 803 840 bool fDirectory, const Utf8Str &strName, int *pGuestRc) 804 841 { 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 805 847 GuestProcessStartupInfo procInfo; 806 848 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP); 807 849 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 820 868 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); 837 870 838 871 LogFlowFuncLeaveRC(vrc); … … 840 873 } 841 874 842 int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,843 uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)875 int GuestSession::directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo, 876 ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc) 844 877 { 845 878 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)); 847 880 848 881 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; 849 912 850 913 /* Create the directory object. */ … … 853 916 return VERR_COM_UNEXPECTED; 854 917 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); 857 923 if (RT_FAILURE(vrc)) 858 924 return vrc; 859 925 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 } 865 958 866 959 LogFlowFuncLeaveRC(vrc); 867 960 return vrc; 961 } 962 963 int 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; 868 997 } 869 998 … … 901 1030 } 902 1031 1032 int 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 903 1081 int GuestSession::dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) 904 1082 { … … 949 1127 #endif 950 1128 951 int rc = VINF_SUCCESS;1129 int rc; 952 1130 switch (pCbCtx->uFunction) 953 1131 { … … 956 1134 break; 957 1135 958 case GUEST_SESSION_NOTIFY: 1136 case GUEST_SESSION_NOTIFY: /* Guest Additions >= 4.3.0. */ 959 1137 { 960 1138 rc = onSessionStatusChange(pCbCtx, pSvcCb); … … 1024 1202 int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc) 1025 1203 { 1204 LogFlowThisFunc(("strPath=%s\n", strPath.c_str())); 1205 1206 int vrc = VINF_SUCCESS; 1207 1026 1208 GuestProcessStartupInfo procInfo; 1027 1209 GuestProcessStream streamOut; … … 1029 1211 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM); 1030 1212 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 1036 1224 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); 1050 1226 1051 1227 LogFlowFuncLeaveRC(vrc); … … 1053 1229 } 1054 1230 1055 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc) 1231 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, 1232 ComObjPtr<GuestFile> &pFile, int *pGuestRc) 1056 1233 { 1057 1234 LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n", … … 1080 1257 { 1081 1258 /* Is the file ID already used? */ 1082 if (!fileExists(uNewFileID, NULL /* p Progress*/))1259 if (!fileExists(uNewFileID, NULL /* pFile */)) 1083 1260 { 1084 1261 /* Callback with context ID was not found. This means … … 1185 1362 LogFlowThisFunc(("strPath=%s\n", strPath.c_str())); 1186 1363 1364 int vrc = VINF_SUCCESS; 1365 1187 1366 /** @todo Merge this with IGuestFile::queryInfo(). */ 1188 1367 GuestProcessStartupInfo procInfo; … … 1190 1369 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut; 1191 1370 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; 1198 1383 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; 1217 1394 } 1218 1395 … … 1403 1580 /* Set current session status. */ 1404 1581 mData.mStatus = GuestSessionStatus_Starting; 1582 mData.mRC = VINF_SUCCESS; /* Clear previous error, if any. */ 1405 1583 1406 1584 int vrc; 1407 1585 1408 1586 GuestWaitEvent *pEvent = NULL; 1409 std::list < VBoxEventType_T >eventTypes;1587 GuestEventTypes eventTypes; 1410 1588 try 1411 1589 { … … 1440 1618 vrc = sendCommand(HOST_SESSION_CREATE, i, paParms); 1441 1619 if (RT_SUCCESS(vrc)) 1620 { 1442 1621 vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start, 1443 1622 30 * 1000 /* 30s timeout */, 1444 1623 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 } 1445 1636 1446 1637 unregisterWaitEvent(pEvent); … … 1498 1689 int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */); 1499 1690 /* Nothing to do here anymore. */ 1691 1692 LogFlowFuncLeaveRC(vrc); 1693 return vrc; 1694 } 1695 1696 int 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); 1500 1734 1501 1735 LogFlowFuncLeaveRC(vrc); … … 1625 1859 { 1626 1860 /* Is the context ID already used? */ 1627 if (!processExists(uNewProcessID, NULL /* pPro gress */))1861 if (!processExists(uNewProcessID, NULL /* pProcess */)) 1628 1862 { 1629 1863 /* Callback with context ID was not found. This means … … 1988 2222 1989 2223 GuestWaitEvent *pEvent = NULL; 1990 std::list < VBoxEventType_T >eventTypes;2224 GuestEventTypes eventTypes; 1991 2225 try 1992 2226 { … … 2110 2344 /* Remove ourselves from the session list. */ 2111 2345 int rc2 = mParent->sessionRemove(this); 2346 if (rc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */ 2347 rc2 = VINF_SUCCESS; 2348 2112 2349 if (RT_SUCCESS(rc)) 2113 2350 rc = rc2; … … 2418 2655 HRESULT hr = S_OK; 2419 2656 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); 2422 2664 if (RT_SUCCESS(rc)) 2423 2665 { … … 2433 2675 Utf8Str(aPath).c_str())); 2434 2676 break; 2677 2678 case VERR_GSTCTL_GUEST_ERROR: 2679 hr = GuestDirectory::setErrorExternal(this, guestRc); 2680 break; 2435 2681 2436 2682 default: … … 2511 2757 LogFlowThisFuncEnter(); 2512 2758 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; 2517 2795 #endif /* VBOX_WITH_GUEST_CONTROL */ 2518 2796 } … … 2525 2803 LogFlowThisFuncEnter(); 2526 2804 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; 2531 2862 #endif /* VBOX_WITH_GUEST_CONTROL */ 2532 2863 } … … 2539 2870 LogFlowThisFuncEnter(); 2540 2871 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; 2545 2912 #endif /* VBOX_WITH_GUEST_CONTROL */ 2546 2913 } … … 2930 3297 LogFlowThisFuncEnter(); 2931 3298 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; 2936 3340 #endif /* VBOX_WITH_GUEST_CONTROL */ 2937 3341 } -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r47905 r49349 627 627 { 628 628 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); 631 631 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT); 632 632 procInfo.mFlags = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
Note:
See TracChangeset
for help on using the changeset viewer.