| 1 | /*++ |
| 2 | |
| 3 | Copyright (c) Microsoft. All rights reserved. |
| 4 | |
| 5 | Module Name: |
| 6 | |
| 7 | WslCoreConfig.h |
| 8 | |
| 9 | Abstract: |
| 10 | |
| 11 | This file contains the WSL Core VM configuration helper class declaration. |
| 12 | |
| 13 | --*/ |
| 14 | |
| 15 | #pragma once |
| 16 | |
| 17 | #define T_ENUM(c, n) TraceLoggingValue(wsl::core::ToString((c).n), #n) |
| 18 | #define T_PRESENT(c, n) TraceLoggingValue((c).n == ConfigKeyPresence::Present, #n) |
| 19 | #define T_SET(c, n) TraceLoggingValue(!(c).n.empty(), #n "Set") |
| 20 | #define T_STRING(c, n) TraceLoggingValue((c).n.c_str(), #n) |
| 21 | #define T_VALUE(c, n) TraceLoggingValue((c).n, #n) |
| 22 | |
| 23 | #define CONFIG_TELEMETRY(c) \ |
| 24 | T_VALUE(c, BestEffortDnsParsing), T_VALUE(c, DhcpTimeout), T_VALUE(c, EnableAutoProxy), T_VALUE(c, EnableDebugConsole), \ |
| 25 | T_VALUE(c, EnableDebugShell), T_VALUE(c, EnableDhcp), T_VALUE(c, EnableDnsProxy), T_VALUE(c, EnableDnsTunneling), \ |
| 26 | T_VALUE(c, EnableGpuSupport), T_VALUE(c, EnableGuiApps), T_VALUE(c, EnableHardwarePerformanceCounters), \ |
| 27 | T_VALUE(c, EnableHostAddressLoopback), T_VALUE(c, EnableHostFileSystemAccess), T_VALUE(c, EnableIpv6), \ |
| 28 | T_VALUE(c, EnableLocalhostRelay), T_VALUE(c, EnableNestedVirtualization), T_VALUE(c, EnableSafeMode), \ |
| 29 | T_VALUE(c, EnableSparseVhd), T_VALUE(c, EnableVirtio), T_VALUE(c, EnableVirtio9p), T_VALUE(c, EnableVirtioFs), \ |
| 30 | T_VALUE(c, EnableVirtioFsAggregateShares), T_ENUM(c, FirewallConfigPresence), T_VALUE(c, IsolateDistroCgroup), \ |
| 31 | T_VALUE(c, KernelBootTimeout), T_SET(c, KernelCommandLine), T_VALUE(c, KernelDebugPort), T_STRING(c, KernelModulesList), \ |
| 32 | T_SET(c, KernelModulesPath), T_SET(c, KernelPath), T_VALUE(c, LoadDefaultKernelModules), \ |
| 33 | T_PRESENT(c, LoadKernelModulesPresence), T_VALUE(c, MaximumMemorySizeBytes), T_VALUE(c, MaximumProcessorCount), \ |
| 34 | T_ENUM(c, MemoryReclaim), T_VALUE(c, MemorySizeBytes), T_VALUE(c, MountDeviceTimeout), T_ENUM(c, NetworkingMode), \ |
| 35 | T_VALUE(c, ProcessorCount), T_SET(c, SwapFilePath), T_VALUE(c, SwapSizeBytes), T_VALUE(c, SwiotlbSizeBytes), \ |
| 36 | T_SET(c, SystemDistroPath), T_VALUE(c, VhdSizeBytes), T_VALUE(c, VmIdleTimeout), T_SET(c, VmSwitch) |
| 37 | |
| 38 | namespace wsl::core { |
| 39 | constexpr auto ToString(ConfigKeyPresence key) |
| 40 | { |
| 41 | switch (key) |
| 42 | { |
| 43 | case ConfigKeyPresence::Absent: |
| 44 | return "Absent"; |
| 45 | case ConfigKeyPresence::Present: |
| 46 | return "Present"; |
| 47 | default: |
| 48 | return "Invalid"; |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | enum class MemoryReclaimMode |
| 53 | { |
| 54 | Disabled, |
| 55 | Gradual, |
| 56 | DropCache |
| 57 | }; |
| 58 | |
| 59 | // Ensure the WslCoreConfig versions of the enum match the version that's used in mini init. |
| 60 | static_assert(static_cast<ULONG>(MemoryReclaimMode::Disabled) == LxMiniInitMemoryReclaimModeDisabled); |
| 61 | static_assert(static_cast<ULONG>(MemoryReclaimMode::Gradual) == LxMiniInitMemoryReclaimModeGradual); |
| 62 | static_assert(static_cast<ULONG>(MemoryReclaimMode::DropCache) == LxMiniInitMemoryReclaimModeDropCache); |
| 63 | |
| 64 | constexpr auto ToString(MemoryReclaimMode mode) |
| 65 | { |
| 66 | switch (mode) |
| 67 | { |
| 68 | case MemoryReclaimMode::Disabled: |
| 69 | return "Disabled"; |
| 70 | case MemoryReclaimMode::Gradual: |
| 71 | return "Gradual"; |
| 72 | case MemoryReclaimMode::DropCache: |
| 73 | return "DropCache"; |
| 74 | default: |
| 75 | return "Invalid"; |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | const std::map<std::string, MemoryReclaimMode, shared::string::CaseInsensitiveCompare> MemoryReclaimModes = { |
| 80 | {ToString(MemoryReclaimMode::Gradual), MemoryReclaimMode::Gradual}, |
| 81 | {ToString(MemoryReclaimMode::DropCache), MemoryReclaimMode::DropCache}, |
| 82 | {ToString(MemoryReclaimMode::Disabled), MemoryReclaimMode::Disabled}}; |
| 83 | |
| 84 | // N.B. These enum values are also used in InTune ADMX templates, if entries are added or removed ensure that existing |
| 85 | // values are not changed. |
| 86 | enum NetworkingMode |
| 87 | { |
| 88 | None = 0, |
| 89 | Nat = 1, |
| 90 | Bridged = 2, |
| 91 | Mirrored = 3, |
| 92 | Consomme = 4 |
| 93 | }; |
| 94 | |
| 95 | // Ensure the WslCoreConfig versions of the enum match the version that's used in mini init. |
| 96 | static_assert(static_cast<ULONG>(NetworkingMode::None) == LxMiniInitNetworkingModeNone); |
| 97 | static_assert(static_cast<ULONG>(NetworkingMode::Nat) == LxMiniInitNetworkingModeNat); |
| 98 | static_assert(static_cast<ULONG>(NetworkingMode::Bridged) == LxMiniInitNetworkingModeBridged); |
| 99 | static_assert(static_cast<ULONG>(NetworkingMode::Mirrored) == LxMiniInitNetworkingModeMirrored); |
| 100 | static_assert(static_cast<ULONG>(NetworkingMode::Consomme) == LxMiniInitNetworkingModeConsomme); |
| 101 | |
| 102 | constexpr auto ToString(NetworkingMode config) noexcept |
| 103 | { |
| 104 | switch (config) |
| 105 | { |
| 106 | case NetworkingMode::None: |
| 107 | return "None"; |
| 108 | case NetworkingMode::Nat: |
| 109 | return "Nat"; |
| 110 | case NetworkingMode::Bridged: |
| 111 | return "Bridged"; |
| 112 | case NetworkingMode::Mirrored: |
| 113 | return "Mirrored"; |
| 114 | case NetworkingMode::Consomme: |
| 115 | return "Consomme"; |
| 116 | default: |
| 117 | return "Invalid"; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | const std::map<std::string, wsl::core::NetworkingMode, shared::string::CaseInsensitiveCompare> NetworkingModes{ |
| 122 | {ToString(NetworkingMode::None), NetworkingMode::None}, |
| 123 | {ToString(NetworkingMode::Nat), NetworkingMode::Nat}, |
| 124 | {ToString(NetworkingMode::Bridged), NetworkingMode::Bridged}, |
| 125 | {ToString(NetworkingMode::Mirrored), NetworkingMode::Mirrored}, |
| 126 | {ToString(NetworkingMode::Consomme), NetworkingMode::Consomme}, |
| 127 | // Legacy alias: the Consomme networking mode was previously named "VirtioProxy". |
| 128 | {"VirtioProxy", NetworkingMode::Consomme}}; |
| 129 | |
| 130 | enum class FirewallAction |
| 131 | { |
| 132 | Invalid, |
| 133 | Allow, |
| 134 | Block |
| 135 | }; |
| 136 | |
| 137 | constexpr auto ToString(const FirewallAction Action) noexcept |
| 138 | { |
| 139 | switch (Action) |
| 140 | { |
| 141 | case FirewallAction::Allow: |
| 142 | return "Allow"; |
| 143 | case FirewallAction::Block: |
| 144 | return "Block"; |
| 145 | default: |
| 146 | return "Invalid"; |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | enum class FirewallRuleOperation |
| 151 | { |
| 152 | Invalid, |
| 153 | Add, |
| 154 | Delete |
| 155 | }; |
| 156 | |
| 157 | struct FirewallRuleConfiguration |
| 158 | { |
| 159 | // These values are shared_bstr because we make temporary copies (for example in ConfigureHyperVFirewall) |
| 160 | wil::shared_bstr RuleId; |
| 161 | wil::shared_bstr RuleName; |
| 162 | wil::shared_bstr Protocol; |
| 163 | std::vector<wil::shared_bstr> LocalPorts; |
| 164 | std::vector<wil::shared_bstr> LocalAddresses; |
| 165 | std::vector<wil::shared_bstr> RemoteAddresses; |
| 166 | FirewallRuleOperation RuleOperation; |
| 167 | // NOTE these are only applicable for HOST firewall rules |
| 168 | wil::shared_bstr LocalService; |
| 169 | wil::shared_bstr LocalApplication; |
| 170 | |
| 171 | FirewallRuleConfiguration& operator=(const FirewallRuleConfiguration&) = default; |
| 172 | FirewallRuleConfiguration& operator=(FirewallRuleConfiguration&&) = default; |
| 173 | FirewallRuleConfiguration(FirewallRuleConfiguration&&) = default; |
| 174 | FirewallRuleConfiguration(const FirewallRuleConfiguration&) = default; |
| 175 | |
| 176 | FirewallRuleConfiguration( |
| 177 | _In_ LPCWSTR RuleIdParam, |
| 178 | _In_opt_ LPCWSTR RuleNameParam = nullptr, |
| 179 | _In_opt_ LPCWSTR ProtocolParam = nullptr, |
| 180 | _In_ DWORD LocalPortsCountParam = 0, |
| 181 | _In_reads_opt_(LocalPortsCountParam) LPCWSTR* LocalPortsParam = nullptr, |
| 182 | _In_ DWORD LocalAddressesCountParam = 0, |
| 183 | _In_reads_opt_(LocalAddressesCountParam) LPCWSTR* LocalAddressesParam = nullptr, |
| 184 | _In_ DWORD RemoteAddressesCountParam = 0, |
| 185 | _In_reads_opt_(RemoteAddressesCountParam) LPCWSTR* RemoteAddressesParam = nullptr, |
| 186 | _In_opt_ LPCWSTR LocalServiceParam = nullptr, |
| 187 | _In_opt_ LPCWSTR LocalApplicationParam = nullptr, |
| 188 | _In_ FirewallRuleOperation RuleOperationParam = FirewallRuleOperation::Add) |
| 189 | { |
| 190 | RuleId = wil::make_bstr(RuleIdParam); |
| 191 | if (RuleNameParam) |
| 192 | { |
| 193 | RuleName = wil::make_bstr(RuleNameParam); |
| 194 | } |
| 195 | if (ProtocolParam) |
| 196 | { |
| 197 | Protocol = wil::make_bstr(ProtocolParam); |
| 198 | } |
| 199 | for (ULONG i = 0; i < LocalPortsCountParam; ++i) |
| 200 | { |
| 201 | LocalPorts.emplace_back(wil::make_bstr(LocalPortsParam[i])); |
| 202 | } |
| 203 | for (ULONG i = 0; i < LocalAddressesCountParam; ++i) |
| 204 | { |
| 205 | LocalAddresses.emplace_back(wil::make_bstr(LocalAddressesParam[i])); |
| 206 | } |
| 207 | for (ULONG i = 0; i < RemoteAddressesCountParam; ++i) |
| 208 | { |
| 209 | RemoteAddresses.emplace_back(wil::make_bstr(RemoteAddressesParam[i])); |
| 210 | } |
| 211 | if (LocalServiceParam) |
| 212 | { |
| 213 | LocalService = wil::make_bstr(LocalServiceParam); |
| 214 | } |
| 215 | if (LocalApplicationParam) |
| 216 | { |
| 217 | LocalApplication = wil::make_bstr(LocalApplicationParam); |
| 218 | } |
| 219 | RuleOperation = RuleOperationParam; |
| 220 | } |
| 221 | }; |
| 222 | |
| 223 | struct FirewallConfiguration |
| 224 | { |
| 225 | std::optional<GUID> VmCreatorId{}; |
| 226 | std::vector<FirewallRuleConfiguration> Rules{}; |
| 227 | FirewallAction DefaultLoopbackPolicy{FirewallAction::Invalid}; |
| 228 | |
| 229 | bool Enabled() const noexcept; |
| 230 | |
| 231 | void reset() noexcept; |
| 232 | |
| 233 | void Enable() noexcept; |
| 234 | }; |
| 235 | |
| 236 | namespace ConfigSetting { |
| 237 | static constexpr auto Kernel = "wsl2.kernel"; |
| 238 | static constexpr auto KernelCommandLine = "wsl2.kernelCommandLine"; |
| 239 | static constexpr auto KernelModules = "wsl2.kernelModules"; |
| 240 | static constexpr auto Memory = "wsl2.memory"; |
| 241 | static constexpr auto Processors = "wsl2.processors"; |
| 242 | static constexpr auto DebugConsole = "wsl2.debugConsole"; |
| 243 | static constexpr auto EarlyBootLogging = "wsl2.earlyBootLogging"; |
| 244 | static constexpr auto Swap = "wsl2.swap"; |
| 245 | static constexpr auto SwapFile = "wsl2.swapFile"; |
| 246 | static constexpr auto LocalhostForwarding = "wsl2.localhostForwarding"; |
| 247 | static constexpr auto NestedVirtualization = "wsl2.nestedVirtualization"; |
| 248 | static constexpr auto Virtio9p = "wsl2.virtio9p"; |
| 249 | static constexpr auto Virtiofs = "wsl2.virtiofs"; |
| 250 | static constexpr auto KernelDebugPort = "wsl2.kernelDebugPort"; |
| 251 | static constexpr auto GpuSupport = "wsl2.gpuSupport"; |
| 252 | static constexpr auto GuiApplications = "wsl2.guiApplications"; |
| 253 | static constexpr auto SystemDistro = "wsl2.systemDistro"; |
| 254 | static constexpr auto Telemetry = "wsl2.telemetry"; |
| 255 | static constexpr auto VmIdleTimeout = "wsl2.vmIdleTimeout"; |
| 256 | static constexpr auto DebugConsoleLogFile = "wsl2.debugConsoleLogFile"; |
| 257 | static constexpr auto KernelBootTimeout = "wsl2.kernelBootTimeout"; |
| 258 | static constexpr auto DistributionStartTimeout = "wsl2.distributionStartTimeout"; |
| 259 | static constexpr auto Virtio = "wsl2.virtio"; |
| 260 | static constexpr auto HostFileSystemAccess = "wsl2.hostFileSystemAccess"; |
| 261 | static constexpr auto MountDeviceTimeout = "wsl2.mountDeviceTimeout"; |
| 262 | static constexpr auto HardwarePerformanceCounters = "wsl2.hardwarePerformanceCounters"; |
| 263 | static constexpr auto NetworkingMode = "wsl2.networkingMode"; |
| 264 | static constexpr auto VmSwitch = "wsl2.vmSwitch"; |
| 265 | static constexpr auto MacAddress = "wsl2.macAddress"; |
| 266 | static constexpr auto Dhcp = "wsl2.dhcp"; |
| 267 | static constexpr auto DhcpTimeout = "wsl2.dhcpTimeout"; |
| 268 | static constexpr auto Ipv6 = "wsl2.ipv6"; |
| 269 | static constexpr auto DnsProxy = "wsl2.dnsProxy"; |
| 270 | static constexpr auto SafeMode = "wsl2.safeMode"; |
| 271 | static constexpr auto DefaultVhdSize = "wsl2.defaultVhdSize"; |
| 272 | static constexpr auto CrashDumpFolder = "wsl2.crashDumpFolder"; |
| 273 | static constexpr auto MaxCrashDumpCount = "wsl2.maxCrashDumpCount"; |
| 274 | static constexpr auto DistributionInstallPath = "general.distributionInstallPath"; |
| 275 | static constexpr auto InstanceIdleTimeout = "general.instanceIdleTimeout"; |
| 276 | static constexpr auto DnsTunneling = "wsl2.dnsTunneling"; |
| 277 | static constexpr auto Firewall = "wsl2.firewall"; |
| 278 | static constexpr auto AutoProxy = "wsl2.autoProxy"; |
| 279 | static constexpr auto LoadKernelModules = "wsl2.loadKernelModules"; |
| 280 | static constexpr auto LoadDefaultKernelModules = "wsl2.loadDefaultKernelModules"; |
| 281 | static constexpr auto IsolateDistroCgroup = "wsl2.isolateDistroCgroup"; |
| 282 | |
| 283 | namespace Experimental { |
| 284 | static constexpr auto NetworkingMode = "experimental.networkingMode"; |
| 285 | static constexpr auto AutoMemoryReclaim = "experimental.autoMemoryReclaim"; |
| 286 | static constexpr auto SparseVhd = "experimental.sparseVhd"; |
| 287 | static constexpr auto DnsTunneling = "experimental.dnsTunneling"; |
| 288 | static constexpr auto BestEffortDnsParsing = "experimental.bestEffortDnsParsing"; |
| 289 | static constexpr auto DnsTunnelingIpAddress = "experimental.dnsTunnelingIpAddress"; |
| 290 | static constexpr auto Firewall = "experimental.firewall"; |
| 291 | static constexpr auto AutoProxy = "experimental.autoProxy"; |
| 292 | static constexpr auto InitialAutoProxyTimeout = "experimental.initialAutoProxyTimeout"; |
| 293 | static constexpr auto IgnoredPorts = "experimental.ignoredPorts"; |
| 294 | static constexpr auto HostAddressLoopback = "experimental.hostAddressLoopback"; |
| 295 | static constexpr auto SetVersionDebug = "experimental.setVersionDebug"; |
| 296 | static constexpr auto Swiotlb = "experimental.swiotlb"; |
| 297 | static constexpr auto VirtioFsAggregateShares = "experimental.virtioFsAggregateShares"; |
| 298 | |
| 299 | } // namespace Experimental |
| 300 | } // namespace ConfigSetting |
| 301 | |
| 302 | struct Config |
| 303 | { |
| 304 | Config() = delete; |
| 305 | Config(_In_opt_ LPCWSTR Path = nullptr, _In_opt_ HANDLE UserToken = nullptr); |
| 306 | ~Config() = default; |
| 307 | |
| 308 | void Initialize(_In_opt_ HANDLE UserToken = nullptr); |
| 309 | void ParseConfigFile(_In_opt_ LPCWSTR ConfigFilePath, _In_opt_ HANDLE UserToken); |
| 310 | void SaveNetworkingSettings(_In_opt_ HANDLE UserToken) const; |
| 311 | static unsigned long WriteConfigFile(_In_ LPCWSTR ConfigFilePath, _In_ ConfigKey KeyToWrite, _In_ bool RemoveKey = false); |
| 312 | |
| 313 | std::filesystem::path KernelPath; |
| 314 | std::wstring KernelCommandLine; |
| 315 | std::wstring KernelModulesList; |
| 316 | std::filesystem::path KernelModulesPath; |
| 317 | UINT64 MemorySizeBytes = 0; |
| 318 | UINT64 MaximumMemorySizeBytes = 0; |
| 319 | int ProcessorCount = 0; |
| 320 | int MaximumProcessorCount = 0; |
| 321 | bool EnableDebugConsole = false; |
| 322 | bool EnableEarlyBootLogging = false; |
| 323 | UINT64 SwapSizeBytes = UINT64_MAX; |
| 324 | std::filesystem::path SwapFilePath; |
| 325 | bool EnableLocalhostRelay = true; |
| 326 | ConfigKeyPresence LocalhostRelayConfigPresence = ConfigKeyPresence::Absent; |
| 327 | ConfigKeyPresence LoadKernelModulesPresence = ConfigKeyPresence::Absent; |
| 328 | bool LoadDefaultKernelModules = true; |
| 329 | bool EnableNestedVirtualization = !shared::Arm64 && windows::common::helpers::IsWindows11OrAbove(); |
| 330 | bool EnableVirtio9p = false; |
| 331 | bool EnableVirtio = !shared::Arm64 || windows::common::helpers::IsWindows11OrAbove(); |
| 332 | bool EnableVirtioFs = false; |
| 333 | bool EnableVirtioFsAggregateShares = true; |
| 334 | int KernelDebugPort = 0; |
| 335 | bool EnableGpuSupport = true; |
| 336 | bool EnableGuiApps = true; |
| 337 | std::filesystem::path SystemDistroPath; |
| 338 | bool EnableTelemetry = shared::OfficialBuild; |
| 339 | int VmIdleTimeout = (60 * 1000); |
| 340 | int InstanceIdleTimeout = (15 * 1000); |
| 341 | std::filesystem::path DebugConsoleLogFile; |
| 342 | std::wstring VmSwitch; |
| 343 | int KernelBootTimeout = (30 * 1000); |
| 344 | int DistributionStartTimeout = (60 * 1000); |
| 345 | int MountDeviceTimeout = (5 * 1000); |
| 346 | bool EnableHostFileSystemAccess = true; |
| 347 | bool EnableDhcp = true; |
| 348 | bool EnableIpv6 = false; |
| 349 | int DhcpTimeout = (5 * 1000); |
| 350 | NetworkingMode NetworkingMode = NetworkingMode::Nat; |
| 351 | ConfigKeyPresence NetworkingModePresence = ConfigKeyPresence::Absent; |
| 352 | bool EnableDnsProxy = true; |
| 353 | bool EnableSafeMode = false; |
| 354 | bool EnableDnsTunneling = true; |
| 355 | std::filesystem::path DefaultDistributionLocation; |
| 356 | ConfigKeyPresence DnsTunnelingConfigPresence = ConfigKeyPresence::Absent; |
| 357 | // Only applicable when DNS tunneling is enabled |
| 358 | // |
| 359 | // In a DNS request from Linux there might be DNS records that Windows DNS client does not know how to parse. |
| 360 | // By default in this case Windows will fail the request. When the flag is enabled, Windows will extract the |
| 361 | // question from the DNS request and attempt to resolve it, ignoring the unknown records |
| 362 | bool BestEffortDnsParsing = false; |
| 363 | // Only applicable when DNS tunneling is enabled |
| 364 | // IP address that will be used by the DNS listener/proxy used for DNS tunneling. Some scenarios (such as native Docker) |
| 365 | // require Linux nameserver to be an IP that is not in the range 127.0.0.0/8. This config is intended for those scenarios. |
| 366 | std::optional<uint32_t> DnsTunnelingIpAddress; |
| 367 | bool EnableHardwarePerformanceCounters = !shared::Arm64; |
| 368 | bool EnableAutoProxy = true; |
| 369 | int InitialAutoProxyTimeout = 1000; |
| 370 | MemoryReclaimMode MemoryReclaim = MemoryReclaimMode::DropCache; |
| 371 | bool EnableSparseVhd = false; |
| 372 | UINT64 VhdSizeBytes = 0x10000000000; // 1TB |
| 373 | |
| 374 | wsl::shared::string::MacAddress MacAddress; |
| 375 | std::wstring NatIpAddress; |
| 376 | std::wstring NatGateway; |
| 377 | std::wstring NatNetwork; |
| 378 | bool EnableDebugShell = true; |
| 379 | FirewallConfiguration FirewallConfig; |
| 380 | ConfigKeyPresence FirewallConfigPresence = ConfigKeyPresence::Absent; |
| 381 | std::set<uint16_t> IgnoredPorts; |
| 382 | bool EnableHostAddressLoopback = false; |
| 383 | std::filesystem::path CrashDumpFolder; |
| 384 | int MaxCrashDumpCount = 10; |
| 385 | UINT64 SwiotlbSizeBytes = 0; |
| 386 | bool IsolateDistroCgroup = true; |
| 387 | |
| 388 | // Temporary config value to help root cause the truncated archive errors in SetVersion() |
| 389 | bool SetVersionDebug = false; |
| 390 | |
| 391 | GUID NatNetworkId() const noexcept; |
| 392 | LPCWSTR NatNetworkName() const noexcept; |
| 393 | }; |
| 394 | } // namespace wsl::core |