summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-server/HostDriveImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-server/HostDriveImpl.cpp')
-rw-r--r--src/VBox/Main/src-server/HostDriveImpl.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/HostDriveImpl.cpp b/src/VBox/Main/src-server/HostDriveImpl.cpp
new file mode 100644
index 00000000..10b06d3f
--- /dev/null
+++ b/src/VBox/Main/src-server/HostDriveImpl.cpp
@@ -0,0 +1,273 @@
+/* $Id: HostDriveImpl.cpp $ */
+/** @file
+ * VirtualBox Main - IHostDrive implementation, VBoxSVC.
+ */
+
+/*
+ * Copyright (C) 2013-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define LOG_GROUP LOG_GROUP_MAIN_HOSTDRIVE
+#include "Global.h"
+#include "HostDriveImpl.h"
+#include "HostDrivePartitionImpl.h"
+#include "LoggingNew.h"
+#include "VirtualBoxImpl.h"
+
+#include <iprt/dvm.h>
+#include <iprt/err.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
+#include <iprt/vfs.h>
+#include <VBox/com/Guid.h>
+
+
+/*
+ * HostDrive implementation.
+ */
+DEFINE_EMPTY_CTOR_DTOR(HostDrive)
+
+HRESULT HostDrive::FinalConstruct()
+{
+ return BaseFinalConstruct();
+}
+
+void HostDrive::FinalRelease()
+{
+ uninit();
+
+ BaseFinalRelease();
+}
+
+/**
+ * Initializes the instance.
+ */
+HRESULT HostDrive::initFromPathAndModel(const com::Utf8Str &drivePath, const com::Utf8Str &driveModel)
+{
+ LogFlowThisFunc(("\n"));
+
+ AssertReturn(!drivePath.isEmpty(), E_INVALIDARG);
+
+ /* Enclose the state transition NotReady->InInit->Ready */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+ m.partitioningType = PartitioningType_MBR;
+ m.drivePath = drivePath;
+ m.model = driveModel;
+ m.partitions.clear();
+
+ /*
+ * Try open the drive so we can extract futher details,
+ * like the size, sector size and partitions.
+ */
+ HRESULT hrc = E_FAIL;
+ RTFILE hRawFile = NIL_RTFILE;
+ int vrc = RTFileOpen(&hRawFile, drivePath.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = RTFileQuerySize(hRawFile, &m.cbDisk);
+ int vrc2 = RTFileQuerySectorSize(hRawFile, &m.cbSector);
+ if (RT_FAILURE(vrc2))
+ vrc = vrc2;
+ if (RT_SUCCESS(vrc))
+ {
+ /*
+ * Hand it to DVM.
+ */
+ RTVFSFILE hVfsFile = NIL_RTVFSFILE;
+ vrc = RTVfsFileFromRTFile(hRawFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE /*fOpen*/,
+ true /*fLeaveOpen*/, &hVfsFile);
+ if (RT_SUCCESS(vrc))
+ {
+ RTDVM hVolMgr = NIL_RTDVM;
+ vrc = RTDvmCreate(&hVolMgr, hVfsFile, m.cbSector, 0 /*fFlags*/);
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = RTDvmMapOpen(hVolMgr);
+ if (RT_SUCCESS(vrc))
+ {
+ hrc = S_OK;
+
+ /*
+ * Get details.
+ */
+ switch (RTDvmMapGetFormatType(hVolMgr))
+ {
+ case RTDVMFORMATTYPE_GPT:
+ m.partitioningType = PartitioningType_GPT;
+ break;
+ case RTDVMFORMATTYPE_MBR:
+ m.partitioningType = PartitioningType_MBR;
+ break;
+ case RTDVMFORMATTYPE_BSD_LABEL:
+ AssertMsgFailed(("TODO\n"));
+ break;
+ default:
+ AssertFailed();
+ }
+
+ RTUUID Uuid = RTUUID_INITIALIZE_NULL;
+ if (RT_SUCCESS(RTDvmMapQueryDiskUuid(hVolMgr, &Uuid)))
+ m.uuid = Uuid;
+
+ /*
+ * Enumerate volumes and tuck them into the partitions list..
+ */
+ uint32_t const cVolumes = RTDvmMapGetValidVolumes(hVolMgr);
+ RTDVMVOLUME hVol = NIL_RTDVMVOLUME;
+ for (uint32_t i = 0; i < cVolumes; i++)
+ {
+ /* Enumeration cruft: */
+ RTDVMVOLUME hVolNext = NIL_RTDVMVOLUME;
+ if (i == 0)
+ vrc = RTDvmMapQueryFirstVolume(hVolMgr, &hVolNext);
+ else
+ vrc = RTDvmMapQueryNextVolume(hVolMgr, hVol, &hVolNext);
+ AssertRCBreakStmt(vrc, hrc = Global::vboxStatusCodeToCOM(vrc));
+
+ uint32_t cRefs = RTDvmVolumeRelease(hVol);
+ Assert(cRefs != UINT32_MAX); RT_NOREF(cRefs);
+ hVol = hVolNext;
+
+ /* Instantiate a new partition object and add it to the list: */
+ ComObjPtr<HostDrivePartition> ptrHostPartition;
+ hrc = ptrHostPartition.createObject();
+ if (SUCCEEDED(hrc))
+ hrc = ptrHostPartition->initFromDvmVol(hVol);
+ if (SUCCEEDED(hrc))
+ try
+ {
+ m.partitions.push_back(ptrHostPartition);
+ }
+ catch (std::bad_alloc &)
+ {
+ AssertFailedBreakStmt(hrc = E_OUTOFMEMORY);
+ }
+ }
+ RTDvmVolumeRelease(hVol);
+ }
+ else
+ hrc = Global::vboxStatusCodeToCOM(vrc);
+ RTDvmRelease(hVolMgr);
+ }
+ else
+ hrc = Global::vboxStatusCodeToCOM(vrc);
+ RTVfsFileRelease(hVfsFile);
+ }
+ else
+ hrc = Global::vboxStatusCodeToCOM(vrc);
+ }
+ else /* VERR_IO_NOT_READ / STATUS_NO_MEDIA_IN_DEVICE is likely for card readers on windows. */
+ hrc = Global::vboxStatusCodeToCOM(vrc);
+ RTFileClose(hRawFile);
+ }
+ else
+ {
+ /*
+ * We don't use the Global::vboxStatusCodeToCOM(vrc) here
+ * because RTFileOpen can return some error which causes
+ * the assertion and breaks original idea of returning
+ * the object in the limited state.
+ */
+ if ( vrc == VERR_RESOURCE_BUSY
+ || vrc == VERR_ACCESS_DENIED)
+ hrc = E_ACCESSDENIED;
+ else
+ hrc = VBOX_E_IPRT_ERROR;
+ }
+
+ /* Confirm a successful initialization */
+ if (SUCCEEDED(hrc))
+ autoInitSpan.setSucceeded();
+ else
+ autoInitSpan.setLimited(hrc);
+ return S_OK;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called either from FinalRelease() or by the parent when it gets destroyed.
+ */
+void HostDrive::uninit()
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition Ready->InUninit->NotReady */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ m.drivePath.setNull();
+ m.partitions.clear();
+}
+
+
+/*********************************************************************************************************************************
+* IHostDrive properties *
+*********************************************************************************************************************************/
+
+HRESULT HostDrive::getPartitioningType(PartitioningType_T *aPartitioningType)
+{
+ *aPartitioningType = m.partitioningType;
+ return S_OK;
+}
+
+HRESULT HostDrive::getDrivePath(com::Utf8Str &aDrivePath)
+{
+ aDrivePath = m.drivePath;
+ return S_OK;
+}
+
+HRESULT HostDrive::getUuid(com::Guid &aUuid)
+{
+ aUuid = m.uuid;
+ return S_OK;
+}
+
+HRESULT HostDrive::getSectorSize(ULONG *aSectorSize)
+{
+ *aSectorSize = m.cbSector;
+ return S_OK;
+}
+
+HRESULT HostDrive::getSize(LONG64 *aSize)
+{
+ *aSize = (LONG64)m.cbDisk;
+ if (*aSize < 0)
+ *aSize = INT64_MAX;
+ return S_OK;
+}
+
+HRESULT HostDrive::getModel(com::Utf8Str &aModel)
+{
+ return aModel.assignEx(m.model);
+}
+
+HRESULT HostDrive::getPartitions(std::vector<ComPtr<IHostDrivePartition> > &aPartitions)
+{
+ aPartitions = m.partitions;
+ return S_OK;
+}
+
+
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */