VirtualBox

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

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

Main/IGuestFile: Changed disposition and openMode parameters being wstrings instead of ulongs (related to r88105), matching the IGuestSession::openFile / openFileEx calls.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.0 KB
Line 
1
2/* $Id: GuestFileImpl.cpp 47836 2013-08-19 09:16:40Z 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->signalWaitEvents(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(InitialSize)(LONG64 *aInitialSize)
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(aInitialSize);
327
328 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
329
330 *aInitialSize = mData.mInitialSize;
331
332 return S_OK;
333#endif /* VBOX_WITH_GUEST_CONTROL */
334}
335
336STDMETHODIMP GuestFile::COMGETTER(Offset)(LONG64 *aOffset)
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(aOffset);
345
346 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
347
348 *aOffset = mData.mOffCurrent;
349
350 return S_OK;
351#endif /* VBOX_WITH_GUEST_CONTROL */
352}
353
354STDMETHODIMP GuestFile::COMGETTER(OpenMode)(BSTR *aOpenMode)
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(aOpenMode);
363
364 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
365
366 mData.mOpenInfo.mOpenMode.cloneTo(aOpenMode);
367
368 return S_OK;
369#endif /* VBOX_WITH_GUEST_CONTROL */
370}
371
372STDMETHODIMP GuestFile::COMGETTER(Status)(FileStatus_T *aStatus)
373{
374#ifndef VBOX_WITH_GUEST_CONTROL
375 ReturnComNotImplemented();
376#else
377 LogFlowThisFuncEnter();
378
379 AutoCaller autoCaller(this);
380 if (FAILED(autoCaller.rc())) return autoCaller.rc();
381
382 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
383
384 *aStatus = mData.mStatus;
385
386 return S_OK;
387#endif /* VBOX_WITH_GUEST_CONTROL */
388}
389
390// private methods
391/////////////////////////////////////////////////////////////////////////////
392
393int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
394{
395#ifdef DEBUG
396 LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
397 mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
398#endif
399 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
400
401 int vrc;
402 switch (pCbCtx->uFunction)
403 {
404 case GUEST_DISCONNECTED:
405 vrc = onGuestDisconnected(pCbCtx, pSvcCb);
406 break;
407
408 case GUEST_FILE_NOTIFY:
409 vrc = onFileNotify(pCbCtx, pSvcCb);
410 break;
411
412 default:
413 /* Silently ignore not implemented functions. */
414 vrc = VERR_NOT_SUPPORTED;
415 break;
416 }
417
418#ifdef DEBUG
419 LogFlowFuncLeaveRC(vrc);
420#endif
421 return vrc;
422}
423
424int GuestFile::closeFile(int *pGuestRc)
425{
426 LogFlowThisFunc(("strFile=%s\n", mData.mOpenInfo.mFileName.c_str()));
427
428 int vrc;
429
430 GuestWaitEvent *pEvent = NULL;
431 std::list < VBoxEventType_T > eventTypes;
432 try
433 {
434 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
435
436 vrc = registerWaitEvent(eventTypes, &pEvent);
437 }
438 catch (std::bad_alloc)
439 {
440 vrc = VERR_NO_MEMORY;
441 }
442
443 if (RT_FAILURE(vrc))
444 return vrc;
445
446 /* Prepare HGCM call. */
447 VBOXHGCMSVCPARM paParms[4];
448 int i = 0;
449 paParms[i++].setUInt32(pEvent->ContextID());
450 paParms[i++].setUInt32(mData.mID /* Guest file ID */);
451
452 vrc = sendCommand(HOST_FILE_CLOSE, i, paParms);
453 if (RT_SUCCESS(vrc))
454 vrc = waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */,
455 NULL /* FileStatus */, pGuestRc);
456 unregisterWaitEvent(pEvent);
457
458 LogFlowFuncLeaveRC(vrc);
459 return vrc;
460}
461
462/* static */
463Utf8Str GuestFile::guestErrorToString(int guestRc)
464{
465 Utf8Str strError;
466
467 /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
468 switch (guestRc)
469 {
470 case VERR_INVALID_VM_HANDLE:
471 strError += Utf8StrFmt(tr("VMM device is not available (is the VM running?)"));
472 break;
473
474 case VERR_HGCM_SERVICE_NOT_FOUND:
475 strError += Utf8StrFmt(tr("The guest execution service is not available"));
476 break;
477
478 case VERR_TIMEOUT:
479 strError += Utf8StrFmt(tr("The guest did not respond within time"));
480 break;
481
482 case VERR_CANCELLED:
483 strError += Utf8StrFmt(tr("The session operation was canceled"));
484 break;
485
486 case VERR_MAX_PROCS_REACHED:
487 strError += Utf8StrFmt(tr("Maximum number of concurrent guest files has been reached"));
488 break;
489
490 case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
491 strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
492 break;
493
494 case VERR_NOT_FOUND:
495 strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
496 break;
497
498 default:
499 strError += Utf8StrFmt("%Rrc", guestRc);
500 break;
501 }
502
503 return strError;
504}
505
506int GuestFile::onFileNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
507{
508 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
509 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
510
511 LogFlowThisFuncEnter();
512
513 if (pSvcCbData->mParms < 3)
514 return VERR_INVALID_PARAMETER;
515
516 int vrc = VINF_SUCCESS;
517
518 int idx = 1; /* Current parameter index. */
519 CALLBACKDATA_FILE_NOTIFY dataCb;
520 /* pSvcCb->mpaParms[0] always contains the context ID. */
521 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.uType);
522 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.rc);
523
524 FileStatus_T fileStatus = FileStatus_Undefined;
525 int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
526
527 LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
528 dataCb.uType, guestRc));
529
530 if (RT_FAILURE(guestRc))
531 {
532 int rc2 = setFileStatus(FileStatus_Error, guestRc);
533 AssertRC(rc2);
534
535 return VINF_SUCCESS; /* Report to the guest. */
536 }
537
538 switch (dataCb.uType)
539 {
540 case GUEST_FILE_NOTIFYTYPE_ERROR:
541 {
542 int rc2 = setFileStatus(FileStatus_Error, guestRc);
543 AssertRC(rc2);
544 break;
545 }
546
547 case GUEST_FILE_NOTIFYTYPE_OPEN:
548 {
549 if (pSvcCbData->mParms == 4)
550 {
551 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.open.uHandle);
552
553 {
554 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
555 AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
556 ("File ID %RU32 does not match context ID %RU32\n", mData.mID,
557 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
558 }
559
560 /* Set the process status. */
561 int rc2 = setFileStatus(FileStatus_Open, guestRc);
562 if (RT_SUCCESS(vrc))
563 vrc = rc2;
564 }
565 else
566 vrc = VERR_NOT_SUPPORTED;
567
568 break;
569 }
570
571 case GUEST_FILE_NOTIFYTYPE_CLOSE:
572 {
573 int rc2 = setFileStatus(FileStatus_Closed, guestRc);
574 AssertRC(rc2);
575
576 break;
577 }
578
579 case GUEST_FILE_NOTIFYTYPE_READ:
580 {
581 if (pSvcCbData->mParms == 4)
582 {
583 pSvcCbData->mpaParms[idx++].getPointer(&dataCb.u.read.pvData,
584 &dataCb.u.read.cbData);
585 uint32_t cbRead = dataCb.u.read.cbData;
586 if (cbRead)
587 {
588 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
589
590 mData.mOffCurrent += cbRead;
591
592 alock.release();
593
594 com::SafeArray<BYTE> data((size_t)cbRead);
595 data.initFrom((BYTE*)dataCb.u.read.pvData, cbRead);
596
597 fireGuestFileReadEvent(mEventSource, mSession, this, mData.mOffCurrent,
598 cbRead, ComSafeArrayAsInParam(data));
599 }
600 }
601 else
602 vrc = VERR_NOT_SUPPORTED;
603 break;
604 }
605
606 case GUEST_FILE_NOTIFYTYPE_WRITE:
607 {
608 if (pSvcCbData->mParms == 4)
609 {
610 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.write.cbWritten);
611
612 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
613
614 mData.mOffCurrent += dataCb.u.write.cbWritten;
615 uint64_t uOffCurrent = mData.mOffCurrent;
616
617 alock.release();
618
619 if (dataCb.u.write.cbWritten)
620 fireGuestFileWriteEvent(mEventSource, mSession, this, uOffCurrent,
621 dataCb.u.write.cbWritten);
622 }
623 else
624 vrc = VERR_NOT_SUPPORTED;
625 break;
626 }
627
628 case GUEST_FILE_NOTIFYTYPE_SEEK:
629 {
630 if (pSvcCbData->mParms == 4)
631 {
632 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.seek.uOffActual);
633
634 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
635
636 mData.mOffCurrent = dataCb.u.seek.uOffActual;
637 uint64_t uOffCurrent = mData.mOffCurrent;
638
639 alock.release();
640
641 if (dataCb.u.seek.uOffActual)
642 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
643 uOffCurrent, 0 /* Processed */);
644 }
645 else
646 vrc = VERR_NOT_SUPPORTED;
647 break;
648 }
649
650 case GUEST_FILE_NOTIFYTYPE_TELL:
651 {
652 if (pSvcCbData->mParms == 4)
653 {
654 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.tell.uOffActual);
655
656 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
657
658 if (mData.mOffCurrent != dataCb.u.tell.uOffActual)
659 {
660 mData.mOffCurrent = dataCb.u.tell.uOffActual;
661 uint64_t uOffCurrent = mData.mOffCurrent;
662
663 alock.release();
664
665 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
666 uOffCurrent, 0 /* Processed */);
667 }
668 }
669 else
670 vrc = VERR_NOT_SUPPORTED;
671 break;
672 }
673
674 default:
675 vrc = VERR_NOT_SUPPORTED;
676 break;
677 }
678
679 LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n",
680 dataCb.uType, dataCb.rc));
681
682 LogFlowFuncLeaveRC(vrc);
683 return vrc;
684}
685
686int GuestFile::onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
687{
688 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
689 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
690
691 int vrc = setFileStatus(FileStatus_Down, VINF_SUCCESS);
692
693 LogFlowFuncLeaveRC(vrc);
694 return vrc;
695}
696
697int GuestFile::openFile(uint32_t uTimeoutMS, int *pGuestRc)
698{
699 LogFlowThisFuncEnter();
700
701 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
702
703 LogFlowThisFunc(("strFile=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%RU32, uOffset=%RU64\n",
704 mData.mOpenInfo.mFileName.c_str(), mData.mOpenInfo.mOpenMode.c_str(),
705 mData.mOpenInfo.mDisposition.c_str(), mData.mOpenInfo.mCreationMode, mData.mOpenInfo.mInitialOffset));
706 int vrc;
707
708 GuestWaitEvent *pEvent = NULL;
709 std::list < VBoxEventType_T > eventTypes;
710 try
711 {
712 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
713
714 vrc = registerWaitEvent(eventTypes, &pEvent);
715 }
716 catch (std::bad_alloc)
717 {
718 vrc = VERR_NO_MEMORY;
719 }
720
721 if (RT_FAILURE(vrc))
722 return vrc;
723
724 /* Prepare HGCM call. */
725 VBOXHGCMSVCPARM paParms[8];
726 int i = 0;
727 paParms[i++].setUInt32(pEvent->ContextID());
728 paParms[i++].setPointer((void*)mData.mOpenInfo.mFileName.c_str(),
729 (ULONG)mData.mOpenInfo.mFileName.length() + 1);
730 paParms[i++].setPointer((void*)mData.mOpenInfo.mOpenMode.c_str(),
731 (ULONG)mData.mOpenInfo.mOpenMode.length() + 1);
732 paParms[i++].setPointer((void*)mData.mOpenInfo.mDisposition.c_str(),
733 (ULONG)mData.mOpenInfo.mDisposition.length() + 1);
734 paParms[i++].setPointer((void*)mData.mOpenInfo.mSharingMode.c_str(),
735 (ULONG)mData.mOpenInfo.mSharingMode.length() + 1);
736 paParms[i++].setUInt32(mData.mOpenInfo.mCreationMode);
737 paParms[i++].setUInt64(mData.mOpenInfo.mInitialOffset);
738
739 alock.release(); /* Drop read lock before sending. */
740
741 vrc = sendCommand(HOST_FILE_OPEN, i, paParms);
742 if (RT_SUCCESS(vrc))
743 vrc = waitForStatusChange(pEvent, uTimeoutMS,
744 NULL /* FileStatus */, pGuestRc);
745
746 unregisterWaitEvent(pEvent);
747
748 LogFlowFuncLeaveRC(vrc);
749 return vrc;
750}
751
752int GuestFile::readData(uint32_t uSize, uint32_t uTimeoutMS,
753 void* pvData, uint32_t cbData, uint32_t* pcbRead)
754{
755 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
756 AssertReturn(cbData, VERR_INVALID_PARAMETER);
757
758 LogFlowThisFunc(("uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
759 uSize, uTimeoutMS, pvData, cbData));
760 int vrc;
761
762 GuestWaitEvent *pEvent = NULL;
763 std::list < VBoxEventType_T > eventTypes;
764 try
765 {
766 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
767 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
768
769 vrc = registerWaitEvent(eventTypes, &pEvent);
770 }
771 catch (std::bad_alloc)
772 {
773 vrc = VERR_NO_MEMORY;
774 }
775
776 if (RT_FAILURE(vrc))
777 return vrc;
778
779 /* Prepare HGCM call. */
780 VBOXHGCMSVCPARM paParms[4];
781 int i = 0;
782 paParms[i++].setUInt32(pEvent->ContextID());
783 paParms[i++].setUInt32(mData.mID /* File handle */);
784 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
785
786 uint32_t cbRead;
787 vrc = sendCommand(HOST_FILE_READ, i, paParms);
788 if (RT_SUCCESS(vrc))
789 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
790
791 if (RT_SUCCESS(vrc))
792 {
793 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
794
795 if (pcbRead)
796 *pcbRead = cbRead;
797 }
798
799 unregisterWaitEvent(pEvent);
800
801 LogFlowFuncLeaveRC(vrc);
802 return vrc;
803}
804
805int GuestFile::readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS,
806 void* pvData, size_t cbData, size_t* pcbRead)
807{
808 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
809 uOffset, uSize, uTimeoutMS, pvData, cbData));
810 int vrc;
811
812 GuestWaitEvent *pEvent = NULL;
813 std::list < VBoxEventType_T > eventTypes;
814 try
815 {
816 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
817 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
818
819 vrc = registerWaitEvent(eventTypes, &pEvent);
820 }
821 catch (std::bad_alloc)
822 {
823 vrc = VERR_NO_MEMORY;
824 }
825
826 if (RT_FAILURE(vrc))
827 return vrc;
828
829 /* Prepare HGCM call. */
830 VBOXHGCMSVCPARM paParms[4];
831 int i = 0;
832 paParms[i++].setUInt32(pEvent->ContextID());
833 paParms[i++].setUInt32(mData.mID /* File handle */);
834 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */);
835 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
836
837 uint32_t cbRead;
838 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms);
839 if (RT_SUCCESS(vrc))
840 vrc = waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
841
842 if (RT_SUCCESS(vrc))
843 {
844 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
845
846 if (pcbRead)
847 *pcbRead = cbRead;
848 }
849
850 unregisterWaitEvent(pEvent);
851
852 LogFlowFuncLeaveRC(vrc);
853 return vrc;
854}
855
856int GuestFile::seekAt(uint64_t uOffset, GUEST_FILE_SEEKTYPE eSeekType,
857 uint32_t uTimeoutMS, uint64_t *puOffset)
858{
859 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32\n",
860 uOffset, uTimeoutMS));
861 int vrc;
862
863 GuestWaitEvent *pEvent = NULL;
864 std::list < VBoxEventType_T > eventTypes;
865 try
866 {
867 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
868 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
869
870 vrc = registerWaitEvent(eventTypes, &pEvent);
871 }
872 catch (std::bad_alloc)
873 {
874 vrc = VERR_NO_MEMORY;
875 }
876
877 if (RT_FAILURE(vrc))
878 return vrc;
879
880 /* Prepare HGCM call. */
881 VBOXHGCMSVCPARM paParms[4];
882 int i = 0;
883 paParms[i++].setUInt32(pEvent->ContextID());
884 paParms[i++].setUInt32(mData.mID /* File handle */);
885 paParms[i++].setUInt32(eSeekType /* Seek method */);
886 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */);
887
888 vrc = sendCommand(HOST_FILE_SEEK, i, paParms);
889 if (RT_SUCCESS(vrc))
890 vrc = waitForOffsetChange(pEvent, uTimeoutMS, puOffset);
891
892 unregisterWaitEvent(pEvent);
893
894 LogFlowFuncLeaveRC(vrc);
895 return vrc;
896}
897
898/* static */
899HRESULT GuestFile::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
900{
901 AssertPtr(pInterface);
902 AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
903
904 return pInterface->setError(VBOX_E_IPRT_ERROR, GuestFile::guestErrorToString(guestRc).c_str());
905}
906
907int GuestFile::setFileStatus(FileStatus_T fileStatus, int fileRc)
908{
909 LogFlowThisFuncEnter();
910
911 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
912
913 LogFlowThisFunc(("oldStatus=%ld, newStatus=%ld, fileRc=%Rrc\n",
914 mData.mStatus, fileStatus, fileRc));
915
916#ifdef VBOX_STRICT
917 if (fileStatus == FileStatus_Error)
918 {
919 AssertMsg(RT_FAILURE(fileRc), ("Guest rc must be an error (%Rrc)\n", fileRc));
920 }
921 else
922 AssertMsg(RT_SUCCESS(fileRc), ("Guest rc must not be an error (%Rrc)\n", fileRc));
923#endif
924
925 if (mData.mStatus != fileStatus)
926 {
927 mData.mStatus = fileStatus;
928 mData.mLastError = fileRc;
929
930 ComObjPtr<VirtualBoxErrorInfo> errorInfo;
931 HRESULT hr = errorInfo.createObject();
932 ComAssertComRC(hr);
933 if (RT_FAILURE(fileRc))
934 {
935 hr = errorInfo->initEx(VBOX_E_IPRT_ERROR, fileRc,
936 COM_IIDOF(IGuestFile), getComponentName(),
937 guestErrorToString(fileRc));
938 ComAssertComRC(hr);
939 }
940
941 /* Copy over necessary data before releasing lock again. */
942 FileStatus_T fileStatus = mData.mStatus;
943
944 alock.release(); /* Release lock before firing off event. */
945
946 fireGuestFileStateChangedEvent(mEventSource, mSession,
947 this, fileStatus, errorInfo);
948 }
949
950 return VINF_SUCCESS;
951}
952
953int GuestFile::waitForOffsetChange(GuestWaitEvent *pEvent,
954 uint32_t uTimeoutMS, uint64_t *puOffset)
955{
956 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
957
958 VBoxEventType_T evtType;
959 ComPtr<IEvent> pIEvent;
960 int vrc = waitForEvent(pEvent, uTimeoutMS,
961 &evtType, pIEvent.asOutParam());
962 if (RT_SUCCESS(vrc))
963 {
964 if (evtType == VBoxEventType_OnGuestFileOffsetChanged)
965 {
966 if (puOffset)
967 {
968 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent;
969 Assert(!pFileEvent.isNull());
970
971 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset);
972 ComAssertComRC(hr);
973 }
974 }
975 else
976 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
977 }
978
979 return vrc;
980}
981
982int GuestFile::waitForRead(GuestWaitEvent *pEvent,
983 uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead)
984{
985 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
986
987 VBoxEventType_T evtType;
988 ComPtr<IEvent> pIEvent;
989 int vrc = waitForEvent(pEvent, uTimeoutMS,
990 &evtType, pIEvent.asOutParam());
991 if (RT_SUCCESS(vrc))
992 {
993 if (evtType == VBoxEventType_OnGuestFileRead)
994 {
995 ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent;
996 Assert(!pFileEvent.isNull());
997
998 HRESULT hr;
999 if (pvData)
1000 {
1001 com::SafeArray <BYTE> data;
1002 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
1003 ComAssertComRC(hr);
1004 size_t cbRead = data.size();
1005 if ( cbRead
1006 && cbRead <= cbData)
1007 {
1008 memcpy(pvData, data.raw(), data.size());
1009 }
1010 else
1011 vrc = VERR_BUFFER_OVERFLOW;
1012 }
1013 if (pcbRead)
1014 {
1015 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead);
1016 ComAssertComRC(hr);
1017 }
1018 }
1019 else
1020 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
1021 }
1022
1023 return vrc;
1024}
1025
1026int GuestFile::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
1027 FileStatus_T *pFileStatus, int *pGuestRc)
1028{
1029 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1030 /* pFileStatus is optional. */
1031
1032 VBoxEventType_T evtType;
1033 ComPtr<IEvent> pIEvent;
1034 int vrc = waitForEvent(pEvent, uTimeoutMS,
1035 &evtType, pIEvent.asOutParam());
1036 if (RT_SUCCESS(vrc))
1037 {
1038 Assert(evtType == VBoxEventType_OnGuestFileStateChanged);
1039 ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent;
1040 Assert(!pFileEvent.isNull());
1041
1042 HRESULT hr;
1043 if (pFileStatus)
1044 {
1045 hr = pFileEvent->COMGETTER(Status)(pFileStatus);
1046 ComAssertComRC(hr);
1047 }
1048
1049 ComPtr<IVirtualBoxErrorInfo> errorInfo;
1050 hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam());
1051 ComAssertComRC(hr);
1052
1053 LONG lGuestRc;
1054 hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
1055 ComAssertComRC(hr);
1056
1057 LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
1058 lGuestRc, lGuestRc));
1059
1060 if (RT_FAILURE((int)lGuestRc))
1061 vrc = VERR_GSTCTL_GUEST_ERROR;
1062
1063 if (pGuestRc)
1064 *pGuestRc = (int)lGuestRc;
1065 }
1066
1067 return vrc;
1068}
1069
1070int GuestFile::waitForWrite(GuestWaitEvent *pEvent,
1071 uint32_t uTimeoutMS, uint32_t *pcbWritten)
1072{
1073 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1074
1075 VBoxEventType_T evtType;
1076 ComPtr<IEvent> pIEvent;
1077 int vrc = waitForEvent(pEvent, uTimeoutMS,
1078 &evtType, pIEvent.asOutParam());
1079 if (RT_SUCCESS(vrc))
1080 {
1081 if (evtType == VBoxEventType_OnGuestFileWrite)
1082 {
1083 if (pcbWritten)
1084 {
1085 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent;
1086 Assert(!pFileEvent.isNull());
1087
1088 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten);
1089 ComAssertComRC(hr);
1090 }
1091 }
1092 else
1093 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
1094 }
1095
1096 return vrc;
1097}
1098
1099int GuestFile::writeData(uint32_t uTimeoutMS, void *pvData, uint32_t cbData,
1100 uint32_t *pcbWritten)
1101{
1102 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1103 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1104
1105 LogFlowThisFunc(("uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1106 uTimeoutMS, pvData, cbData));
1107 int vrc;
1108
1109 GuestWaitEvent *pEvent = NULL;
1110 std::list < VBoxEventType_T > eventTypes;
1111 try
1112 {
1113 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1114 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1115
1116 vrc = registerWaitEvent(eventTypes, &pEvent);
1117 }
1118 catch (std::bad_alloc)
1119 {
1120 vrc = VERR_NO_MEMORY;
1121 }
1122
1123 if (RT_FAILURE(vrc))
1124 return vrc;
1125
1126 /* Prepare HGCM call. */
1127 VBOXHGCMSVCPARM paParms[8];
1128 int i = 0;
1129 paParms[i++].setUInt32(pEvent->ContextID());
1130 paParms[i++].setUInt32(mData.mID /* File handle */);
1131 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1132 paParms[i++].setPointer(pvData, cbData);
1133
1134 uint32_t cbWritten;
1135 vrc = sendCommand(HOST_FILE_WRITE, i, paParms);
1136 if (RT_SUCCESS(vrc))
1137 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1138
1139 if (RT_SUCCESS(vrc))
1140 {
1141 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1142
1143 if (cbWritten)
1144 *pcbWritten = cbWritten;
1145 }
1146
1147 unregisterWaitEvent(pEvent);
1148
1149 LogFlowFuncLeaveRC(vrc);
1150 return vrc;
1151}
1152
1153int GuestFile::writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS,
1154 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1155{
1156 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1157 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1158
1159 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1160 uOffset, uTimeoutMS, pvData, cbData));
1161 int vrc;
1162
1163 GuestWaitEvent *pEvent = NULL;
1164 std::list < VBoxEventType_T > eventTypes;
1165 try
1166 {
1167 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1168 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1169
1170 vrc = registerWaitEvent(eventTypes, &pEvent);
1171 }
1172 catch (std::bad_alloc)
1173 {
1174 vrc = VERR_NO_MEMORY;
1175 }
1176
1177 if (RT_FAILURE(vrc))
1178 return vrc;
1179
1180 /* Prepare HGCM call. */
1181 VBOXHGCMSVCPARM paParms[8];
1182 int i = 0;
1183 paParms[i++].setUInt32(pEvent->ContextID());
1184 paParms[i++].setUInt32(mData.mID /* File handle */);
1185 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */);
1186 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1187 paParms[i++].setPointer(pvData, cbData);
1188
1189 uint32_t cbWritten;
1190 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms);
1191 if (RT_SUCCESS(vrc))
1192 vrc = waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1193
1194 if (RT_SUCCESS(vrc))
1195 {
1196 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1197
1198 if (cbWritten)
1199 *pcbWritten = cbWritten;
1200 }
1201
1202 unregisterWaitEvent(pEvent);
1203
1204 LogFlowFuncLeaveRC(vrc);
1205 return vrc;
1206}
1207
1208// implementation of public methods
1209/////////////////////////////////////////////////////////////////////////////
1210
1211STDMETHODIMP GuestFile::Close(void)
1212{
1213#ifndef VBOX_WITH_GUEST_CONTROL
1214 ReturnComNotImplemented();
1215#else
1216 LogFlowThisFuncEnter();
1217
1218 AutoCaller autoCaller(this);
1219 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1220
1221 /* Close file on guest. */
1222 int guestRc;
1223 int rc = closeFile(&guestRc);
1224 /* On failure don't return here, instead do all the cleanup
1225 * work first and then return an error. */
1226
1227 AssertPtr(mSession);
1228 int rc2 = mSession->fileRemoveFromList(this);
1229 if (RT_SUCCESS(rc))
1230 rc = rc2;
1231
1232 if (RT_FAILURE(rc))
1233 {
1234 if (rc == VERR_GSTCTL_GUEST_ERROR)
1235 return GuestFile::setErrorExternal(this, guestRc);
1236
1237 return setError(VBOX_E_IPRT_ERROR,
1238 tr("Closing guest file failed with %Rrc\n"), rc);
1239 }
1240
1241 LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
1242 return S_OK;
1243#endif /* VBOX_WITH_GUEST_CONTROL */
1244}
1245
1246STDMETHODIMP GuestFile::QueryInfo(IFsObjInfo **aInfo)
1247{
1248#ifndef VBOX_WITH_GUEST_CONTROL
1249 ReturnComNotImplemented();
1250#else
1251 AutoCaller autoCaller(this);
1252 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1253
1254 ReturnComNotImplemented();
1255#endif /* VBOX_WITH_GUEST_CONTROL */
1256}
1257
1258STDMETHODIMP GuestFile::Read(ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
1259{
1260#ifndef VBOX_WITH_GUEST_CONTROL
1261 ReturnComNotImplemented();
1262#else
1263 if (aToRead == 0)
1264 return setError(E_INVALIDARG, tr("The size to read is zero"));
1265 CheckComArgOutSafeArrayPointerValid(aData);
1266
1267 AutoCaller autoCaller(this);
1268 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1269
1270 com::SafeArray<BYTE> data((size_t)aToRead);
1271 Assert(data.size() >= aToRead);
1272
1273 HRESULT hr = S_OK;
1274
1275 uint32_t cbRead;
1276 int vrc = readData(aToRead, aTimeoutMS,
1277 data.raw(), aToRead, &cbRead);
1278 if (RT_SUCCESS(vrc))
1279 {
1280 if (data.size() != cbRead)
1281 data.resize(cbRead);
1282 data.detachTo(ComSafeArrayOutArg(aData));
1283 }
1284 else
1285 {
1286 switch (vrc)
1287 {
1288 default:
1289 hr = setError(VBOX_E_IPRT_ERROR,
1290 tr("Reading from file \"%s\" failed: %Rrc"),
1291 mData.mOpenInfo.mFileName.c_str(), vrc);
1292 break;
1293 }
1294 }
1295
1296 LogFlowFuncLeaveRC(vrc);
1297 return hr;
1298#endif /* VBOX_WITH_GUEST_CONTROL */
1299}
1300
1301STDMETHODIMP GuestFile::ReadAt(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
1302{
1303#ifndef VBOX_WITH_GUEST_CONTROL
1304 ReturnComNotImplemented();
1305#else
1306 if (aToRead == 0)
1307 return setError(E_INVALIDARG, tr("The size to read is zero"));
1308 CheckComArgOutSafeArrayPointerValid(aData);
1309
1310 AutoCaller autoCaller(this);
1311 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1312
1313 com::SafeArray<BYTE> data((size_t)aToRead);
1314 Assert(data.size() >= aToRead);
1315
1316 HRESULT hr = S_OK;
1317
1318 size_t cbRead;
1319 int vrc = readDataAt(aOffset, aToRead, aTimeoutMS,
1320 data.raw(), aToRead, &cbRead);
1321 if (RT_SUCCESS(vrc))
1322 {
1323 if (data.size() != cbRead)
1324 data.resize(cbRead);
1325 data.detachTo(ComSafeArrayOutArg(aData));
1326 }
1327 else
1328 {
1329 switch (vrc)
1330 {
1331 default:
1332 hr = setError(VBOX_E_IPRT_ERROR,
1333 tr("Reading from file \"%s\" (at offset %RU64) failed: %Rrc"),
1334 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1335 break;
1336 }
1337 }
1338
1339 LogFlowFuncLeaveRC(vrc);
1340 return hr;
1341#endif /* VBOX_WITH_GUEST_CONTROL */
1342}
1343
1344STDMETHODIMP GuestFile::Seek(LONG64 aOffset, FileSeekType_T aType)
1345{
1346#ifndef VBOX_WITH_GUEST_CONTROL
1347 ReturnComNotImplemented();
1348#else
1349 LogFlowThisFuncEnter();
1350
1351 AutoCaller autoCaller(this);
1352 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1353
1354 HRESULT hr = S_OK;
1355
1356 GUEST_FILE_SEEKTYPE eSeekType;
1357 switch (aType)
1358 {
1359 case FileSeekType_Set:
1360 eSeekType = GUEST_FILE_SEEKTYPE_BEGIN;
1361 break;
1362
1363 case FileSeekType_Current:
1364 eSeekType = GUEST_FILE_SEEKTYPE_CURRENT;
1365 break;
1366
1367 default:
1368 return setError(E_INVALIDARG, tr("Invalid seek type specified"));
1369 break;
1370 }
1371
1372 int vrc = seekAt(aOffset, eSeekType,
1373 30 * 1000 /* 30s timeout */, NULL /* puOffset */);
1374 if (RT_FAILURE(vrc))
1375 {
1376 switch (vrc)
1377 {
1378 default:
1379 hr = setError(VBOX_E_IPRT_ERROR,
1380 tr("Seeking file \"%s\" (to offset %RU64) failed: %Rrc"),
1381 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1382 break;
1383 }
1384 }
1385
1386 LogFlowFuncLeaveRC(vrc);
1387 return hr;
1388#endif /* VBOX_WITH_GUEST_CONTROL */
1389}
1390
1391STDMETHODIMP GuestFile::SetACL(IN_BSTR aACL)
1392{
1393#ifndef VBOX_WITH_GUEST_CONTROL
1394 ReturnComNotImplemented();
1395#else
1396 AutoCaller autoCaller(this);
1397 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1398
1399 ReturnComNotImplemented();
1400#endif /* VBOX_WITH_GUEST_CONTROL */
1401}
1402
1403STDMETHODIMP GuestFile::Write(ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
1404{
1405#ifndef VBOX_WITH_GUEST_CONTROL
1406 ReturnComNotImplemented();
1407#else
1408 LogFlowThisFuncEnter();
1409
1410 CheckComArgOutPointerValid(aWritten);
1411
1412 AutoCaller autoCaller(this);
1413 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1414
1415 HRESULT hr = S_OK;
1416
1417 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData));
1418 int vrc = writeData(aTimeoutMS, data.raw(), (uint32_t)data.size(),
1419 (uint32_t*)aWritten);
1420 if (RT_FAILURE(vrc))
1421 {
1422 switch (vrc)
1423 {
1424 default:
1425 hr = setError(VBOX_E_IPRT_ERROR,
1426 tr("Writing %zubytes to file \"%s\" failed: %Rrc"),
1427 data.size(), mData.mOpenInfo.mFileName.c_str(), vrc);
1428 break;
1429 }
1430 }
1431
1432 LogFlowFuncLeaveRC(vrc);
1433 return hr;
1434#endif /* VBOX_WITH_GUEST_CONTROL */
1435}
1436
1437STDMETHODIMP GuestFile::WriteAt(LONG64 aOffset, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
1438{
1439#ifndef VBOX_WITH_GUEST_CONTROL
1440 ReturnComNotImplemented();
1441#else
1442 LogFlowThisFuncEnter();
1443
1444 CheckComArgOutPointerValid(aWritten);
1445
1446 AutoCaller autoCaller(this);
1447 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1448
1449 HRESULT hr = S_OK;
1450
1451 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData));
1452 int vrc = writeData(aTimeoutMS, data.raw(), (uint32_t)data.size(),
1453 (uint32_t*)aWritten);
1454 if (RT_FAILURE(vrc))
1455 {
1456 switch (vrc)
1457 {
1458 default:
1459 hr = setError(VBOX_E_IPRT_ERROR,
1460 tr("Writing %zubytes to file \"%s\" (at offset %RU64) failed: %Rrc"),
1461 data.size(), mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1462 break;
1463 }
1464 }
1465
1466 LogFlowFuncLeaveRC(vrc);
1467 return hr;
1468#endif /* VBOX_WITH_GUEST_CONTROL */
1469}
1470
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