master
cpp 169 lines 6.74 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "GuestDeviceManager.h"
5 #include "DeviceHostProxy.h"
6
7 GuestDeviceManager::GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId, bool EnableTelemetry) :
8 m_machineId(machineId), m_deviceHostSupport(wil::MakeOrThrow<DeviceHostProxy>(machineId, runtimeId, EnableTelemetry))
9 {
10 }
11
12 GuestDeviceManager::~GuestDeviceManager()
13 {
14 try
15 {
16 m_deviceHostSupport->Shutdown();
17 }
18 CATCH_LOG()
19 }
20
21 _Requires_lock_not_held_(m_lock)
22 GUID GuestDeviceManager::AddVirtiofsDevice(_In_ PCWSTR Label, _In_opt_ PCWSTR MountOptions, _In_ PCWSTR RootPath, _In_ HANDLE UserToken, VirtioFsShareOptions Options)
23 {
24 auto guestDeviceLock = m_lock.lock_exclusive();
25 return m_deviceHostSupport->AddVirtiofsDevice(
26 UserToken, Label, RootPath, Options.Kind, Options.SharedMemorySizeMb, MountOptions ? MountOptions : L"");
27 }
28
29 _Requires_lock_not_held_(m_lock)
30 void GuestDeviceManager::AddVirtiofsChild(_In_ const GUID& InstanceId, _In_ PCWSTR Name, _In_opt_ PCWSTR MountOptions, _In_ PCWSTR RootPath)
31 {
32 auto guestDeviceLock = m_lock.lock_exclusive();
33 m_deviceHostSupport->AddVirtiofsChild(InstanceId, Name, RootPath, MountOptions ? MountOptions : L"");
34 }
35
36 _Requires_lock_not_held_(m_lock)
37 void GuestDeviceManager::RemoveVirtiofsChild(_In_ const GUID& InstanceId, _In_ PCWSTR Name)
38 {
39 auto guestDeviceLock = m_lock.lock_exclusive();
40 m_deviceHostSupport->RemoveVirtiofsChild(InstanceId, Name);
41 }
42
43 _Requires_lock_not_held_(m_lock)
44 GUID GuestDeviceManager::AddVirtioPmemDevice(_In_ PCWSTR Path, bool ReadOnly, _In_ HANDLE UserToken)
45 {
46 auto guestDeviceLock = m_lock.lock_exclusive();
47 return m_deviceHostSupport->AddVirtioPmemDevice(UserToken, Path, !ReadOnly);
48 }
49
50 _Requires_lock_not_held_(m_lock)
51 GUID GuestDeviceManager::AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr<IPlan9FileSystem>& server, _In_ PCWSTR tag)
52 {
53 auto guestDeviceLock = m_lock.lock_exclusive();
54 return m_deviceHostSupport->AddNewDevice(deviceId, server, tag);
55 }
56
57 GUID GuestDeviceManager::AddVirtioNetDevice(_In_ PCWSTR Tag, const WslVirtioNetConfig& Config, const std::vector<IpAddress>& Nameservers, _In_ HANDLE UserToken)
58 {
59 auto guestDeviceLock = m_lock.lock_exclusive();
60 THROW_HR_IF(E_INVALIDARG, m_virtioNetDevices.contains(Tag));
61 const auto instanceId = m_deviceHostSupport->AddVirtioNetDevice(UserToken, Config, Nameservers);
62 m_virtioNetDevices.emplace(Tag, instanceId);
63 return instanceId;
64 }
65
66 wil::com_ptr<IWslVirtioNetDevice> GuestDeviceManager::GetVirtioNetDevice(_In_ PCWSTR Tag)
67 {
68 auto guestDeviceLock = m_lock.lock_shared();
69 const auto device = m_virtioNetDevices.find(Tag);
70 THROW_HR_IF(E_NOT_SET, device == m_virtioNetDevices.end());
71 return m_deviceHostSupport->GetVirtioNetDevice(device->second);
72 }
73
74 void GuestDeviceManager::AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr<IPlan9FileSystem>& server)
75 {
76 m_deviceHostSupport->AddRemoteFileSystem(clsid, tag, server);
77 }
78
79 void GuestDeviceManager::AddSharedMemoryDevice(_In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken)
80 {
81 auto guestDeviceLock = m_lock.lock_exclusive();
82 auto objectLifetime = CreateSectionObjectRoot(Path, UserToken);
83
84 (void)m_deviceHostSupport->AddVirtiofsDevice(
85 UserToken, Tag, objectLifetime.Path, VirtiofsShareKind_SectionBacked, SizeMb, L"");
86 m_objectDirectories.emplace_back(std::move(objectLifetime));
87 }
88
89 GuestDeviceManager::DirectoryObjectLifetime GuestDeviceManager::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const
90 {
91 auto revert = wil::impersonate_token(UserToken);
92 DWORD sessionId;
93 DWORD bytesWritten;
94 THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten));
95
96 // /Sessions/1/BaseNamedObjects/WSL/<VM ID>/<Relative Path>
97 std::wstringstream sectionPathBuilder;
98 sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath;
99 auto sectionPath = sectionPathBuilder.str();
100
101 UNICODE_STRING ntPath{};
102 OBJECT_ATTRIBUTES attributes{};
103 attributes.Length = sizeof(OBJECT_ATTRIBUTES);
104 attributes.ObjectName = &ntPath;
105 std::vector<wil::unique_handle> directoryHierarchy;
106 auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length());
107 while (remainingPath.length() > 0)
108 {
109 // Find the next path substring, ignoring the root path backslash.
110 auto nextDir = remainingPath;
111 const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0);
112 if (separatorPos != std::wstring_view::npos)
113 {
114 nextDir = nextDir.substr(0, separatorPos);
115 remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos);
116
117 // Skip concurrent backslashes.
118 while (remainingPath.length() > 0 && remainingPath[0] == L'\\')
119 {
120 remainingPath = remainingPath.substr(1, std::wstring_view::npos);
121 }
122 }
123 else
124 {
125 remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos);
126 }
127
128 attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr;
129 ntPath.Buffer = const_cast<PWCH>(nextDir.data());
130 ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast<USHORT>(nextDir.length());
131 ntPath.MaximumLength = ntPath.Length;
132 wil::unique_handle nextHandle;
133 NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes);
134 if (status == STATUS_OBJECT_NAME_COLLISION)
135 {
136 status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes);
137 }
138 THROW_IF_NTSTATUS_FAILED(status);
139 directoryHierarchy.emplace_back(std::move(nextHandle));
140 }
141
142 return {std::move(sectionPath), std::move(directoryHierarchy)};
143 }
144
145 wil::com_ptr<IPlan9FileSystem> GuestDeviceManager::GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag)
146 {
147 return m_deviceHostSupport->GetRemoteFileSystem(clsid, tag);
148 }
149
150 void GuestDeviceManager::SetSwiotlb(UINT64 GpaBase, UINT64 SizeBytes)
151 {
152 m_deviceHostSupport->SetSwiotlb(GpaBase, SizeBytes);
153 }
154
155 _Requires_lock_not_held_(m_lock)
156 void GuestDeviceManager::RemoveGuestDevice(_In_ const GUID& InstanceId)
157 {
158 auto guestDeviceLock = m_lock.lock_exclusive();
159 for (auto it = m_virtioNetDevices.begin(); it != m_virtioNetDevices.end(); ++it)
160 {
161 if (IsEqualGUID(it->second, InstanceId))
162 {
163 m_virtioNetDevices.erase(it);
164 break;
165 }
166 }
167
168 m_deviceHostSupport->RemoveDevice(InstanceId);
169 }