VirtualBox

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

Last change on this file since 70772 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use