VirtualBox

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

Last change on this file since 71707 was 71636, checked in by vboxsync, 7 years ago

Guest Control/Main: Ignore rc when notifying wait events in GuestFile::i_onFileNotify(); those could be long gone at that point of time.

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