VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestFileImpl.cpp@ 49349

Last change on this file since 49349 was 49349, checked in by vboxsync, 11 years ago

Guest Control:

  • Implemented IGuestSession::DirectoryRemove, IGuestSession::DirectoryRemoveRecursive, IGuestSession::DirectoryRename + IGuestSession::FileRename.
  • Added appropriate commands to VBoxManage (basic support for now).
  • Implemented support for proper guest session process termination via SCM.
  • Implemented support for internal anonymous wait events which are not relying on the public API's VBoxEventType_T.
  • Various bugfixes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.3 KB
Line 
1
2/* $Id: GuestFileImpl.cpp 49349 2013-10-31 16:40:46Z vboxsync $ */
3/** @file
4 * VirtualBox Main - Guest file handling.
5 */
6
7/*
8 * Copyright (C) 2012-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include "GuestFileImpl.h"
24#include "GuestSessionImpl.h"
25#include "GuestCtrlImplPrivate.h"
26#include "ConsoleImpl.h"
27#include "VirtualBoxErrorInfoImpl.h"
28
29#include "Global.h"
30#include "AutoCaller.h"
31#include "VBoxEvents.h"
32
33#include <iprt/cpp/utils.h> /* For unconst(). */
34#include <iprt/file.h>
35
36#include <VBox/com/array.h>
37#include <VBox/com/listeners.h>
38
39#ifdef LOG_GROUP
40 #undef LOG_GROUP
41#endif
42#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
43#include <VBox/log.h>
44
45
46/**
47 * Internal listener class to serve events in an
48 * active manner, e.g. without polling delays.
49 */
50class GuestFileListener
51{
52public:
53
54 GuestFileListener(void)
55 {
56 }
57
58 HRESULT init(GuestFile *pFile)
59 {
60 mFile = pFile;
61 return S_OK;
62 }
63
64 void uninit(void)
65 {
66 mFile.setNull();
67 }
68
69 STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
70 {
71 switch (aType)
72 {
73 case VBoxEventType_OnGuestFileStateChanged:
74 case VBoxEventType_OnGuestFileOffsetChanged:
75 case VBoxEventType_OnGuestFileRead:
76 case VBoxEventType_OnGuestFileWrite:
77 {
78 Assert(!mFile.isNull());
79 int rc2 = mFile->signalWaitEvent(aType, aEvent);
80#ifdef DEBUG_andy
81 LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n",
82 aType, mFile, rc2));
83#endif
84 break;
85 }
86
87 default:
88 AssertMsgFailed(("Unhandled event %ld\n", aType));
89 break;
90 }
91
92 return S_OK;
93 }
94
95private:
96
97 ComObjPtr<GuestFile> mFile;
98};
99typedef ListenerImpl<GuestFileListener, GuestFile*> GuestFileListenerImpl;
100
101VBOX_LISTENER_DECLARE(GuestFileListenerImpl)
102
103// constructor / destructor
104/////////////////////////////////////////////////////////////////////////////
105
106DEFINE_EMPTY_CTOR_DTOR(GuestFile)
107
108HRESULT GuestFile::FinalConstruct(void)
109{
110 LogFlowThisFunc(("\n"));
111 return BaseFinalConstruct();
112}
113
114void GuestFile::FinalRelease(void)
115{
116 LogFlowThisFuncEnter();
117 uninit();
118 BaseFinalRelease();
119 LogFlowThisFuncLeave();
120}
121
122// public initializer/uninitializer for internal purposes only
123/////////////////////////////////////////////////////////////////////////////
124
125/**
126 * Initializes a file object but does *not* open the file on the guest
127 * yet. This is done in the dedidcated openFile call.
128 *
129 * @return IPRT status code.
130 * @param pConsole Pointer to console object.
131 * @param pSession Pointer to session object.
132 * @param uFileID Host-based file ID (part of the context ID).
133 * @param openInfo File opening information.
134 */
135int GuestFile::init(Console *pConsole, GuestSession *pSession,
136 ULONG uFileID, const GuestFileOpenInfo &openInfo)
137{
138 LogFlowThisFunc(("pConsole=%p, pSession=%p, uFileID=%RU32, strPath=%s\n",
139 pConsole, pSession, uFileID, openInfo.mFileName.c_str()));
140
141 AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
142 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
143
144 /* Enclose the state transition NotReady->InInit->Ready. */
145 AutoInitSpan autoInitSpan(this);
146 AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
147
148#ifndef VBOX_WITH_GUEST_CONTROL
149 autoInitSpan.setSucceeded();
150 return VINF_SUCCESS;
151#else
152 int vrc = bindToSession(pConsole, pSession, uFileID /* Object ID */);
153 if (RT_SUCCESS(vrc))
154 {
155 mSession = pSession;
156
157 mData.mID = uFileID;
158 mData.mInitialSize = 0;
159 mData.mStatus = FileStatus_Undefined;
160 mData.mOpenInfo = openInfo;
161
162 unconst(mEventSource).createObject();
163 HRESULT hr = mEventSource->init(static_cast<IGuestFile*>(this));
164 if (FAILED(hr))
165 vrc = VERR_COM_UNEXPECTED;
166 }
167
168 if (RT_SUCCESS(vrc))
169 {
170 try
171 {
172 GuestFileListener *pListener = new GuestFileListener();
173 ComObjPtr<GuestFileListenerImpl> thisListener;
174 HRESULT hr = thisListener.createObject();
175 if (SUCCEEDED(hr))
176 hr = thisListener->init(pListener, this);
177
178 if (SUCCEEDED(hr))
179 {
180 com::SafeArray <VBoxEventType_T> eventTypes;
181 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
182 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
183 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
184 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
185 hr = mEventSource->RegisterListener(thisListener,
186 ComSafeArrayAsInParam(eventTypes),
187 TRUE /* Active listener */);
188 if (SUCCEEDED(hr))
189 {
190 vrc = baseInit();
191 if (RT_SUCCESS(vrc))
192 {
193 mLocalListener = thisListener;
194 }
195 }
196 else
197 vrc = VERR_COM_UNEXPECTED;
198 }
199 else
200 vrc = VERR_COM_UNEXPECTED;
201 }
202 catch(std::bad_alloc &)
203 {
204 vrc = VERR_NO_MEMORY;
205 }
206 }
207
208 if (RT_SUCCESS(vrc))
209 {
210 /* Confirm a successful initialization when it's the case. */
211 autoInitSpan.setSucceeded();
212 }
213 else
214 autoInitSpan.setFailed();
215
216 LogFlowFuncLeaveRC(vrc);
217 return vrc;
218#endif /* VBOX_WITH_GUEST_CONTROL */
219}
220
221/**
222 * Uninitializes the instance.
223 * Called from FinalRelease().
224 */
225void GuestFile::uninit(void)
226{
227 LogFlowThisFunc(("\n"));
228
229 /* Enclose the state transition Ready->InUninit->NotReady. */
230 AutoUninitSpan autoUninitSpan(this);
231 if (autoUninitSpan.uninitDone())
232 return;
233
234#ifdef VBOX_WITH_GUEST_CONTROL
235 baseUninit();
236
237 mEventSource->UnregisterListener(mLocalListener);
238 unconst(mEventSource).setNull();
239#endif
240
241 LogFlowThisFuncLeave();
242}
243
244// implementation of public getters/setters for attributes
245/////////////////////////////////////////////////////////////////////////////
246
247STDMETHODIMP GuestFile::COMGETTER(CreationMode)(ULONG *aCreationMode)
248{
249#ifndef VBOX_WITH_GUEST_CONTROL
250 ReturnComNotImplemented();
251#else
252 AutoCaller autoCaller(this);
253 if (FAILED(autoCaller.rc())) return autoCaller.rc();
254
255 CheckComArgOutPointerValid(aCreationMode);
256
257 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
258
259 *aCreationMode = mData.mOpenInfo.mCreationMode;
260
261 return S_OK;
262#endif /* VBOX_WITH_GUEST_CONTROL */
263}
264
265STDMETHODIMP GuestFile::COMGETTER(Disposition)(BSTR *aDisposition)
266{
267#ifndef VBOX_WITH_GUEST_CONTROL
268 ReturnComNotImplemented();
269#else
270 AutoCaller autoCaller(this);
271 if (FAILED(autoCaller.rc())) return autoCaller.rc();
272
273 CheckComArgOutPointerValid(aDisposition);
274
275 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
276
277 mData.mOpenInfo.mDisposition.cloneTo(aDisposition);
278
279 return S_OK;
280#endif /* VBOX_WITH_GUEST_CONTROL */
281}
282
283STDMETHODIMP GuestFile::COMGETTER(EventSource)(IEventSource ** aEventSource)
284{
285#ifndef VBOX_WITH_GUEST_CONTROL
286 ReturnComNotImplemented();
287#else
288 CheckComArgOutPointerValid(aEventSource);
289
290 AutoCaller autoCaller(this);
291 if (FAILED(autoCaller.rc())) return autoCaller.rc();
292
293 /* No need to lock - lifetime constant. */
294 mEventSource.queryInterfaceTo(aEventSource);
295
296 return S_OK;
297#endif /* VBOX_WITH_GUEST_CONTROL */
298}
299
300STDMETHODIMP GuestFile::COMGETTER(FileName)(BSTR *aFileName)
301{
302#ifndef VBOX_WITH_GUEST_CONTROL
303 ReturnComNotImplemented();
304#else
305 AutoCaller autoCaller(this);
306 if (FAILED(autoCaller.rc())) return autoCaller.rc();
307
308 CheckComArgOutPointerValid(aFileName);
309
310 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
311
312 mData.mOpenInfo.mFileName.cloneTo(aFileName);
313
314 return S_OK;
315#endif /* VBOX_WITH_GUEST_CONTROL */
316}
317
318STDMETHODIMP GuestFile::COMGETTER(Id)(ULONG *aID)
319{
320#ifndef VBOX_WITH_GUEST_CONTROL
321 ReturnComNotImplemented();
322#else
323 AutoCaller autoCaller(this);
324 if (FAILED(autoCaller.rc())) return autoCaller.rc();
325
326 CheckComArgOutPointerValid(aID);
327
328 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
329
330 *aID = mData.mID;
331
332 return S_OK;
333#endif /* VBOX_WITH_GUEST_CONTROL */
334}
335
336STDMETHODIMP GuestFile::COMGETTER(InitialSize)(LONG64 *aInitialSize)
337{
338#ifndef VBOX_WITH_GUEST_CONTROL
339 ReturnComNotImplemented();
340#else
341 AutoCaller autoCaller(this);
342 if (FAILED(autoCaller.rc())) return autoCaller.rc();
343
344 CheckComArgOutPointerValid(aInitialSize);
345
346 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
347
348 *aInitialSize = mData.mInitialSize;
349
350 return S_OK;
351#endif /* VBOX_WITH_GUEST_CONTROL */
352}
353
354STDMETHODIMP GuestFile::COMGETTER(Offset)(LONG64 *aOffset)
355{
356#ifndef VBOX_WITH_GUEST_CONTROL
357 ReturnComNotImplemented();
358#else
359 AutoCaller autoCaller(this);
360 if (FAILED(autoCaller.rc())) return autoCaller.rc();
361
362 CheckComArgOutPointerValid(aOffset);
363
364 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
365
366 *aOffset = mData.mOffCurrent;
367
368 return S_OK;
369#endif /* VBOX_WITH_GUEST_CONTROL */
370}
371
372STDMETHODIMP GuestFile::COMGETTER(OpenMode)(BSTR *aOpenMode)
373{
374#ifndef VBOX_WITH_GUEST_CONTROL
375 ReturnComNotImplemented();
376#else
377 AutoCaller autoCaller(this);
378 if (FAILED(autoCaller.rc())) return autoCaller.rc();
379
380 CheckComArgOutPointerValid(aOpenMode);
381
382 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
383
384 mData.mOpenInfo.mOpenMode.cloneTo(aOpenMode);
385
386 return S_OK;
387#endif /* VBOX_WITH_GUEST_CONTROL */
388}
389
390STDMETHODIMP GuestFile::COMGETTER(Status)(FileStatus_T *aStatus)
391{
392#ifndef VBOX_WITH_GUEST_CONTROL
393 ReturnComNotImplemented();
394#else
395 LogFlowThisFuncEnter();
396
397 AutoCaller autoCaller(this);
398 if (FAILED(autoCaller.rc())) return autoCaller.rc();
399
400 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
401
402 *aStatus = mData.mStatus;
403
404 return S_OK;
405#endif /* VBOX_WITH_GUEST_CONTROL */
406}
407
408// private methods
409/////////////////////////////////////////////////////////////////////////////
410
411int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
412{
413 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
414 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
415
416 LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
417 mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
418
419 int vrc;
420 switch (pCbCtx->uFunction)
421 {
422 case GUEST_DISCONNECTED:
423 vrc = onGuestDisconnected(pCbCtx, pSvcCb);
424 break;
425
426 case GUEST_FILE_NOTIFY:
427 vrc = onFileNotify(pCbCtx, pSvcCb);
428 break;
429
430 default:
431 /* Silently ignore not implemented functions. */
432 vrc = VERR_NOT_SUPPORTED;
433 break;
434 }
435
436#ifdef DEBUG
437 LogFlowFuncLeaveRC(vrc);
438#endif
439 return vrc;
440}
441
442int GuestFile::closeFile(int *pGuestRc)
443{
444 LogFlowThisFunc(("strFile=%s\n", mData.mOpenInfo.mFileName.c_str()));
445
446 int vrc;
447
448 GuestWaitEvent *pEvent = NULL;
449 GuestEventTypes eventTypes;
450 try
451 {
452 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
453
454 vrc = registerWaitEvent(eventTypes, &pEvent);
455 }
456 catch (std::bad_alloc)
457 {
458 vrc = VERR_NO_MEMORY;
459 }
460
461 if (RT_FAILURE(vrc))
462 return vrc;
463
464 /* Prepare HGCM call. */
465 VBOXHGCMSVCPARM paParms[4];
466 int i = 0;
467 paParms[i++].setUInt32(pEvent->ContextID());
468 paParms[i++].setUInt32(mData.mID /* Guest file ID */);
469
470 vrc = sendCommand(HOST_FILE_CLOSE, i, paParms);
471 if (RT_SUCCESS(vrc))
472 vrc = waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */,
473 NULL /* FileStatus */, pGuestRc);
474 unregisterWaitEvent(pEvent);
475
476 LogFlowFuncLeaveRC(vrc);
477 return vrc;
478}
479
480/* static */
481Utf8Str GuestFile::guestErrorToString(int guestRc)
482{
483 Utf8Str strError;
484
485 /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
486 switch (guestRc)
487 {
488 case VERR_ALREADY_EXISTS:
489 strError += Utf8StrFmt(tr("File already exists"));
490 break;
491
492 case VERR_FILE_NOT_FOUND:
493 strError += Utf8StrFmt(tr("File not found"));
494 break;
495
496 case VERR_NET_HOST_NOT_FOUND:
497 strError += Utf8StrFmt(tr("Host name not found"));
498 break;
499
500 case VERR_SHARING_VIOLATION:
501 strError += Utf8StrFmt(tr("Sharing violation"));
502 break;
503
504 default:
505 strError += Utf8StrFmt("%Rrc", guestRc);
506 break;
507 }
508
509 return strError;
510}
511
512int GuestFile::onFileNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
513{
514 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
515 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
516
517 LogFlowThisFuncEnter();
518
519 if (pSvcCbData->mParms < 3)
520 return VERR_INVALID_PARAMETER;
521
522 int vrc = VINF_SUCCESS;
523
524 int idx = 1; /* Current parameter index. */
525 CALLBACKDATA_FILE_NOTIFY dataCb;
526 /* pSvcCb->mpaParms[0] always contains the context ID. */
527 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.uType);
528 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.rc);
529
530 FileStatus_T fileStatus = FileStatus_Undefined;
531 int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
532
533 LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
534 dataCb.uType, guestRc));
535
536 if (RT_FAILURE(guestRc))
537 {
538 int rc2 = setFileStatus(FileStatus_Error, guestRc);
539 AssertRC(rc2);
540
541 rc2 = signalWaitEventInternal(pCbCtx,
542 guestRc, NULL /* pPayload */);
543 AssertRC(rc2);
544
545 return VINF_SUCCESS; /* Report to the guest. */
546 }
547
548 switch (dataCb.uType)
549 {
550 case GUEST_FILE_NOTIFYTYPE_ERROR:
551 {
552 int rc2 = setFileStatus(FileStatus_Error, guestRc);
553 AssertRC(rc2);
554
555 break;
556 }
557
558 case GUEST_FILE_NOTIFYTYPE_OPEN:
559 {
560 if (pSvcCbData->mParms == 4)
561 {
562 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.open.uHandle);
563
564 {
565 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
566 AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
567 ("File ID %RU32 does not match context ID %RU32\n", mData.mID,
568 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
569
570 /* Set the initial offset. On the guest the whole opening operation
571 * would fail if an initial seek isn't possible. */
572 mData.mOffCurrent = mData.mOpenInfo.mInitialOffset;
573 }
574
575 /* Set the process status. */
576 int rc2 = setFileStatus(FileStatus_Open, guestRc);
577 AssertRC(rc2);
578 }
579 else
580 vrc = VERR_NOT_SUPPORTED;
581
582 break;
583 }
584
585 case GUEST_FILE_NOTIFYTYPE_CLOSE:
586 {
587 int rc2 = setFileStatus(FileStatus_Closed, guestRc);
588 AssertRC(rc2);
589
590 break;
591 }
592
593 case GUEST_FILE_NOTIFYTYPE_READ:
594 {
595 if (pSvcCbData->mParms == 4)
596 {
597 pSvcCbData->mpaParms[idx++].getPointer(&dataCb.u.read.pvData,
598 &dataCb.u.read.cbData);
599 uint32_t cbRead = dataCb.u.read.cbData;
600
601 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
602
603 mData.mOffCurrent += cbRead;
604
605 alock.release();
606
607 com::SafeArray<BYTE> data((size_t)cbRead);
608 data.initFrom((BYTE*)dataCb.u.read.pvData, cbRead);
609
610 fireGuestFileReadEvent(mEventSource, mSession, this, mData.mOffCurrent,
611 cbRead, ComSafeArrayAsInParam(data));
612 }
613 else
614 vrc = VERR_NOT_SUPPORTED;
615 break;
616 }
617
618 case GUEST_FILE_NOTIFYTYPE_WRITE:
619 {
620 if (pSvcCbData->mParms == 4)
621 {
622 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.write.cbWritten);
623
624 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
625
626 mData.mOffCurrent += dataCb.u.write.cbWritten;
627 uint64_t uOffCurrent = mData.mOffCurrent;
628
629 alock.release();
630
631 fireGuestFileWriteEvent(mEventSource, mSession, this, uOffCurrent,
632 dataCb.u.write.cbWritten);
633 }
634 else
635 vrc = VERR_NOT_SUPPORTED;
636 break;
637 }
638
639 case GUEST_FILE_NOTIFYTYPE_SEEK:
640 {
641 if (pSvcCbData->mParms == 4)
642 {
643 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.seek.uOffActual);
644
645 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
646
647 mData.mOffCurrent = dataCb.u.seek.uOffActual;
648
649 alock.release();
650
651 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
652 dataCb.u.seek.uOffActual, 0 /* Processed */);
653 }
654 else
655 vrc = VERR_NOT_SUPPORTED;
656 break;
657 }
658
659 case GUEST_FILE_NOTIFYTYPE_TELL:
660 {
661 if (pSvcCbData->mParms == 4)
662 {
663 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.tell.uOffActual);
664
665 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
666
667 mData.mOffCurrent = dataCb.u.tell.uOffActual;
668
669 alock.release();
670
671 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
672 dataCb.u.tell.uOffActual, 0 /* Processed */);
673 }
674 else
675 vrc = VERR_NOT_SUPPORTED;
676 break;
677 }
678
679 default:
680 vrc = VERR_NOT_SUPPORTED;
681 break;
682 }
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
691 LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n",
692 dataCb.uType, dataCb.rc));
693
694 LogFlowFuncLeaveRC(vrc);
695 return vrc;
696}
697
698int GuestFile::onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
699{
700 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
701 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
702
703 int vrc = setFileStatus(FileStatus_Down, VINF_SUCCESS);
704
705 LogFlowFuncLeaveRC(vrc);
706 return vrc;
707}
708
709int GuestFile::openFile(uint32_t uTimeoutMS, int *pGuestRc)
710{
711 LogFlowThisFuncEnter();
712
713 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
714
715 LogFlowThisFunc(("strFile=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%RU32, uOffset=%RU64\n",
716 mData.mOpenInfo.mFileName.c_str(), mData.mOpenInfo.mOpenMode.c_str(),
717 mData.mOpenInfo.mDisposition.c_str(), mData.mOpenInfo.mCreationMode, mData.mOpenInfo.mInitialOffset));
718 int vrc;
719
720 GuestWaitEvent *pEvent = NULL;
721 GuestEventTypes eventTypes;
722 try
723 {
724 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
725
726 vrc = registerWaitEvent(eventTypes, &pEvent);
727 }
728 catch (std::bad_alloc)
729 {
730 vrc = VERR_NO_MEMORY;
731 }
732
733 if (RT_FAILURE(vrc))
734 return vrc;
735
736 /* Prepare HGCM call. */
737 VBOXHGCMSVCPARM paParms[8];
738 int i = 0;
739 paParms[i++].setUInt32(pEvent->ContextID());
740 paParms[i++].setPointer((void*)mData.mOpenInfo.mFileName.c_str(),
741 (ULONG)mData.mOpenInfo.mFileName.length() + 1);
742 paParms[i++].setPointer((void*)mData.mOpenInfo.mOpenMode.c_str(),
743 (ULONG)mData.mOpenInfo.mOpenMode.length() + 1);
744 paParms[i++].setPointer((void*)mData.mOpenInfo.mDisposition.c_str(),
745 (ULONG)mData.mOpenInfo.mDisposition.length() + 1);
746 paParms[i++].setPointer((void*)mData.mOpenInfo.mSharingMode.c_str(),
747 (ULONG)mData.mOpenInfo.mSharingMode.length() + 1);
748 paParms[i++].setUInt32(mData.mOpenInfo.mCreationMode);
749 paParms[i++].setUInt64(mData.mOpenInfo.mInitialOffset);
750
751 alock.release(); /* Drop write lock before sending. */
752
753 vrc = sendCommand(HOST_FILE_OPEN, i, paParms);
754 if (RT_SUCCESS(vrc))
755 vrc = waitForStatusChange(pEvent, uTimeoutMS,
756 NULL /* FileStatus */, pGuestRc);
757
758 unregisterWaitEvent(pEvent);
759
760 LogFlowFuncLeaveRC(vrc);
761 return vrc;
762}
763
764int GuestFile::readData(uint32_t uSize, uint32_t uTimeoutMS,
765 void* pvData, uint32_t cbData, uint32_t* pcbRead)
766{
767 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
768 AssertReturn(cbData, VERR_INVALID_PARAMETER);
769
770 LogFlowThisFunc(("uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
771 uSize, uTimeoutMS, pvData, cbData));
772
773 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
774
775 int vrc;
776
777 GuestWaitEvent *pEvent = NULL;
778 GuestEventTypes eventTypes;
779 try
780 {
781 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
782 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
783
784 vrc = registerWaitEvent(eventTypes, &pEvent);
785 }
786 catch (std::bad_alloc)
787 {
788 vrc = VERR_NO_MEMORY;
789 }
790
791 if (RT_FAILURE(vrc))
792 return vrc;
793
794 /* Prepare HGCM call. */
795 VBOXHGCMSVCPARM paParms[4];
796 int i = 0;
797 paParms[i++].setUInt32(pEvent->ContextID());
798 paParms[i++].setUInt32(mData.mID /* File handle */);
799 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
800
801 alock.release(); /* Drop write lock before sending. */
802
803 uint32_t cbRead;
804 vrc = sendCommand(HOST_FILE_READ, i, paParms);
805 if (RT_SUCCESS(vrc))
806 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
807
808 if (RT_SUCCESS(vrc))
809 {
810 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
811
812 if (pcbRead)
813 *pcbRead = cbRead;
814 }
815
816 unregisterWaitEvent(pEvent);
817
818 LogFlowFuncLeaveRC(vrc);
819 return vrc;
820}
821
822int GuestFile::readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS,
823 void* pvData, size_t cbData, size_t* pcbRead)
824{
825 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
826 uOffset, uSize, uTimeoutMS, pvData, cbData));
827
828 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
829
830 int vrc;
831
832 GuestWaitEvent *pEvent = NULL;
833 GuestEventTypes eventTypes;
834 try
835 {
836 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
837 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
838
839 vrc = registerWaitEvent(eventTypes, &pEvent);
840 }
841 catch (std::bad_alloc)
842 {
843 vrc = VERR_NO_MEMORY;
844 }
845
846 if (RT_FAILURE(vrc))
847 return vrc;
848
849 /* Prepare HGCM call. */
850 VBOXHGCMSVCPARM paParms[4];
851 int i = 0;
852 paParms[i++].setUInt32(pEvent->ContextID());
853 paParms[i++].setUInt32(mData.mID /* File handle */);
854 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */);
855 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
856
857 alock.release(); /* Drop write lock before sending. */
858
859 uint32_t cbRead;
860 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms);
861 if (RT_SUCCESS(vrc))
862 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
863
864 if (RT_SUCCESS(vrc))
865 {
866 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
867
868 if (pcbRead)
869 *pcbRead = cbRead;
870 }
871
872 unregisterWaitEvent(pEvent);
873
874 LogFlowFuncLeaveRC(vrc);
875 return vrc;
876}
877
878int GuestFile::seekAt(int64_t iOffset, GUEST_FILE_SEEKTYPE eSeekType,
879 uint32_t uTimeoutMS, uint64_t *puOffset)
880{
881 LogFlowThisFunc(("iOffset=%RI64, uTimeoutMS=%RU32\n",
882 iOffset, uTimeoutMS));
883
884 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
885
886 int vrc;
887
888 GuestWaitEvent *pEvent = NULL;
889 GuestEventTypes eventTypes;
890 try
891 {
892 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
893 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
894
895 vrc = registerWaitEvent(eventTypes, &pEvent);
896 }
897 catch (std::bad_alloc)
898 {
899 vrc = VERR_NO_MEMORY;
900 }
901
902 if (RT_FAILURE(vrc))
903 return vrc;
904
905 /* Prepare HGCM call. */
906 VBOXHGCMSVCPARM paParms[4];
907 int i = 0;
908 paParms[i++].setUInt32(pEvent->ContextID());
909 paParms[i++].setUInt32(mData.mID /* File handle */);
910 paParms[i++].setUInt32(eSeekType /* Seek method */);
911 /** @todo uint64_t vs. int64_t! */
912 paParms[i++].setUInt64((uint64_t)iOffset /* Offset (in bytes) to start reading */);
913
914 alock.release(); /* Drop write lock before sending. */
915
916 vrc = sendCommand(HOST_FILE_SEEK, i, paParms);
917 if (RT_SUCCESS(vrc))
918 vrc = waitForOffsetChange(pEvent, uTimeoutMS, puOffset);
919
920 unregisterWaitEvent(pEvent);
921
922 LogFlowFuncLeaveRC(vrc);
923 return vrc;
924}
925
926/* static */
927HRESULT GuestFile::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
928{
929 AssertPtr(pInterface);
930 AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
931
932 return pInterface->setError(VBOX_E_IPRT_ERROR, GuestFile::guestErrorToString(guestRc).c_str());
933}
934
935int GuestFile::setFileStatus(FileStatus_T fileStatus, int fileRc)
936{
937 LogFlowThisFuncEnter();
938
939 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
940
941 LogFlowThisFunc(("oldStatus=%ld, newStatus=%ld, fileRc=%Rrc\n",
942 mData.mStatus, fileStatus, fileRc));
943
944#ifdef VBOX_STRICT
945 if (fileStatus == FileStatus_Error)
946 {
947 AssertMsg(RT_FAILURE(fileRc), ("Guest rc must be an error (%Rrc)\n", fileRc));
948 }
949 else
950 AssertMsg(RT_SUCCESS(fileRc), ("Guest rc must not be an error (%Rrc)\n", fileRc));
951#endif
952
953 if (mData.mStatus != fileStatus)
954 {
955 mData.mStatus = fileStatus;
956 mData.mLastError = fileRc;
957
958 ComObjPtr<VirtualBoxErrorInfo> errorInfo;
959 HRESULT hr = errorInfo.createObject();
960 ComAssertComRC(hr);
961 if (RT_FAILURE(fileRc))
962 {
963 hr = errorInfo->initEx(VBOX_E_IPRT_ERROR, fileRc,
964 COM_IIDOF(IGuestFile), getComponentName(),
965 guestErrorToString(fileRc));
966 ComAssertComRC(hr);
967 }
968
969 alock.release(); /* Release lock before firing off event. */
970
971 fireGuestFileStateChangedEvent(mEventSource, mSession,
972 this, fileStatus, errorInfo);
973 }
974
975 return VINF_SUCCESS;
976}
977
978int GuestFile::waitForOffsetChange(GuestWaitEvent *pEvent,
979 uint32_t uTimeoutMS, uint64_t *puOffset)
980{
981 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
982
983 int vrc = waitForEvent(pEvent, uTimeoutMS,
984 NULL /* Event type */, NULL /* IEvent */);
985 if (RT_SUCCESS(vrc))
986 {
987 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
988 const PCALLBACKDATA_FILE_NOTIFY pvCbData =
989 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
990 Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_SEEK);
991
992 if (puOffset)
993 *puOffset = pvCbData->u.seek.uOffActual;
994 }
995
996 return vrc;
997}
998
999int GuestFile::waitForRead(GuestWaitEvent *pEvent,
1000 uint32_t uTimeoutMS,
1001 void *pvData, size_t cbData, uint32_t *pcbRead)
1002{
1003 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1004
1005 int vrc = waitForEvent(pEvent, uTimeoutMS,
1006 NULL /* Event type */, NULL /* IEvent */);
1007 if (RT_SUCCESS(vrc))
1008 {
1009 Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
1010 const PCALLBACKDATA_FILE_NOTIFY pvCbData =
1011 (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
1012 Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_READ);
1013
1014 uint32_t cbRead = pvCbData->u.read.cbData;
1015 if ( cbRead
1016 && cbRead <= cbData)
1017 {
1018 memcpy(pvData,
1019 pvCbData->u.read.pvData, cbRead);
1020 }
1021 else
1022 vrc = VERR_BUFFER_OVERFLOW;
1023
1024 if (pcbRead)
1025 *pcbRead = cbRead;
1026 }
1027
1028 return vrc;
1029}
1030
1031int GuestFile::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
1032 FileStatus_T *pFileStatus, int *pGuestRc)
1033{
1034 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1035
1036 int vrc = waitForEvent(pEvent, uTimeoutMS,
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
1046
1047 if (pGuestRc)
1048 *pGuestRc = pvCbData->rc; /* int vs. uint32_t */
1049 }
1050
1051 return vrc;
1052}
1053
1054int GuestFile::waitForWrite(GuestWaitEvent *pEvent,
1055 uint32_t uTimeoutMS, uint32_t *pcbWritten)
1056{
1057 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1058
1059 int vrc = waitForEvent(pEvent, uTimeoutMS,
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;
1070 }
1071
1072 return vrc;
1073}
1074
1075int GuestFile::writeData(uint32_t uTimeoutMS, void *pvData, uint32_t cbData,
1076 uint32_t *pcbWritten)
1077{
1078 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1079 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1080
1081 LogFlowThisFunc(("uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1082 uTimeoutMS, pvData, cbData));
1083
1084 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1085
1086 int vrc;
1087
1088 GuestWaitEvent *pEvent = NULL;
1089 GuestEventTypes eventTypes;
1090 try
1091 {
1092 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1093 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1094
1095 vrc = registerWaitEvent(eventTypes, &pEvent);
1096 }
1097 catch (std::bad_alloc)
1098 {
1099 vrc = VERR_NO_MEMORY;
1100 }
1101
1102 if (RT_FAILURE(vrc))
1103 return vrc;
1104
1105 /* Prepare HGCM call. */
1106 VBOXHGCMSVCPARM paParms[8];
1107 int i = 0;
1108 paParms[i++].setUInt32(pEvent->ContextID());
1109 paParms[i++].setUInt32(mData.mID /* File handle */);
1110 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1111 paParms[i++].setPointer(pvData, cbData);
1112
1113 alock.release(); /* Drop write lock before sending. */
1114
1115 uint32_t cbWritten;
1116 vrc = sendCommand(HOST_FILE_WRITE, i, paParms);
1117 if (RT_SUCCESS(vrc))
1118 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1119
1120 if (RT_SUCCESS(vrc))
1121 {
1122 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1123
1124 if (cbWritten)
1125 *pcbWritten = cbWritten;
1126 }
1127
1128 unregisterWaitEvent(pEvent);
1129
1130 LogFlowFuncLeaveRC(vrc);
1131 return vrc;
1132}
1133
1134int GuestFile::writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS,
1135 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1136{
1137 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1138 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1139
1140 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1141 uOffset, uTimeoutMS, pvData, cbData));
1142
1143 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1144
1145 int vrc;
1146
1147 GuestWaitEvent *pEvent = NULL;
1148 GuestEventTypes eventTypes;
1149 try
1150 {
1151 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1152 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1153
1154 vrc = registerWaitEvent(eventTypes, &pEvent);
1155 }
1156 catch (std::bad_alloc)
1157 {
1158 vrc = VERR_NO_MEMORY;
1159 }
1160
1161 if (RT_FAILURE(vrc))
1162 return vrc;
1163
1164 /* Prepare HGCM call. */
1165 VBOXHGCMSVCPARM paParms[8];
1166 int i = 0;
1167 paParms[i++].setUInt32(pEvent->ContextID());
1168 paParms[i++].setUInt32(mData.mID /* File handle */);
1169 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */);
1170 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1171 paParms[i++].setPointer(pvData, cbData);
1172
1173 alock.release(); /* Drop write lock before sending. */
1174
1175 uint32_t cbWritten;
1176 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms);
1177 if (RT_SUCCESS(vrc))
1178 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1179
1180 if (RT_SUCCESS(vrc))
1181 {
1182 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1183
1184 if (cbWritten)
1185 *pcbWritten = cbWritten;
1186 }
1187
1188 unregisterWaitEvent(pEvent);
1189
1190 LogFlowFuncLeaveRC(vrc);
1191 return vrc;
1192}
1193
1194// implementation of public methods
1195/////////////////////////////////////////////////////////////////////////////
1196
1197STDMETHODIMP GuestFile::Close(void)
1198{
1199#ifndef VBOX_WITH_GUEST_CONTROL
1200 ReturnComNotImplemented();
1201#else
1202 LogFlowThisFuncEnter();
1203
1204 AutoCaller autoCaller(this);
1205 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1206
1207 /* Close file on guest. */
1208 int guestRc;
1209 int rc = closeFile(&guestRc);
1210 /* On failure don't return here, instead do all the cleanup
1211 * work first and then return an error. */
1212
1213 AssertPtr(mSession);
1214 int rc2 = mSession->fileRemoveFromList(this);
1215 if (RT_SUCCESS(rc))
1216 rc = rc2;
1217
1218 if (RT_FAILURE(rc))
1219 {
1220 if (rc == VERR_GSTCTL_GUEST_ERROR)
1221 return GuestFile::setErrorExternal(this, guestRc);
1222
1223 return setError(VBOX_E_IPRT_ERROR,
1224 tr("Closing guest file failed with %Rrc\n"), rc);
1225 }
1226
1227 LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
1228 return S_OK;
1229#endif /* VBOX_WITH_GUEST_CONTROL */
1230}
1231
1232STDMETHODIMP GuestFile::QueryInfo(IFsObjInfo **aInfo)
1233{
1234#ifndef VBOX_WITH_GUEST_CONTROL
1235 ReturnComNotImplemented();
1236#else
1237 AutoCaller autoCaller(this);
1238 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1239
1240 ReturnComNotImplemented();
1241#endif /* VBOX_WITH_GUEST_CONTROL */
1242}
1243
1244STDMETHODIMP GuestFile::Read(ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
1245{
1246#ifndef VBOX_WITH_GUEST_CONTROL
1247 ReturnComNotImplemented();
1248#else
1249 if (aToRead == 0)
1250 return setError(E_INVALIDARG, tr("The size to read is zero"));
1251 CheckComArgOutSafeArrayPointerValid(aData);
1252
1253 AutoCaller autoCaller(this);
1254 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1255
1256 com::SafeArray<BYTE> data((size_t)aToRead);
1257 Assert(data.size() >= aToRead);
1258
1259 HRESULT hr = S_OK;
1260
1261 uint32_t cbRead;
1262 int vrc = readData(aToRead, aTimeoutMS,
1263 data.raw(), aToRead, &cbRead);
1264 if (RT_SUCCESS(vrc))
1265 {
1266 if (data.size() != cbRead)
1267 data.resize(cbRead);
1268 data.detachTo(ComSafeArrayOutArg(aData));
1269 }
1270 else
1271 {
1272 switch (vrc)
1273 {
1274 default:
1275 hr = setError(VBOX_E_IPRT_ERROR,
1276 tr("Reading from file \"%s\" failed: %Rrc"),
1277 mData.mOpenInfo.mFileName.c_str(), vrc);
1278 break;
1279 }
1280 }
1281
1282 LogFlowFuncLeaveRC(vrc);
1283 return hr;
1284#endif /* VBOX_WITH_GUEST_CONTROL */
1285}
1286
1287STDMETHODIMP GuestFile::ReadAt(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
1288{
1289#ifndef VBOX_WITH_GUEST_CONTROL
1290 ReturnComNotImplemented();
1291#else
1292 if (aToRead == 0)
1293 return setError(E_INVALIDARG, tr("The size to read is zero"));
1294 CheckComArgOutSafeArrayPointerValid(aData);
1295
1296 AutoCaller autoCaller(this);
1297 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1298
1299 com::SafeArray<BYTE> data((size_t)aToRead);
1300 Assert(data.size() >= aToRead);
1301
1302 HRESULT hr = S_OK;
1303
1304 size_t cbRead;
1305 int vrc = readDataAt(aOffset, aToRead, aTimeoutMS,
1306 data.raw(), aToRead, &cbRead);
1307 if (RT_SUCCESS(vrc))
1308 {
1309 if (data.size() != cbRead)
1310 data.resize(cbRead);
1311 data.detachTo(ComSafeArrayOutArg(aData));
1312 }
1313 else
1314 {
1315 switch (vrc)
1316 {
1317 default:
1318 hr = setError(VBOX_E_IPRT_ERROR,
1319 tr("Reading from file \"%s\" (at offset %RU64) failed: %Rrc"),
1320 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1321 break;
1322 }
1323 }
1324
1325 LogFlowFuncLeaveRC(vrc);
1326 return hr;
1327#endif /* VBOX_WITH_GUEST_CONTROL */
1328}
1329
1330STDMETHODIMP GuestFile::Seek(LONG64 aOffset, FileSeekType_T aType)
1331{
1332#ifndef VBOX_WITH_GUEST_CONTROL
1333 ReturnComNotImplemented();
1334#else
1335 LogFlowThisFuncEnter();
1336
1337 AutoCaller autoCaller(this);
1338 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1339
1340 HRESULT hr = S_OK;
1341
1342 GUEST_FILE_SEEKTYPE eSeekType;
1343 switch (aType)
1344 {
1345 case FileSeekType_Set:
1346 eSeekType = GUEST_FILE_SEEKTYPE_BEGIN;
1347 break;
1348
1349 case FileSeekType_Current:
1350 eSeekType = GUEST_FILE_SEEKTYPE_CURRENT;
1351 break;
1352
1353 default:
1354 return setError(E_INVALIDARG, tr("Invalid seek type specified"));
1355 break; /* Never reached. */
1356 }
1357
1358 int vrc = seekAt(aOffset, eSeekType,
1359 30 * 1000 /* 30s timeout */, NULL /* puOffset */);
1360 if (RT_FAILURE(vrc))
1361 {
1362 switch (vrc)
1363 {
1364 default:
1365 hr = setError(VBOX_E_IPRT_ERROR,
1366 tr("Seeking file \"%s\" (to offset %RI64) failed: %Rrc"),
1367 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1368 break;
1369 }
1370 }
1371
1372 LogFlowFuncLeaveRC(vrc);
1373 return hr;
1374#endif /* VBOX_WITH_GUEST_CONTROL */
1375}
1376
1377STDMETHODIMP GuestFile::SetACL(IN_BSTR aACL)
1378{
1379#ifndef VBOX_WITH_GUEST_CONTROL
1380 ReturnComNotImplemented();
1381#else
1382 AutoCaller autoCaller(this);
1383 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1384
1385 ReturnComNotImplemented();
1386#endif /* VBOX_WITH_GUEST_CONTROL */
1387}
1388
1389STDMETHODIMP GuestFile::Write(ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
1390{
1391#ifndef VBOX_WITH_GUEST_CONTROL
1392 ReturnComNotImplemented();
1393#else
1394 LogFlowThisFuncEnter();
1395
1396 CheckComArgSafeArrayNotNull(aData);
1397 CheckComArgOutPointerValid(aWritten);
1398
1399 AutoCaller autoCaller(this);
1400 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1401
1402 HRESULT hr = S_OK;
1403
1404 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData));
1405 int vrc = writeData(aTimeoutMS, data.raw(), (uint32_t)data.size(),
1406 (uint32_t*)aWritten);
1407 if (RT_FAILURE(vrc))
1408 {
1409 switch (vrc)
1410 {
1411 default:
1412 hr = setError(VBOX_E_IPRT_ERROR,
1413 tr("Writing %zubytes to file \"%s\" failed: %Rrc"),
1414 data.size(), mData.mOpenInfo.mFileName.c_str(), vrc);
1415 break;
1416 }
1417 }
1418
1419 LogFlowFuncLeaveRC(vrc);
1420 return hr;
1421#endif /* VBOX_WITH_GUEST_CONTROL */
1422}
1423
1424STDMETHODIMP GuestFile::WriteAt(LONG64 aOffset, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
1425{
1426#ifndef VBOX_WITH_GUEST_CONTROL
1427 ReturnComNotImplemented();
1428#else
1429 LogFlowThisFuncEnter();
1430
1431 CheckComArgSafeArrayNotNull(aData);
1432 CheckComArgOutPointerValid(aWritten);
1433
1434 AutoCaller autoCaller(this);
1435 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1436
1437 HRESULT hr = S_OK;
1438
1439 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData));
1440 int vrc = writeData(aTimeoutMS, data.raw(), (uint32_t)data.size(),
1441 (uint32_t*)aWritten);
1442 if (RT_FAILURE(vrc))
1443 {
1444 switch (vrc)
1445 {
1446 default:
1447 hr = setError(VBOX_E_IPRT_ERROR,
1448 tr("Writing %zubytes to file \"%s\" (at offset %RU64) failed: %Rrc"),
1449 data.size(), mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1450 break;
1451 }
1452 }
1453
1454 LogFlowFuncLeaveRC(vrc);
1455 return hr;
1456#endif /* VBOX_WITH_GUEST_CONTROL */
1457}
1458
Note: See TracBrowser for help on using the repository browser.

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