master
cpp 423 lines 12.7 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "APICompat.h"
5 #include <wrl/implements.h>
6
7 namespace wsl::windows::common::apicompat {
8
9 namespace {
10
11 template <size_t Size>
12 void CopyString(char (&Destination)[Size], const char* Source)
13 {
14 THROW_HR_IF(E_UNEXPECTED, strcpy_s(Destination, Source) != 0);
15 }
16
17 template <typename TOut, typename TIn>
18 std::vector<TOut> ConvertArray(const TIn* Items, ULONG Count)
19 {
20 std::vector<TOut> result;
21 if (Items == nullptr || Count == 0)
22 {
23 return result;
24 }
25
26 result.reserve(Count);
27 for (ULONG index = 0; index < Count; index++)
28 {
29 result.push_back(Convert(Items[index]));
30 }
31
32 return result;
33 }
34
35 class CrashDumpCallbackAdapter
36 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ICrashDumpCallback>
37 {
38 public:
39 CrashDumpCallbackAdapter(IWSLCCompatCrashDumpCallback* Inner) : m_inner(Inner)
40 {
41 }
42
43 IFACEMETHOD(OnCrashDump)(LPCWSTR DumpPath, LPCSTR ProcessName, ULONG Pid, ULONG Signal, ULONGLONG Timestamp) override
44 {
45 return m_inner->OnCrashDump(DumpPath, ProcessName, Pid, Signal, Timestamp);
46 }
47
48 private:
49 Microsoft::WRL::ComPtr<IWSLCCompatCrashDumpCallback> m_inner;
50 };
51
52 class ProgressCallbackAdapter
53 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IProgressCallback>
54 {
55 public:
56 ProgressCallbackAdapter(IWSLCCompatProgressCallback* Inner) : m_inner(Inner)
57 {
58 }
59
60 IFACEMETHOD(OnProgress)(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total) override
61 {
62 return m_inner->OnProgress(Status, Id, Current, Total);
63 }
64
65 private:
66 Microsoft::WRL::ComPtr<IWSLCCompatProgressCallback> m_inner;
67 };
68
69 class WarningCallbackAdapter
70 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWarningCallback>
71 {
72 public:
73 WarningCallbackAdapter(IWSLCCompatWarningCallback* Inner) : m_inner(Inner)
74 {
75 }
76
77 IFACEMETHOD(OnWarning)(LPCWSTR Message) override
78 {
79 return m_inner->OnWarning(Message);
80 }
81
82 private:
83 Microsoft::WRL::ComPtr<IWSLCCompatWarningCallback> m_inner;
84 };
85
86 } // namespace
87
88 //
89 // Scalar / non-owning struct conversions.
90 //
91
92 WSLCVersion Convert(const WSLCCompatVersion& Version)
93 {
94 WSLCVersion result{};
95 result.Major = Version.Major;
96 result.Minor = Version.Minor;
97 result.Revision = Version.Revision;
98 return result;
99 }
100
101 WSLCCompatVersion Convert(const WSLCVersion& Version)
102 {
103 WSLCCompatVersion result{};
104 result.Major = Version.Major;
105 result.Minor = Version.Minor;
106 result.Revision = Version.Revision;
107 return result;
108 }
109
110 WSLCHandle Convert(const WSLCCompatHandle& Handle)
111 {
112 WSLCHandle result{};
113 result.Type = Handle.Type;
114 switch (Handle.Type)
115 {
116 case WSLCHandleTypeFile:
117 result.Handle.File = Handle.Handle.File;
118 break;
119 case WSLCHandleTypePipe:
120 result.Handle.Pipe = Handle.Handle.Pipe;
121 break;
122 case WSLCHandleTypeSocket:
123 result.Handle.Socket = Handle.Handle.Socket;
124 break;
125 case WSLCHandleTypeUnknown:
126 break;
127 }
128
129 return result;
130 }
131
132 WSLCCompatHandle Convert(const WSLCHandle& Handle)
133 {
134 WSLCCompatHandle result{};
135 result.Type = Handle.Type;
136 switch (Handle.Type)
137 {
138 case WSLCHandleTypeFile:
139 result.Handle.File = Handle.Handle.File;
140 break;
141 case WSLCHandleTypePipe:
142 result.Handle.Pipe = Handle.Handle.Pipe;
143 break;
144 case WSLCHandleTypeSocket:
145 result.Handle.Socket = Handle.Handle.Socket;
146 break;
147 case WSLCHandleTypeUnknown:
148 break;
149 }
150
151 return result;
152 }
153
154 WSLCStringArray Convert(const WSLCCompatStringArray& Array)
155 {
156 WSLCStringArray result{};
157 result.Values = Array.Values;
158 result.Count = Array.Count;
159 return result;
160 }
161
162 WSLCProcessOptions Convert(const WSLCCompatProcessOptions& Options)
163 {
164 WSLCProcessOptions result{};
165 result.CurrentDirectory = Options.CurrentDirectory;
166 result.User = Options.User;
167 result.CommandLine = Convert(Options.CommandLine);
168 result.Environment = Convert(Options.Environment);
169 result.Flags = Options.Flags;
170 return result;
171 }
172
173 KeyValuePair Convert(const WSLCCompatKeyValuePair& Pair)
174 {
175 KeyValuePair result{};
176 result.Key = Pair.Key;
177 result.Value = Pair.Value;
178 return result;
179 }
180
181 WSLCVolume Convert(const WSLCCompatVolume& Volume)
182 {
183 WSLCVolume result{};
184 result.HostPath = Volume.HostPath;
185 result.ContainerPath = Volume.ContainerPath;
186 result.ReadOnly = Volume.ReadOnly;
187 return result;
188 }
189
190 WSLCNamedVolume Convert(const WSLCCompatNamedVolume& Volume)
191 {
192 WSLCNamedVolume result{};
193 result.Name = Volume.Name;
194 result.ContainerPath = Volume.ContainerPath;
195 result.ReadOnly = Volume.ReadOnly;
196 return result;
197 }
198
199 WSLCPortMapping Convert(const WSLCCompatPortMapping& Port)
200 {
201 WSLCPortMapping result{};
202 result.HostPort = Port.HostPort;
203 result.ContainerPort = Port.ContainerPort;
204 result.Family = Port.Family;
205 result.Protocol = Port.Protocol;
206 CopyString(result.BindingAddress, Port.BindingAddress);
207 return result;
208 }
209
210 WSLCTmpfsMount Convert(const WSLCCompatTmpfsMount& Mount)
211 {
212 WSLCTmpfsMount result{};
213 result.Destination = Mount.Destination;
214 result.Options = Mount.Options;
215 return result;
216 }
217
218 WSLCUlimit Convert(const WSLCCompatUlimit& Ulimit)
219 {
220 WSLCUlimit result{};
221 result.Name = Ulimit.Name;
222 result.Soft = Ulimit.Soft;
223 result.Hard = Ulimit.Hard;
224 return result;
225 }
226
227 WSLCDeleteImageOptions Convert(const WSLCCompatDeleteImageOptions& Options)
228 {
229 WSLCDeleteImageOptions result{};
230 result.Image = Options.Image;
231 result.Flags = Options.Flags;
232 return result;
233 }
234
235 WSLCTagImageOptions Convert(const WSLCCompatTagImageOptions& Options)
236 {
237 WSLCTagImageOptions result{};
238 result.Image = Options.Image;
239 result.Repo = Options.Repo;
240 result.Tag = Options.Tag;
241 return result;
242 }
243
244 WSLCCompatImageInformation Convert(const WSLCImageInformation& Image)
245 {
246 WSLCCompatImageInformation result{};
247 CopyString(result.Image, Image.Image);
248 CopyString(result.Hash, Image.Hash);
249 CopyString(result.Digest, Image.Digest);
250 result.Size = Image.Size;
251 result.Created = Image.Created;
252 CopyString(result.ParentId, Image.ParentId);
253 return result;
254 }
255
256 WSLCCompatDeletedImageInformation Convert(const WSLCDeletedImageInformation& Image)
257 {
258 WSLCCompatDeletedImageInformation result{};
259 CopyString(result.Image, Image.Image);
260 result.Type = Image.Type;
261 return result;
262 }
263
264 WSLCCompatVolumeInformation Convert(const WSLCVolumeInformation& Volume)
265 {
266 WSLCCompatVolumeInformation result{};
267 CopyString(result.Name, Volume.Name);
268 CopyString(result.Driver, Volume.Driver);
269 return result;
270 }
271
272 //
273 // Composite struct conversions.
274 //
275
276 ContainerOptionsConversion::ContainerOptionsConversion(const WSLCCompatContainerOptions& Options)
277 {
278 m_value.Image = Options.Image;
279 m_value.Name = Options.Name;
280 m_value.Entrypoint = Convert(Options.Entrypoint);
281 m_value.InitProcessOptions = Convert(Options.InitProcessOptions);
282
283 m_volumes = ConvertArray<WSLCVolume>(Options.Volumes, Options.VolumesCount);
284 m_value.Volumes = m_volumes.empty() ? nullptr : m_volumes.data();
285 m_value.VolumesCount = Options.VolumesCount;
286
287 m_ports = ConvertArray<WSLCPortMapping>(Options.Ports, Options.PortsCount);
288 m_value.Ports = m_ports.empty() ? nullptr : m_ports.data();
289 m_value.PortsCount = Options.PortsCount;
290
291 m_labels = ConvertArray<WSLCLabel>(Options.Labels, Options.LabelsCount);
292 m_value.Labels = m_labels.empty() ? nullptr : m_labels.data();
293 m_value.LabelsCount = Options.LabelsCount;
294
295 m_value.Flags = Options.Flags;
296 m_value.StopSignal = Options.StopSignal;
297 m_value.HostName = Options.HostName;
298 m_value.DomainName = Options.DomainName;
299
300 m_value.DnsServers = Convert(Options.DnsServers);
301 m_value.DnsSearchDomains = Convert(Options.DnsSearchDomains);
302 m_value.DnsOptions = Convert(Options.DnsOptions);
303
304 m_value.ShmSize = Options.ShmSize;
305
306 // Container network (nested arrays whose elements have their own arrays).
307 m_value.ContainerNetwork.NetworkMode = Options.ContainerNetwork.NetworkMode;
308 const ULONG networksCount = Options.ContainerNetwork.NetworksCount;
309 THROW_HR_IF(E_INVALIDARG, networksCount > 0 && Options.ContainerNetwork.Networks == nullptr);
310
311 m_networks.reserve(networksCount);
312 m_networkSettings.reserve(networksCount);
313 for (ULONG index = 0; index < networksCount; index++)
314 {
315 const auto& network = Options.ContainerNetwork.Networks[index];
316 THROW_HR_IF(E_INVALIDARG, network.SettingsCount > 0 && network.Settings == nullptr);
317
318 m_networkSettings.push_back(ConvertArray<KeyValuePair>(network.Settings, network.SettingsCount));
319
320 WSLCNetworkConnection connection{};
321 connection.NetworkName = network.NetworkName;
322 connection.Settings = m_networkSettings.back().empty() ? nullptr : m_networkSettings.back().data();
323 connection.SettingsCount = network.SettingsCount;
324 m_networks.push_back(connection);
325 }
326
327 m_value.ContainerNetwork.Networks = m_networks.empty() ? nullptr : m_networks.data();
328 m_value.ContainerNetwork.NetworksCount = networksCount;
329
330 m_tmpfs = ConvertArray<WSLCTmpfsMount>(Options.Tmpfs, Options.TmpfsCount);
331 m_value.Tmpfs = m_tmpfs.empty() ? nullptr : m_tmpfs.data();
332 m_value.TmpfsCount = Options.TmpfsCount;
333
334 m_namedVolumes = ConvertArray<WSLCNamedVolume>(Options.NamedVolumes, Options.NamedVolumesCount);
335 m_value.NamedVolumes = m_namedVolumes.empty() ? nullptr : m_namedVolumes.data();
336 m_value.NamedVolumesCount = Options.NamedVolumesCount;
337
338 m_value.MemoryBytes = Options.MemoryBytes;
339 m_value.NanoCpus = Options.NanoCpus;
340
341 m_ulimits = ConvertArray<WSLCUlimit>(Options.Ulimits, Options.UlimitsCount);
342 m_value.Ulimits = m_ulimits.empty() ? nullptr : m_ulimits.data();
343 m_value.UlimitsCount = Options.UlimitsCount;
344 }
345
346 ListImagesOptionsConversion::ListImagesOptionsConversion(const WSLCCompatListImagesOptions& Options)
347 {
348 m_value.Flags = Options.Flags;
349
350 m_filters = ConvertArray<WSLCFilter>(Options.Filters, Options.FiltersCount);
351 m_value.Filters = m_filters.empty() ? nullptr : m_filters.data();
352 m_value.FiltersCount = Options.FiltersCount;
353 }
354
355 VolumeOptionsConversion::VolumeOptionsConversion(const WSLCCompatVolumeOptions& Options)
356 {
357 m_value.Name = Options.Name;
358 m_value.Driver = Options.Driver;
359
360 m_driverOpts = ConvertArray<WSLCDriverOption>(Options.DriverOpts, Options.DriverOptsCount);
361 m_value.DriverOpts = m_driverOpts.empty() ? nullptr : m_driverOpts.data();
362 m_value.DriverOptsCount = Options.DriverOptsCount;
363
364 m_labels = ConvertArray<WSLCLabel>(Options.Labels, Options.LabelsCount);
365 m_value.Labels = m_labels.empty() ? nullptr : m_labels.data();
366 m_value.LabelsCount = Options.LabelsCount;
367 }
368
369 SessionSettingsConversion::SessionSettingsConversion(const WSLCCompatSessionSettings& Settings)
370 {
371 m_value.DisplayName = Settings.DisplayName;
372 m_value.StoragePath = Settings.StoragePath;
373 m_value.MaximumStorageSizeMb = Settings.MaximumStorageSizeMb;
374 m_value.CpuCount = Settings.CpuCount;
375 m_value.MemoryMb = Settings.MemoryMb;
376 m_value.BootTimeoutMs = Settings.BootTimeoutMs;
377 m_value.NetworkingMode = Settings.NetworkingMode;
378
379 m_value.FeatureFlags = Settings.FeatureFlags;
380 m_value.DmesgOutput = Convert(Settings.DmesgOutput);
381 m_value.StorageFlags = Settings.StorageFlags;
382 m_value.RootVhdOverride = Settings.RootVhdOverride;
383 m_value.RootVhdTypeOverride = Settings.RootVhdTypeOverride;
384 }
385
386 //
387 // Callback conversions.
388 //
389
390 Microsoft::WRL::ComPtr<ICrashDumpCallback> Convert(IWSLCCompatCrashDumpCallback* Callback)
391 {
392 Microsoft::WRL::ComPtr<ICrashDumpCallback> result;
393 if (Callback != nullptr)
394 {
395 result = Microsoft::WRL::Make<CrashDumpCallbackAdapter>(Callback);
396 }
397
398 return result;
399 }
400
401 Microsoft::WRL::ComPtr<IProgressCallback> Convert(IWSLCCompatProgressCallback* Callback)
402 {
403 Microsoft::WRL::ComPtr<IProgressCallback> result;
404 if (Callback != nullptr)
405 {
406 result = Microsoft::WRL::Make<ProgressCallbackAdapter>(Callback);
407 }
408
409 return result;
410 }
411
412 Microsoft::WRL::ComPtr<IWarningCallback> Convert(IWSLCCompatWarningCallback* Callback)
413 {
414 Microsoft::WRL::ComPtr<IWarningCallback> result;
415 if (Callback != nullptr)
416 {
417 result = Microsoft::WRL::Make<WarningCallbackAdapter>(Callback);
418 }
419
420 return result;
421 }
422
423 } // namespace wsl::windows::common::apicompat