VirtualBox

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

Last change on this file since 71619 was 71560, checked in by vboxsync, 7 years ago

Guest Control/Main: Added more AutoCaller checks for public APIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.7 KB
Line 
1/* $Id: GuestFileImpl.cpp 71560 2018-03-29 11:00:30Z 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.215389.xyz. 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 vrc = 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 rc2 = signalWaitEventInternal(pCbCtx, rcGuest, NULL /* pPayload */);
455 AssertRC(rc2);
456
457 return VINF_SUCCESS; /* Report to the guest. */
458 }
459
460 switch (dataCb.uType)
461 {
462 case GUEST_FILE_NOTIFYTYPE_ERROR:
463 {
464 int rc2 = i_setFileStatus(FileStatus_Error, rcGuest);
465 AssertRC(rc2);
466
467 break;
468 }
469
470 case GUEST_FILE_NOTIFYTYPE_OPEN:
471 {
472 if (pSvcCbData->mParms == 4)
473 {
474 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.open.uHandle);
475
476 AssertMsg(mObjectID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
477 ("File ID %RU32 does not match object ID %RU32\n", mObjectID,
478 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
479
480 /* Set the process status. */
481 int rc2 = i_setFileStatus(FileStatus_Open, rcGuest);
482 AssertRC(rc2);
483 }
484 else
485 vrc = VERR_NOT_SUPPORTED;
486
487 break;
488 }
489
490 case GUEST_FILE_NOTIFYTYPE_CLOSE:
491 {
492 int rc2 = i_setFileStatus(FileStatus_Closed, rcGuest);
493 AssertRC(rc2);
494
495 break;
496 }
497
498 case GUEST_FILE_NOTIFYTYPE_READ:
499 {
500 if (pSvcCbData->mParms == 4)
501 {
502 pSvcCbData->mpaParms[idx++].getPointer(&dataCb.u.read.pvData,
503 &dataCb.u.read.cbData);
504 uint32_t cbRead = dataCb.u.read.cbData;
505
506 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
507
508 mData.mOffCurrent += cbRead;
509
510 alock.release();
511
512 com::SafeArray<BYTE> data((size_t)cbRead);
513 data.initFrom((BYTE*)dataCb.u.read.pvData, cbRead);
514
515 fireGuestFileReadEvent(mEventSource, mSession, this, mData.mOffCurrent,
516 cbRead, ComSafeArrayAsInParam(data));
517 }
518 else
519 vrc = VERR_NOT_SUPPORTED;
520 break;
521 }
522
523 case GUEST_FILE_NOTIFYTYPE_WRITE:
524 {
525 if (pSvcCbData->mParms == 4)
526 {
527 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.write.cbWritten);
528
529 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
530
531 mData.mOffCurrent += dataCb.u.write.cbWritten;
532 uint64_t uOffCurrent = mData.mOffCurrent;
533
534 alock.release();
535
536 fireGuestFileWriteEvent(mEventSource, mSession, this, uOffCurrent,
537 dataCb.u.write.cbWritten);
538 }
539 else
540 vrc = VERR_NOT_SUPPORTED;
541 break;
542 }
543
544 case GUEST_FILE_NOTIFYTYPE_SEEK:
545 {
546 if (pSvcCbData->mParms == 4)
547 {
548 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.seek.uOffActual);
549
550 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
551
552 mData.mOffCurrent = dataCb.u.seek.uOffActual;
553
554 alock.release();
555
556 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
557 dataCb.u.seek.uOffActual, 0 /* Processed */);
558 }
559 else
560 vrc = VERR_NOT_SUPPORTED;
561 break;
562 }
563
564 case GUEST_FILE_NOTIFYTYPE_TELL:
565 {
566 if (pSvcCbData->mParms == 4)
567 {
568 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.tell.uOffActual);
569
570 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
571
572 mData.mOffCurrent = dataCb.u.tell.uOffActual;
573
574 alock.release();
575
576 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
577 dataCb.u.tell.uOffActual, 0 /* Processed */);
578 }
579 else
580 vrc = VERR_NOT_SUPPORTED;
581 break;
582 }
583
584 default:
585 vrc = VERR_NOT_SUPPORTED;
586 break;
587 }
588
589 if (RT_SUCCESS(vrc))
590 {
591 GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb));
592 int rc2 = signalWaitEventInternal(pCbCtx, rcGuest, &payload);
593 AssertRC(rc2);
594 }
595
596 LogFlowThisFunc(("uType=%RU32, rcGuest=%Rrc\n",
597 dataCb.uType, dataCb.rc));
598
599 LogFlowFuncLeaveRC(vrc);
600 return vrc;
601}
602
603int GuestFile::i_onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
604{
605 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
606 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
607
608 int vrc = i_setFileStatus(FileStatus_Down, VINF_SUCCESS);
609
610 LogFlowFuncLeaveRC(vrc);
611 return vrc;
612}
613
614/**
615 * Called by IGuestSession right before this file gets removed
616 * from the public file list.
617 */
618int GuestFile::i_onRemove(void)
619{
620 LogFlowThisFuncEnter();
621
622 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
623
624 int vrc = VINF_SUCCESS;
625
626 /*
627 * Note: The event source stuff holds references to this object,
628 * so make sure that this is cleaned up *before* calling uninit().
629 */
630 if (!mEventSource.isNull())
631 {
632 mEventSource->UnregisterListener(mLocalListener);
633
634 mLocalListener.setNull();
635 unconst(mEventSource).setNull();
636 }
637
638 LogFlowFuncLeaveRC(vrc);
639 return vrc;
640}
641
642int GuestFile::i_openFile(uint32_t uTimeoutMS, int *prcGuest)
643{
644 LogFlowThisFuncEnter();
645
646 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
647
648 LogFlowThisFunc(("strFile=%s, enmAccessMode=%d (%s) enmOpenAction=%d (%s) uCreationMode=%RU32, mfOpenEx=%RU32\n",
649 mData.mOpenInfo.mFileName.c_str(), mData.mOpenInfo.mAccessMode, mData.mOpenInfo.mpszAccessMode,
650 mData.mOpenInfo.mOpenAction, mData.mOpenInfo.mpszOpenAction, mData.mOpenInfo.mCreationMode,
651 mData.mOpenInfo.mfOpenEx));
652 int vrc;
653
654 GuestWaitEvent *pEvent = NULL;
655 GuestEventTypes eventTypes;
656 try
657 {
658 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
659
660 vrc = registerWaitEvent(eventTypes, &pEvent);
661 }
662 catch (std::bad_alloc)
663 {
664 vrc = VERR_NO_MEMORY;
665 }
666
667 if (RT_FAILURE(vrc))
668 return vrc;
669
670 /* Prepare HGCM call. */
671 VBOXHGCMSVCPARM paParms[8];
672 int i = 0;
673 paParms[i++].setUInt32(pEvent->ContextID());
674 paParms[i++].setPointer((void*)mData.mOpenInfo.mFileName.c_str(),
675 (ULONG)mData.mOpenInfo.mFileName.length() + 1);
676 paParms[i++].setString(mData.mOpenInfo.mpszAccessMode);
677 paParms[i++].setString(mData.mOpenInfo.mpszOpenAction);
678 paParms[i++].setString(""); /** @todo sharing mode. */
679 paParms[i++].setUInt32(mData.mOpenInfo.mCreationMode);
680 paParms[i++].setUInt64(0 /* initial offset */);
681 /** @todo Next protocol version: add flags, replace strings, remove initial offset. */
682
683 alock.release(); /* Drop write lock before sending. */
684
685 vrc = sendCommand(HOST_FILE_OPEN, i, paParms);
686 if (RT_SUCCESS(vrc))
687 vrc = i_waitForStatusChange(pEvent, uTimeoutMS, NULL /* FileStatus */, prcGuest);
688
689 unregisterWaitEvent(pEvent);
690
691 LogFlowFuncLeaveRC(vrc);
692 return vrc;
693}
694
695int GuestFile::i_readData(uint32_t uSize, uint32_t uTimeoutMS,
696 void* pvData, uint32_t cbData, uint32_t* pcbRead)
697{
698 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
699 AssertReturn(cbData, VERR_INVALID_PARAMETER);
700
701 LogFlowThisFunc(("uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
702 uSize, uTimeoutMS, pvData, cbData));
703
704 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
705
706 int vrc;
707
708 GuestWaitEvent *pEvent = NULL;
709 GuestEventTypes eventTypes;
710 try
711 {
712 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
713 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
714
715 vrc = registerWaitEvent(eventTypes, &pEvent);
716 }
717 catch (std::bad_alloc)
718 {
719 vrc = VERR_NO_MEMORY;
720 }
721
722 if (RT_FAILURE(vrc))
723 return vrc;
724
725 /* Prepare HGCM call. */
726 VBOXHGCMSVCPARM paParms[4];
727 int i = 0;
728 paParms[i++].setUInt32(pEvent->ContextID());
729 paParms[i++].setUInt32(mObjectID /* File handle */);
730 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
731
732 alock.release(); /* Drop write lock before sending. */
733
734 vrc = sendCommand(HOST_FILE_READ, i, paParms);
735 if (RT_SUCCESS(vrc))
736 {
737 uint32_t cbRead = 0;
738 vrc = i_waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
739 if (RT_SUCCESS(vrc))
740 {
741 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
742 if (pcbRead)
743 *pcbRead = cbRead;
744 }
745 }
746
747 unregisterWaitEvent(pEvent);
748
749 LogFlowFuncLeaveRC(vrc);
750 return vrc;
751}
752
753int GuestFile::i_readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS,
754 void* pvData, size_t cbData, size_t* pcbRead)
755{
756 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
757 uOffset, uSize, uTimeoutMS, pvData, cbData));
758
759 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
760
761 int vrc;
762
763 GuestWaitEvent *pEvent = NULL;
764 GuestEventTypes eventTypes;
765 try
766 {
767 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
768 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
769
770 vrc = registerWaitEvent(eventTypes, &pEvent);
771 }
772 catch (std::bad_alloc)
773 {
774 vrc = VERR_NO_MEMORY;
775 }
776
777 if (RT_FAILURE(vrc))
778 return vrc;
779
780 /* Prepare HGCM call. */
781 VBOXHGCMSVCPARM paParms[4];
782 int i = 0;
783 paParms[i++].setUInt32(pEvent->ContextID());
784 paParms[i++].setUInt32(mObjectID /* File handle */);
785 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */);
786 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
787
788 alock.release(); /* Drop write lock before sending. */
789
790 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms);
791 if (RT_SUCCESS(vrc))
792 {
793 uint32_t cbRead = 0;
794 vrc = i_waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
795 if (RT_SUCCESS(vrc))
796 {
797 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
798
799 if (pcbRead)
800 *pcbRead = cbRead;
801 }
802 }
803
804 unregisterWaitEvent(pEvent);
805
806 LogFlowFuncLeaveRC(vrc);
807 return vrc;
808}
809
810int GuestFile::i_seekAt(int64_t iOffset, GUEST_FILE_SEEKTYPE eSeekType,
811 uint32_t uTimeoutMS, uint64_t *puOffset)
812{
813 LogFlowThisFunc(("iOffset=%RI64, uTimeoutMS=%RU32\n",
814 iOffset, uTimeoutMS));
815
816 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
817
818 int vrc;
819
820 GuestWaitEvent *pEvent = NULL;
821 GuestEventTypes eventTypes;
822 try
823 {
824 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
825 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
826
827 vrc = registerWaitEvent(eventTypes, &pEvent);
828 }
829 catch (std::bad_alloc)
830 {
831 vrc = VERR_NO_MEMORY;
832 }
833
834 if (RT_FAILURE(vrc))
835 return vrc;
836
837 /* Prepare HGCM call. */
838 VBOXHGCMSVCPARM paParms[4];
839 int i = 0;
840 paParms[i++].setUInt32(pEvent->ContextID());
841 paParms[i++].setUInt32(mObjectID /* File handle */);
842 paParms[i++].setUInt32(eSeekType /* Seek method */);
843 /** @todo uint64_t vs. int64_t! */
844 paParms[i++].setUInt64((uint64_t)iOffset /* Offset (in bytes) to start reading */);
845
846 alock.release(); /* Drop write lock before sending. */
847
848 vrc = sendCommand(HOST_FILE_SEEK, i, paParms);
849 if (RT_SUCCESS(vrc))
850 vrc = i_waitForOffsetChange(pEvent, uTimeoutMS, puOffset);
851
852 unregisterWaitEvent(pEvent);
853
854 LogFlowFuncLeaveRC(vrc);
855 return vrc;
856}
857
858/* static */
859HRESULT GuestFile::i_setErrorExternal(VirtualBoxBase *pInterface, int rcGuest)
860{
861 AssertPtr(pInterface);
862 AssertMsg(RT_FAILURE(rcGuest), ("Guest rc does not indicate a failure when setting error\n"));
863
864 return pInterface->setError(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(rcGuest).c_str());
865}
866
867int GuestFile::i_setFileStatus(FileStatus_T fileStatus, int fileRc)
868{
869 LogFlowThisFuncEnter();
870
871 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
872
873 LogFlowThisFunc(("oldStatus=%RU32, newStatus=%RU32, fileRc=%Rrc\n",
874 mData.mStatus, fileStatus, fileRc));
875
876#ifdef VBOX_STRICT
877 if (fileStatus == FileStatus_Error)
878 {
879 AssertMsg(RT_FAILURE(fileRc), ("Guest rc must be an error (%Rrc)\n", fileRc));
880 }
881 else
882 AssertMsg(RT_SUCCESS(fileRc), ("Guest rc must not be an error (%Rrc)\n", fileRc));
883#endif
884
885 if (mData.mStatus != fileStatus)
886 {
887 mData.mStatus = fileStatus;
888 mData.mLastError = fileRc;
889
890 ComObjPtr<VirtualBoxErrorInfo> errorInfo;
891 HRESULT hr = errorInfo.createObject();
892 ComAssertComRC(hr);
893 if (RT_FAILURE(fileRc))
894 {
895 hr = errorInfo->initEx(VBOX_E_IPRT_ERROR, fileRc,
896 COM_IIDOF(IGuestFile), getComponentName(),
897 i_guestErrorToString(fileRc));
898 ComAssertComRC(hr);
899 }
900
901 alock.release(); /* Release lock before firing off event. */
902
903 fireGuestFileStateChangedEvent(mEventSource, mSession,
904 this, fileStatus, errorInfo);
905 }
906
907 return VINF_SUCCESS;
908}
909
910int GuestFile::i_waitForOffsetChange(GuestWaitEvent *pEvent,
911 uint32_t uTimeoutMS, uint64_t *puOffset)
912{
913 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
914
915 VBoxEventType_T evtType;
916 ComPtr<IEvent> pIEvent;
917 int vrc = waitForEvent(pEvent, uTimeoutMS,
918 &evtType, pIEvent.asOutParam());
919 if (RT_SUCCESS(vrc))
920 {
921 if (evtType == VBoxEventType_OnGuestFileOffsetChanged)
922 {
923 if (puOffset)
924 {
925 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent;
926 Assert(!pFileEvent.isNull());
927
928 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset);
929 ComAssertComRC(hr);
930 }
931 }
932 else
933 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
934 }
935
936 return vrc;
937}
938
939int GuestFile::i_waitForRead(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
940 void *pvData, size_t cbData, uint32_t *pcbRead)
941{
942 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
943
944 VBoxEventType_T evtType;
945 ComPtr<IEvent> pIEvent;
946 int vrc = waitForEvent(pEvent, uTimeoutMS,
947 &evtType, pIEvent.asOutParam());
948 if (RT_SUCCESS(vrc))
949 {
950 if (evtType == VBoxEventType_OnGuestFileRead)
951 {
952 ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent;
953 Assert(!pFileEvent.isNull());
954
955 HRESULT hr;
956 if (pvData)
957 {
958 com::SafeArray <BYTE> data;
959 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
960 ComAssertComRC(hr);
961 size_t cbRead = data.size();
962 if ( cbRead
963 && cbRead <= cbData)
964 {
965 memcpy(pvData, data.raw(), data.size());
966 }
967 else
968 vrc = VERR_BUFFER_OVERFLOW;
969 }
970 if (pcbRead)
971 {
972 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead);
973 ComAssertComRC(hr);
974 }
975 }
976 else
977 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
978 }
979
980 return vrc;
981}
982
983int GuestFile::i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
984 FileStatus_T *pFileStatus, int *prcGuest)
985{
986 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
987 /* pFileStatus is optional. */
988
989 VBoxEventType_T evtType;
990 ComPtr<IEvent> pIEvent;
991 int vrc = waitForEvent(pEvent, uTimeoutMS,
992 &evtType, pIEvent.asOutParam());
993 if (RT_SUCCESS(vrc))
994 {
995 Assert(evtType == VBoxEventType_OnGuestFileStateChanged);
996 ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent;
997 Assert(!pFileEvent.isNull());
998
999 HRESULT hr;
1000 if (pFileStatus)
1001 {
1002 hr = pFileEvent->COMGETTER(Status)(pFileStatus);
1003 ComAssertComRC(hr);
1004 }
1005
1006 ComPtr<IVirtualBoxErrorInfo> errorInfo;
1007 hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam());
1008 ComAssertComRC(hr);
1009
1010 LONG lGuestRc;
1011 hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
1012 ComAssertComRC(hr);
1013
1014 LogFlowThisFunc(("resultDetail=%RI32 (%Rrc)\n",
1015 lGuestRc, lGuestRc));
1016
1017 if (RT_FAILURE((int)lGuestRc))
1018 vrc = VERR_GSTCTL_GUEST_ERROR;
1019
1020 if (prcGuest)
1021 *prcGuest = (int)lGuestRc;
1022 }
1023
1024 return vrc;
1025}
1026
1027int GuestFile::i_waitForWrite(GuestWaitEvent *pEvent,
1028 uint32_t uTimeoutMS, uint32_t *pcbWritten)
1029{
1030 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
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 if (evtType == VBoxEventType_OnGuestFileWrite)
1039 {
1040 if (pcbWritten)
1041 {
1042 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent;
1043 Assert(!pFileEvent.isNull());
1044
1045 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten);
1046 ComAssertComRC(hr);
1047 }
1048 }
1049 else
1050 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
1051 }
1052
1053 return vrc;
1054}
1055
1056int GuestFile::i_writeData(uint32_t uTimeoutMS, void *pvData, uint32_t cbData,
1057 uint32_t *pcbWritten)
1058{
1059 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1060 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1061
1062 LogFlowThisFunc(("uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1063 uTimeoutMS, pvData, cbData));
1064
1065 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1066
1067 int vrc;
1068
1069 GuestWaitEvent *pEvent = NULL;
1070 GuestEventTypes eventTypes;
1071 try
1072 {
1073 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1074 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1075
1076 vrc = registerWaitEvent(eventTypes, &pEvent);
1077 }
1078 catch (std::bad_alloc)
1079 {
1080 vrc = VERR_NO_MEMORY;
1081 }
1082
1083 if (RT_FAILURE(vrc))
1084 return vrc;
1085
1086 /* Prepare HGCM call. */
1087 VBOXHGCMSVCPARM paParms[8];
1088 int i = 0;
1089 paParms[i++].setUInt32(pEvent->ContextID());
1090 paParms[i++].setUInt32(mObjectID /* File handle */);
1091 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1092 paParms[i++].setPointer(pvData, cbData);
1093
1094 alock.release(); /* Drop write lock before sending. */
1095
1096 vrc = sendCommand(HOST_FILE_WRITE, i, paParms);
1097 if (RT_SUCCESS(vrc))
1098 {
1099 uint32_t cbWritten = 0;
1100 vrc = i_waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1101 if (RT_SUCCESS(vrc))
1102 {
1103 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1104 if (cbWritten)
1105 *pcbWritten = cbWritten;
1106 }
1107 }
1108
1109 unregisterWaitEvent(pEvent);
1110
1111 LogFlowFuncLeaveRC(vrc);
1112 return vrc;
1113}
1114
1115int GuestFile::i_writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS,
1116 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1117{
1118 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1119 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1120
1121 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1122 uOffset, uTimeoutMS, pvData, cbData));
1123
1124 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1125
1126 int vrc;
1127
1128 GuestWaitEvent *pEvent = NULL;
1129 GuestEventTypes eventTypes;
1130 try
1131 {
1132 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1133 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1134
1135 vrc = registerWaitEvent(eventTypes, &pEvent);
1136 }
1137 catch (std::bad_alloc)
1138 {
1139 vrc = VERR_NO_MEMORY;
1140 }
1141
1142 if (RT_FAILURE(vrc))
1143 return vrc;
1144
1145 /* Prepare HGCM call. */
1146 VBOXHGCMSVCPARM paParms[8];
1147 int i = 0;
1148 paParms[i++].setUInt32(pEvent->ContextID());
1149 paParms[i++].setUInt32(mObjectID /* File handle */);
1150 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */);
1151 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1152 paParms[i++].setPointer(pvData, cbData);
1153
1154 alock.release(); /* Drop write lock before sending. */
1155
1156 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms);
1157 if (RT_SUCCESS(vrc))
1158 {
1159 uint32_t cbWritten = 0;
1160 vrc = i_waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1161 if (RT_SUCCESS(vrc))
1162 {
1163 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1164 if (cbWritten)
1165 *pcbWritten = cbWritten;
1166 }
1167 }
1168
1169 unregisterWaitEvent(pEvent);
1170
1171 LogFlowFuncLeaveRC(vrc);
1172 return vrc;
1173}
1174
1175// Wrapped IGuestFile methods
1176/////////////////////////////////////////////////////////////////////////////
1177HRESULT GuestFile::close()
1178{
1179 AutoCaller autoCaller(this);
1180 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1181
1182 LogFlowThisFuncEnter();
1183
1184 /* Close file on guest. */
1185 int rcGuest;
1186 int rc = i_closeFile(&rcGuest);
1187 /* On failure don't return here, instead do all the cleanup
1188 * work first and then return an error. */
1189
1190 AssertPtr(mSession);
1191 int rc2 = mSession->i_fileUnregister(this);
1192 if (RT_SUCCESS(rc))
1193 rc = rc2;
1194
1195 if (RT_FAILURE(rc))
1196 {
1197 if (rc == VERR_GSTCTL_GUEST_ERROR)
1198 return GuestFile::i_setErrorExternal(this, rcGuest);
1199
1200 return setError(VBOX_E_IPRT_ERROR,
1201 tr("Closing guest file failed with %Rrc\n"), rc);
1202 }
1203
1204 LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
1205 return S_OK;
1206}
1207
1208HRESULT GuestFile::queryInfo(ComPtr<IFsObjInfo> &aObjInfo)
1209{
1210 RT_NOREF(aObjInfo);
1211 ReturnComNotImplemented();
1212}
1213
1214HRESULT GuestFile::querySize(LONG64 *aSize)
1215{
1216 RT_NOREF(aSize);
1217 ReturnComNotImplemented();
1218}
1219
1220HRESULT GuestFile::read(ULONG aToRead, ULONG aTimeoutMS, std::vector<BYTE> &aData)
1221{
1222 AutoCaller autoCaller(this);
1223 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1224
1225 if (aToRead == 0)
1226 return setError(E_INVALIDARG, tr("The size to read is zero"));
1227
1228 LogFlowThisFuncEnter();
1229
1230 aData.resize(aToRead);
1231
1232 HRESULT hr = S_OK;
1233
1234 uint32_t cbRead;
1235 int vrc = i_readData(aToRead, aTimeoutMS,
1236 &aData.front(), aToRead, &cbRead);
1237
1238 if (RT_SUCCESS(vrc))
1239 {
1240 if (aData.size() != cbRead)
1241 aData.resize(cbRead);
1242 }
1243 else
1244 {
1245 aData.resize(0);
1246
1247 switch (vrc)
1248 {
1249 default:
1250 hr = setError(VBOX_E_IPRT_ERROR,
1251 tr("Reading from file \"%s\" failed: %Rrc"),
1252 mData.mOpenInfo.mFileName.c_str(), vrc);
1253 break;
1254 }
1255 }
1256
1257 LogFlowFuncLeaveRC(vrc);
1258 return hr;
1259}
1260HRESULT GuestFile::readAt(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, std::vector<BYTE> &aData)
1261
1262{
1263 AutoCaller autoCaller(this);
1264 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1265
1266 if (aToRead == 0)
1267 return setError(E_INVALIDARG, tr("The size to read is zero"));
1268
1269 LogFlowThisFuncEnter();
1270
1271 aData.resize(aToRead);
1272
1273 HRESULT hr = S_OK;
1274
1275 size_t cbRead;
1276 int vrc = i_readDataAt(aOffset, aToRead, aTimeoutMS,
1277 &aData.front(), aToRead, &cbRead);
1278 if (RT_SUCCESS(vrc))
1279 {
1280 if (aData.size() != cbRead)
1281 aData.resize(cbRead);
1282 }
1283 else
1284 {
1285 aData.resize(0);
1286
1287 switch (vrc)
1288 {
1289 default:
1290 hr = setError(VBOX_E_IPRT_ERROR,
1291 tr("Reading from file \"%s\" (at offset %RU64) failed: %Rrc"),
1292 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1293 break;
1294 }
1295 }
1296
1297 LogFlowFuncLeaveRC(vrc);
1298 return hr;
1299}
1300
1301HRESULT GuestFile::seek(LONG64 aOffset, FileSeekOrigin_T aWhence, LONG64 *aNewOffset)
1302{
1303 AutoCaller autoCaller(this);
1304 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1305
1306 HRESULT hr = S_OK;
1307
1308 GUEST_FILE_SEEKTYPE eSeekType;
1309 switch (aWhence)
1310 {
1311 case FileSeekOrigin_Begin:
1312 eSeekType = GUEST_FILE_SEEKTYPE_BEGIN;
1313 break;
1314
1315 case FileSeekOrigin_Current:
1316 eSeekType = GUEST_FILE_SEEKTYPE_CURRENT;
1317 break;
1318
1319 case FileSeekOrigin_End:
1320 eSeekType = GUEST_FILE_SEEKTYPE_END;
1321 break;
1322
1323 default:
1324 return setError(E_INVALIDARG, tr("Invalid seek type specified"));
1325 break; /* Never reached. */
1326 }
1327
1328 LogFlowThisFuncEnter();
1329
1330 uint64_t uNewOffset;
1331 int vrc = i_seekAt(aOffset, eSeekType,
1332 30 * 1000 /* 30s timeout */, &uNewOffset);
1333 if (RT_SUCCESS(vrc))
1334 *aNewOffset = RT_MIN(uNewOffset, (uint64_t)INT64_MAX);
1335 else
1336 {
1337 switch (vrc)
1338 {
1339 default:
1340 hr = setError(VBOX_E_IPRT_ERROR,
1341 tr("Seeking file \"%s\" (to offset %RI64) failed: %Rrc"),
1342 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1343 break;
1344 }
1345 }
1346
1347 LogFlowFuncLeaveRC(vrc);
1348 return hr;
1349}
1350
1351HRESULT GuestFile::setACL(const com::Utf8Str &aAcl, ULONG aMode)
1352{
1353 RT_NOREF(aAcl, aMode);
1354 ReturnComNotImplemented();
1355}
1356
1357HRESULT GuestFile::setSize(LONG64 aSize)
1358{
1359 RT_NOREF(aSize);
1360 ReturnComNotImplemented();
1361}
1362
1363HRESULT GuestFile::write(const std::vector<BYTE> &aData, ULONG aTimeoutMS, ULONG *aWritten)
1364{
1365 AutoCaller autoCaller(this);
1366 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1367
1368 LogFlowThisFuncEnter();
1369
1370 HRESULT hr = S_OK;
1371
1372 uint32_t cbData = (uint32_t)aData.size();
1373 void *pvData = cbData > 0? (void *)&aData.front(): NULL;
1374 int vrc = i_writeData(aTimeoutMS, pvData, cbData, (uint32_t*)aWritten);
1375 if (RT_FAILURE(vrc))
1376 {
1377 switch (vrc)
1378 {
1379 default:
1380 hr = setError(VBOX_E_IPRT_ERROR,
1381 tr("Writing %zubytes to file \"%s\" failed: %Rrc"),
1382 aData.size(), mData.mOpenInfo.mFileName.c_str(), vrc);
1383 break;
1384 }
1385 }
1386
1387 LogFlowFuncLeaveRC(vrc);
1388 return hr;
1389}
1390
1391HRESULT GuestFile::writeAt(LONG64 aOffset, const std::vector<BYTE> &aData, ULONG aTimeoutMS, ULONG *aWritten)
1392
1393{
1394 AutoCaller autoCaller(this);
1395 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1396
1397 LogFlowThisFuncEnter();
1398
1399 HRESULT hr = S_OK;
1400
1401 uint32_t cbData = (uint32_t)aData.size();
1402 void *pvData = cbData > 0? (void *)&aData.front(): NULL;
1403 int vrc = i_writeData(aTimeoutMS, pvData, cbData, (uint32_t*)aWritten);
1404 if (RT_FAILURE(vrc))
1405 {
1406 switch (vrc)
1407 {
1408 default:
1409 hr = setError(VBOX_E_IPRT_ERROR,
1410 tr("Writing %zubytes to file \"%s\" (at offset %RU64) failed: %Rrc"),
1411 aData.size(), mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1412 break;
1413 }
1414 }
1415
1416 LogFlowFuncLeaveRC(vrc);
1417 return hr;
1418}
1419
Note: See TracBrowser for help on using the repository browser.

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