master
md 398 lines 17.2 KB
Rendered Raw
1 # Windows Subsystem for Linux (WSL)
2
3 **ALWAYS reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.**
4
5 WSL is the Windows Subsystem for Linux - a compatibility layer for running Linux binary executables natively on Windows. This repository contains the core Windows components that enable WSL functionality.
6
7 ## Coding Conventions
8
9 ### Naming
10
11 - **Classes/Structs**: `PascalCase` (e.g., `ConsoleProgressBar`, `DeviceHostProxy`)
12 - **Functions/Methods**: `PascalCase()` (e.g., `GetFamilyName()`, `MultiByteToWide()`)
13 - **Member variables**: `m_camelCase` (e.g., `m_isOutputConsole`, `m_outputHandle`)
14 - **Local variables**: `camelCase` (e.g., `distroGuidString`, `asyncResponse`)
15 - **Constants**: `c_camelCase` with `constexpr` (e.g., `constexpr size_t c_progressBarWidth = 58;`)
16 - **Namespaces**: lowercase with `::` nesting (e.g., `wsl::windows::common::registry`)
17 - **Enums**: `PascalCaseValue` (e.g., `LxssDistributionStateInstalled`)
18 - **Windows types**: Keep as-is (`LPCWSTR`, `HRESULT`, `DWORD`, `ULONG`, `GUID`)
19
20 ### Error Handling
21
22 Use WIL (Windows Implementation Libraries) macros — **never** bare `if (FAILED(hr))`:
23 - `THROW_IF_FAILED(hr)` — throw on HRESULT failure
24 - `THROW_HR_IF(hr, condition)` — conditional throw
25 - `THROW_HR_IF_MSG(hr, condition, fmt, ...)` — conditional throw with message
26 - `THROW_IF_NULL_ALLOC(ptr)` — throw on null allocation
27 - `THROW_LAST_ERROR_IF(condition)` — throw last Win32 error
28 - `RETURN_IF_FAILED(hr)` — return HRESULT on failure (no throw)
29 - `RETURN_LAST_ERROR_IF_EXPECTED(condition)` — expected failure path
30 - `LOG_IF_FAILED(hr)` — log but don't throw
31 - `CATCH_LOG()` — catch and log exceptions
32
33 For user-facing errors, set a localized message before throwing:
34 ```cpp
35 THROW_HR_WITH_USER_ERROR(E_INVALIDARG, Localization::MessageConfigInvalidBoolean(name, value));
36 ```
37
38 At API boundaries (COM interfaces), return `HRESULT` with out params. Internal code throws exceptions.
39
40 ### Memory Management and RAII
41
42 Use WIL smart pointers — **never** raw `CloseHandle()` or manual cleanup:
43 - `wil::unique_handle` — kernel handles
44 - `wil::com_ptr<T>` — COM objects
45 - `wil::unique_hfile` — file handles
46 - `wil::unique_hkey` — registry keys
47 - `wil::unique_event` — events
48 - `wil::unique_hlocal_string` — HLOCAL strings
49 - `wil::unique_cotaskmem_string` — CoTaskMem strings
50
51 For non-standard resource types, use `wil::unique_any<Type, Deleter, Fn>`.
52
53 For cleanup scopes, use `wil::scope_exit`:
54 ```cpp
55 auto cleanup = wil::scope_exit([&] { registry::DeleteKey(LxssKey, guid.c_str()); });
56 // ... work ...
57 cleanup.release(); // dismiss on success
58 ```
59
60 ### Synchronization
61
62 Use `wil::srwlock` (Slim Reader/Writer locks) with SAL annotations:
63 ```cpp
64 mutable wil::srwlock m_lock;
65 _Guarded_by_(m_lock) std::vector<Entry> m_entries;
66 ```
67
68 ### Strings
69
70 - `std::wstring` / `std::wstring_view` are dominant throughout the codebase
71 - Use `MultiByteToWide()` / `WideToMultiByte()` from `stringshared.h` for conversions
72 - Use `std::format()` for formatting (the repo defines `std::formatter<std::wstring, char>` for wide-to-narrow support)
73 - The `STRING_TO_WIDE_STRING()` macro handles compile-time conversion
74
75 ### Copy/Move Semantics
76
77 Use macros from `defs.h` to declare copy/move behavior:
78 ```cpp
79 NON_COPYABLE(MyClass);
80 NON_MOVABLE(MyClass);
81 DEFAULT_MOVABLE(MyClass);
82 ```
83
84 ### Headers
85
86 - Use `#pragma once` (no traditional `#ifndef` include guards)
87 - In Windows C++ components, every `.cpp` file must start with `#include "precomp.h"`
88 - Linux-side code (`src/linux/`) does not use precompiled headers
89 - Use `.h` for C-compatible headers, `.hpp` for C++-only headers
90 - Include order is enforced by `.clang-format` (precomp first, then system, then project)
91
92 ### Copyright Headers
93
94 Use this single-line format for new files:
95 ```cpp
96 // Copyright (C) Microsoft Corporation. All rights reserved.
97 ```
98
99 Some older files use the block format (`/*++ Copyright (c) Microsoft. All rights reserved. ... --*/`). Match the surrounding files in the same directory when editing.
100
101 ### Localization
102
103 - Use `wsl::shared::Localization::MessageXxx()` static methods for user-facing strings
104 - Use `EMIT_USER_WARNING(Localization::MessageXxx(...))` for non-fatal config warnings
105 - All new user-facing strings must have entries in `localization/strings/en-US/Resources.resw`
106 - In Resources.resw comments, use `{Locked="..."}` to prevent translation of `.wslconfig` property key names
107 - Localized files are generated by a separate localization team and regenerated downstream, so translation edits in a GitHub PR cannot be merged (they would be overwritten). This covers the per-locale `localization/strings/<locale>/Resources.resw` UI strings and the per-locale `intune/<locale>/WSL.adml` policy templates (anything other than the `en-US` sources and the neutral `intune/WSL.admx`). Filing a GitHub issue is the correct path for contributors; see `CONTRIBUTING.md`. Ignore this guidance for automated localization-service PRs that are generated by that pipeline.
108 - Community localization reports come in as **both GitHub issues and pull requests** - when triaging, look for both and file a tracking Bug for each. These are tracked via Bugs in the GCS Azure DevOps project, not merged directly. See `.github/copilot/localization-bugs.md` for the project coordinates, required fields, and `az boards` workflow.
109
110 ### Telemetry and Logging
111
112 - `WSL_LOG(Name, ...)` — standard trace event
113 - `WSL_LOG_DEBUG(Name, ...)` — debug-only (compiled out in release via `if constexpr`)
114 - `WSL_LOG_TELEMETRY(Name, Tag, ...)` — metrics with privacy tag and version info
115 - Provider: `g_hTraceLoggingProvider`, initialized via `WslTraceLoggingInitialize()`
116
117 ### Platform Conditionals
118
119 Prefer `constexpr` checks over `#ifdef` where possible:
120 ```cpp
121 if constexpr (wsl::shared::Debug) { /* debug-only code */ }
122 if constexpr (wsl::shared::Arm64) { /* ARM64-specific code */ }
123 ```
124
125 For compiler-specific code, use `#ifdef _MSC_VER` (Windows) / `#ifdef __GNUC__` (Linux).
126
127 ### Formatting
128
129 Enforced by `.clang-format`:
130 - 130 character column limit
131 - 4-space indentation, no tabs
132 - Allman-style braces (opening brace on new line for classes, functions, structs, control statements)
133 - Left-aligned pointers (`int* ptr`, not `int *ptr`)
134 - `InsertBraces: true` — all control statements must have braces
135
136 ### IDL / COM Conventions
137
138 When modifying service interfaces (`src/windows/service/inc/`):
139 - Interface attributes on separate lines: `[uuid(...), pointer_default(unique), object]`
140 - String params: `[in, unique] LPCWSTR` with `[string]` for marshaled strings
141 - Handle params: `[in, system_handle(sh_file)] HANDLE`
142 - User-facing errors: pass `[in, out] LXSS_ERROR_INFO* Error`
143 - **ABI stability applies only to SDK-facing and public surfaces.** `WSLCCompat.idl` (the WSLC SDK-facing layer) and the public plugin API (`WslPluginApi.h`) must stay backward compatible: do not add, remove, or reorder methods on their existing interfaces, and do not change struct layouts. Introduce a new versioned interface with a new IID instead. Every other interface (`IWSLCSession` in `wslc.idl`, the interfaces in `wslservice.idl`, etc.) is internal and non-stable: rebuilt and shipped in lockstep with its only clients, so appending new methods to those is fine.
144 - Custom error codes: `WSL_E_xxx` via `MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSL_E_BASE + N)`
145
146 ### Config File (.wslconfig) Conventions
147
148 When adding settings to `src/shared/configfile/`:
149 - Format is `.gitconfig`-style INI: `[section]`, `key = value`, `#` comments, `\` line continuation
150 - Use the `ConfigKey` template class for type-safe parsing
151 - Supported types: `bool`, `int` (hex/octal), `std::string`, `std::wstring`, `MemoryString`, `MacAddress`, enum maps
152 - Report invalid values with `EMIT_USER_WARNING(Localization::MessageConfigXxx(...))`
153 - New settings require a corresponding localization string in Resources.resw
154
155 ## Repository Navigation
156
157 ### Key Directories
158 - `src/windows/` — Main Windows WSL service components
159 - `src/linux/` — Linux-side WSL components
160 - `src/shared/` — Shared code between Windows and Linux
161 - `test/windows/` — Windows-based tests (TAEF framework)
162 - `test/linux/unit_tests/` — Linux unit test suite
163 - `doc/` — Documentation source (MkDocs)
164 - `tools/` — Build and deployment scripts
165 - `distributions/` — Distribution validation and metadata
166 - `localization/` — Localized string resources
167
168 ### Namespace → Directory Map
169
170 | Namespace | Location |
171 |---|---|
172 | `wsl::shared::` | `src/shared/` |
173 | `wsl::windows::common::` | `src/windows/common/` |
174 | `wsl::windows::service::` | `src/windows/service/exe/` |
175 | `wsl::core::` | `src/windows/service/exe/` |
176 | `wsl::core::networking::` | `src/windows/common/` + `src/windows/service/exe/` |
177 | `wsl::linux::` | `src/linux/init/` |
178
179 ### Key Files
180 - `src/shared/inc/defs.h` — Shared platform definitions (NON_COPYABLE, Debug, Arm64, etc.)
181 - `src/shared/inc/stringshared.h` — String conversion utilities
182 - `src/windows/common/WslTelemetry.h` — Telemetry macros
183 - `src/windows/common/ExecutionContext.h` — Error context and user-facing error macros
184 - `src/windows/service/inc/wslservice.idl` — Main service COM interface definitions
185 - `src/windows/service/inc/wslc.idl` — Container COM interface definitions
186 - `src/windows/inc/WslPluginApi.h` — Plugin API header
187 - `src/shared/configfile/configfile.h` — Config file parser
188 - `.clang-format` — Code formatting rules (130 col, 4-space indent, Allman braces)
189
190 ## Building and Deploying
191
192 ### Critical Platform Requirements
193 - **Full builds ONLY work on Windows** with Visual Studio and Windows SDK 26100
194 - **DO NOT attempt to build the main WSL components on Linux** — they require Windows-specific APIs, MSBuild, and Visual Studio toolchain
195 - Many validation and development tasks CAN be performed on Linux (documentation, formatting, Python validation scripts)
196
197 ### Windows Build Requirements
198 - CMake >= 3.25 (`winget install Kitware.CMake`)
199 - Visual Studio with these components:
200 - Windows SDK 26100
201 - MSBuild
202 - Universal Windows platform support for v143 build tools (X64 and ARM64)
203 - MSVC v143 - VS 2022 C++ ARM64 build tools (Latest + Spectre) (X64 and ARM64)
204 - C++ core features
205 - C++ ATL for latest v143 tools (X64 and ARM64)
206 - C++ Clang compiler for Windows
207 - .NET desktop development
208 - .NET WinUI app development tools
209 - Enable Developer Mode in Windows Settings OR run with Administrator privileges (required for symbolic link support)
210
211 ### Building WSL (Windows Only)
212 1. Clone the repository
213 2. Generate Visual Studio solution: `cmake .`
214 3. Build: `cmake --build . -- -m` OR open `wsl.sln` in Visual Studio
215
216 Build parameters:
217 - `cmake . -A arm64` — Build for ARM64
218 - `cmake . -DCMAKE_BUILD_TYPE=Release` — Release build
219 - `cmake . -DBUILD_BUNDLE=TRUE` — Build bundle MSIX package (requires ARM64 built first)
220
221 ### Deploying WSL (Windows Only)
222 - Install MSI: `bin\<platform>\<target>\wsl.msi`
223 - OR use script: `powershell tools\deploy\deploy-to-host.ps1`
224 - For Hyper-V VM: `powershell tools\deploy\deploy-to-vm.ps1 -VmName <vm> -Username <user> -Password <pass>`
225
226 ## Testing
227
228 ### Writing Tests (TAEF Framework)
229
230 Tests use TAEF. See `.github/copilot/test.md` for detailed patterns and macros.
231
232 Key points:
233 - Use `WSL_TEST_CLASS(Name)` — not raw `BEGIN_TEST_CLASS`
234 - Use `VERIFY_*` macros for assertions (`VERIFY_ARE_EQUAL`, `VERIFY_IS_TRUE`, etc.)
235 - Skip macros: `WSL1_TEST_ONLY()`, `WSL2_TEST_ONLY()`, `SKIP_TEST_ARM64()`
236 - Test infrastructure is in `test/windows/Common.h`
237
238 ### Running Tests (Windows Only)
239
240 **CRITICAL: ALWAYS build the ENTIRE project before running tests:**
241 ```powershell
242 cmake --build . -- -m
243 bin\<platform>\<target>\test.bat
244 ```
245
246 **Why full build is required:**
247 - Tests depend on multiple components (libwsl.dll, wsltests.dll, wslservice.exe, etc.)
248 - Partial builds will cause test failures
249 - **DO NOT skip the full build step even if only one file changed**
250
251 Test execution:
252 - Run all tests: `bin\<platform>\<target>\test.bat`
253 - Run subset: `bin\<platform>\<target>\test.bat /name:*UnitTest*`
254 - Run specific test: `bin\<platform>\<target>\test.bat /name:<class>::<test>`
255 - WSL1 tests: Add `-Version 1` flag
256 - Fast mode (after first run): Add `-f` flag (requires `wsl --set-default test_distro`)
257 - **Requires Administrator privileges**
258
259 Test debugging:
260 - Attach WinDbgX automatically: `/attachdebugger`
261 - Wait for debugger (manual attach): `/waitfordebugger`
262 - Break on failure: `/breakonfailure`
263 - Run in-process: `/inproc`
264
265 ### Linux Unit Tests (Linux Only)
266 - Location: `test/linux/unit_tests/`
267 - Build script: `test/linux/unit_tests/build_tests.sh`
268 - **Note**: Requires specific Linux build environment setup not covered in main build process
269
270 ## Cross-Platform Validation Tasks
271
272 ### Documentation (Works on Linux/Windows)
273 - Install tools: `pip install mkdocs-mermaid2-plugin mkdocs --break-system-packages`
274 - Build docs: `mkdocs build -f doc/mkdocs.yml`
275 - Output location: `doc/site/`
276 - **Note**: May show warnings about mermaid CDN access on restricted networks
277
278 ### Code Formatting and Validation
279 - Format all source (Windows, requires `cmake .` first): `.\FormatSource.ps1`
280 - Format check (Linux/cross-platform): `clang-format --dry-run --style=file <files>`
281 - Validate copyright headers: `python3 tools/devops/validate-copyright-headers.py`
282 - **Note**: Will report missing headers in generated/dependency files (`_deps/`), which is expected
283 - Validate localization: `python3 tools/devops/validate-localization.py`
284 - **Note**: Only works after Windows build (requires `localization/strings/en-US/Resources.resw`)
285
286 ### Distribution Validation (Limited on Linux)
287 - Validate distribution info: `python3 distributions/validate.py distributions/DistributionInfo.json`
288 - **Note**: May fail on Linux due to network restrictions accessing distribution URLs
289
290 ### Pre-commit Checklist
291 Always run before committing:
292 1. `.\FormatSource.ps1` to verify formatting on changed C++ files
293 2. `python3 tools/devops/validate-copyright-headers.py` (ignore `_deps/` warnings)
294 3. `mkdocs build -f doc/mkdocs.yml` if documentation changed
295 4. Full Windows build if core components changed
296
297 **Note**: The `.gitignore` properly excludes build artifacts (`*.sln`, `*.dll`, `*.pdb`, `obj/`, `bin/`, etc.) — do not commit these files.
298
299 ## Frequently Used Commands
300
301 ### Windows Development
302 ```powershell
303 # Initial setup
304 cmake .
305 cmake --build . -- -m
306
307 # Deploy and test
308 powershell tools\deploy\deploy-to-host.ps1
309 wsl --version
310
311 # Run tests
312 bin\x64\debug\test.bat
313 ```
314
315 ### Cross-Platform Validation
316 ```powershell
317 # Documentation
318 mkdocs build -f doc/mkdocs.yml
319
320 # Code formatting (Windows)
321 .\FormatSource.ps1
322
323 # Copyright header validation (reports expected issues in _deps/)
324 python3 tools/devops/validate-copyright-headers.py
325
326 # Distribution validation (may fail on networks without external access)
327 python3 distributions/validate.py distributions/DistributionInfo.json
328 ```
329
330 ## Debugging and Logging
331
332 ### ETL Tracing (Windows Only)
333 ```powershell
334 # Collect traces
335 wpr -start diagnostics\wsl.wprp -filemode
336 # [reproduce issue]
337 wpr -stop logs.ETL
338
339 # Available profiles:
340 # - WSL (default) - General WSL tracing
341 # - WSL-Storage - Enhanced storage tracing
342 # - WSL-Networking - Comprehensive networking tracing
343 # - WSL-HvSocket - HvSocket-specific tracing
344 # Example: wpr -start diagnostics\wsl.wprp!WSL -filemode
345 ```
346
347 ### Log Analysis Tools
348 - Use WPA (Windows Performance Analyzer) for ETL traces
349 - Key providers: `Microsoft.Windows.Lxss.Manager`, `Microsoft.Windows.Subsystem.Lxss`
350 - For graphical/audio (WSLg) issues, see `.github/copilot/wslg-logs.md`. `collect-wsl-logs.ps1` gathers WSLg logs (`/mnt/wslg`: weston.log, pulseaudio.log, wlog.log, stderr.log, versions.txt) into a `wslg/` folder using `wsl.exe --system --user root`; crash dumps (`%TEMP%\wsl-crashes`, legacy `/mnt/wslg/dumps`) are only collected with `-Dump`. WSLg code lives in https://github.com/microsoft/wslg, not this repo.
351
352 ### Debug Console (Linux)
353 Add to `%USERPROFILE%\.wslconfig`:
354 ```ini
355 [wsl2]
356 debugConsole=true
357 ```
358
359 ### Common Debugging Commands
360 - Debug shell: `wsl --debug-shell`
361 - Collect WSL logs: `powershell diagnostics\collect-wsl-logs.ps1`
362 - Network logs: `powershell diagnostics\collect-wsl-logs.ps1 -LogProfile networking`
363
364 ## Timing and Timeout Guidelines
365
366 **NEVER CANCEL these operations — always wait for completion:**
367
368 | Operation | Typical Duration | Minimum Timeout |
369 |---|---|---|
370 | Full Windows build | 20-45 minutes | 60+ minutes |
371 | Full test suite | 30-60 minutes | 90+ minutes |
372 | Unit test subset | 5-15 minutes | 30+ minutes |
373 | Documentation build | ~0.5 seconds | 5+ minutes |
374 | Distribution validation | 2-5 minutes | 15+ minutes |
375
376 ## CI/CD Integration
377
378 ### GitHub Actions
379 - **distributions.yml** — Validates distribution metadata (Linux)
380 - **documentation.yml** — Builds and deploys docs (Linux)
381 - **modern-distributions.yml** — Tests modern distribution support
382
383 ## Development Environment Setup
384
385 ### Windows (Full Development)
386 1. Install Visual Studio with required components (listed above)
387 2. Install CMake 3.25+
388 3. Enable Developer Mode
389 4. Clone repository
390 5. Run `cmake .` to generate solution
391
392 ### Linux (Documentation/Validation Only)
393 1. Install Python 3.8+
394 2. Install docs tools: `pip install mkdocs-mermaid2-plugin mkdocs`
395 3. Clone repository
396 4. Run validation commands as needed
397
398 Remember: **This is a Windows-focused project**. While some tasks can be performed on Linux, full WSL development requires Windows with Visual Studio.