Windows Sandbox guest BugCheck 0x3B (dxgkrnl) — root cause, 26H1→26H2 binary analysis, and an independent <vGPU> finding
Report date: 2026-10-15
Upstream threads: microsoft/Windows-Sandbox #131 (Edge path, "build 26300.9539", open) · #132 (KB5124010 path, open, 18 comments)
Affected: Windows 11 26H2 (26300.9550, includes KB5124010) — Windows Sandbox
Reproduced on: Windows 11 26H2 Pro (26300.9550) with Intel integrated GPU; an independent reporter reproduced the same faulting instruction on an NVIDIA system.
Verification tooling used: stock WinDbg/cdb + Microsoft symbol server PDBs; Windows built-in ISO media; no WDK or custom drivers required.
Read this first (what this report adds over the earlier comments):
- The trigger is a user-mode addition:
d3d12core.dll build 9549 added one new CDevice method — EnsureDXGKExclusiveEngineAccessSupport — that did not exist in 26H1 (9278). It queries a new OS-category WDDM feature.
- The kernel-side defect is old: the consumer checks only
adapter != NULL, and the object it wrongly uses is the WARP software adapter that exists on every Windows. Byte-identical in 26H1 and 26H2.
- Correction to an earlier claim: KB5124010 did not expand the feature table. 26H1's dxgkrnl (9444) already contains the same feature table
{50, 10, 3, 19} as 26H2's (9549). The expansion happened before 26H1.
- New independent finding:
<vGPU>Disable</vGPU> in a .wsb does not prevent the host from provisioning the paravirtualized GPU — verified both at the host HCS layer and in the guest. Details in §5.
- Every claim below carries a source: a public URL, a system file path (+version), or a binary RVA that can be re-verified with a debugger. See Appendix A.
1. Impact and reproduction
| Item | Value |
|---|---|
| Crash type | Guest kernel BugCheck 0x3B (SYSTEM_SERVICE_EXCEPTION), arg2 = 0xC0000005, arg3 = guest kernel stack address |
| Faulting instruction | dxgkrnl!DXGVMBUSMESSAGE::InitializeMessage+0xDE → mov rax, qword ptr [rax+12C4h] with rax = 0 |
| Constant RVA | 0x35800A in dxgkrnl 10.0.26100.9549 (RVA & 0xFFF == 0xA); identical on 5+ independent dumps, across Task Manager / dxdiag / Edge triggers, and with both vGPU configurations |
| Time to crash | ~2–3 s after the triggering action (Task Manager); dxdiag stalls and faults when it reaches the display probe |
| Triggers observed | Opening Task Manager (performance tab), running dxdiag, browsing in Edge / Chromium-based apps (Firefox does not trigger) |
| Not affected | The Windows host outside the sandbox; <VGpu>Disable</VGpu> does not avoid it (see §5) |
Minimal reproduction (stock system, no extra tools):
- On Windows 11 26H2 (26300.9550 / any build including KB5124010), launch Windows Sandbox (default or with any
.wsb).
- In the guest, open Task Manager and switch to the performance tab.
- The guest VM terminates within seconds (kernel memory dump optional; see Appendix B).
2. The fault chain, step by step (26H1 vs 26H2 behavior at every step)
Builds under comparison (both extracted from official media, byte-for-byte verification in Table T0):
| File | 26H1 = ISO ...26300.9457... | 26H2 = ISO 26300.9550.260920-2000.26H2_GE_RELEASE... |
|---|---|---|
| dxgkrnl.sys | 10.0.26100.9444 (5,293,592 B) | 10.0.26100.9549 (5,316,048 B) |
| D3D12Core.dll | 10.0.26100.9278 (3,522,000 B) | 10.0.26100.9549 (3,562,784 B) |
| dxgmms2.sys | 9444 | 9549 |
| win32u.dll | 9444 | 9549 |
T0 — the failing system is exactly the 26H2 image. SHA256 of the four files above extracted from the 26H2 ISO equals the corresponding files on the failing machine (4/4 matches). Source: the two ISO files + C:\Windows\System32\drivers\dxgkrnl.sys etc. on the affected host.
Step 1 — Sandbox launch: the guest gets 4 adapter objects; one of them is the WARP software adapter
The host provisions a paravirtualized GPU (Virtual Render Device, PCI\VEN_1414&DEV_008E = vrd.inf) — per Microsoft's GPU-PV documentation, a GPU-PV guest shows exactly two adapters: a display adapter ("Microsoft Hyper-V Video Adapter or Microsoft Remote Display Adapter") and the Virtual Render Driver (source: GPU paravirtualization, learn.microsoft.com).
In the guest kernel, dxgglobal holds a doubly-linked list of four adapter objects: IndirectKmd → VirtualRender (VRD) → BasicRender → BasicDisplay. Field read-out from a kernel dump:
| adapter | role byte ext+0x1E1 | channel created (+0x44) | channel +0x48 | host_vgpu_luid (+0x12C4) |
|---|---|---|---|---|
| IndirectKmd | 0 | 0 | 0 | 0 |
| VirtualRender (VRD) | 1 | 1 | points to itself | 0x01914893 |
| BasicRender ← the one the faulting query lands on | 0 | 0 | 0 | 0 |
| BasicDisplay | 0 | 0 | 0 | 0 |
Only the VRD — the device that actually talks to the host — gets the per-adapter vGPU channel. This is correct by design: CreateVmBusChannel is called only from DXGADAPTER::Initialize behind cmp byte ptr [ext+0x1E1],0 (9549 RVA 0x1A4958, same instruction in 9444), and BasicRender is the render-only WARP adapter present on every Windows install (GPU-PV doc: "This display-only adapter is paired by default with the BasicRender adapter for rendering."). The empty channel on BasicRender is a correct terminal state, not missing data.
26H1 vs 26H2: identical. Same list, same fields, same channel writer (CreateVmBusChannel 9549 RVA 0x235768, writes +0x48 at 0x235793).
Step 2 — Task Manager / dxdiag / Edge create a D3D12 device
All three triggers converge on D3D12Core!CDevice construction (e.g. D3D12CoreCreateDevice → … → CDevice::LLOCompleteLayerConstruction). This step exists in both builds.
Step 3 — ★ The divergence: 26H2 issues the EEA feature query; 26H1 cannot
26H2 (d3d12core 9549): CDevice::LLOCompleteLayerConstruction (RVA 0x80081580) ends with three feature queries:
800825f7 lea rcx,[wil::Feature<__WilFeatureTraits_Feature_D3DVideoEncoderExclusiveAccess>::impl]
800825fe call ...__private_IsEnabled ; a wil feature switch (feature-flag controlled)
80082603 test al,al
80082605 je +0x108f ; OFF → skip the query below
80082607 mov rcx,rdi
8008260a call CDevice::EnsureDXGKExclusiveEngineAccessSupport ; ← THE NEW CALL (unique)
8008260f mov rcx,rdi
80082612 call CDevice::NativeFencesKernelFeatureEnabled ; query #2 (feature 0x25)
...
80083112 call CDevice::GPUUploadHeapOSSupported ; query #3 (feature 0x20000000)
and the new function itself (RVA 0xD0504, the whole thing is 0xDA bytes):
800d0558 xorps xmm0,xmm0
800d055b movdqu [rsp+28h],xmm0
800d0561 mov dword ptr [rsp+24h],10000009h ; feature id = 0x10000009
800d0569 mov rbx,[rdi+2E8h]
800d0574 mov r8d,[rdx+0F0h] ; mov [rsp+20h],r8d
800d0585 call guard_dispatch_icall$thunk ; call via resolved pointer
Before the call, the function resolves its entry point dynamically: GetModuleHandleA("gdi32.dll") + GetProcAddress("D3DKMTQueryFeatureInterface") (strings at RVA 0x293760 / 0x2935D8).
26H1 (d3d12core 9278): the same LLOCompleteLayerConstruction exists, but:
- The set of 392
CDevice:: symbols in 9278 vs 9549 differs by exactly one addition: CDevice::EnsureDXGKExclusiveEngineAccessSupport (9549 only). (The single removal, VersionedCreateComputeShader, is unrelated.)
- A byte scan of 9278's whole
.text finds zero occurrences of the immediate 0x10000009 in code (9549 has it at RVA 0xD0565; the only hex-match in 9278 is inside the Rich header, which is not code).
⇒ On 26H1 this query cannot be issued at all; on 26H2 it is issued on every D3D12 device creation and is protected by the Feature_D3DVideoEncoderExclusiveAccess wil switch.
Step 4 — User-mode forwarding (same in both builds)
gdi32!D3DKMTQueryFeatureInterface → API set ext-ms-win-dx-d3dkmt-dxcore-l1-1-5 → DXCore → win32u!NtDxgkIsFeatureEnabled (syscall 0x115F on this build). Frame-by-frame verification from a dump: the syscall entry frame carries no adapter pointer — the adapter is resolved inside the kernel from the user request.
Step 5 — Kernel routing: why this feature must "ask the host"
Microsoft's documentation for this mechanism states: "For GPU-PV, the OS automatically negotiates feature support and enablement between the host and guest" (source). The code path (all RVAs = dxgkrnl 9549; each function is instruction-identical in 9444 with shifted addresses):
NtDxgkIsFeatureEnabled (0x42A2C0)
→ DpiIsFeatureEnabled (0x42876C) ; adapter==NULL → global db; else 'Dprt'/v2 check → [obj+0x16D0] = per-adapter db
→ DxgkIsFeatureEnabled (0x19C2C8) ; cache shell (QueryCachedFeatureState / RecordCachedFeatureState)
→ IsFeatureEnabledUncached (0x432224) ; known-feature check, then routing by descriptor bits:
; desc[+4] bit5, DxgkIsVmConnectedToHost(), desc[+4] & 0x1C == 0x10
→ IsFeatureEnabledHost (0x43261C) ; [db+0x3C0] bit0 → NULL (global channel); else [db+0x3B8] as adapter
→ DxgkIsFeatureEnabledVmBus (0x6CCE0) ; ← the defect lives here
The three feature queries' descriptor entries (read directly from the static tables; identical in both builds — 9444 OS-table base 0x13C1A0, 9549 base 0x13D350):
| query | feature id | descriptor bytes | & 0x1C | routing |
|---|---|---|---|---|
| EEA | 0x10000009 | 01 00 01 00 33 00 | 0x10 | bit5=1 → in a VM always goes to the host |
| NativeFences | 0x00000025 | 01 00 01 00 4F 00 | 0x0C | conditional |
| GPUUploadHeap | 0x20000000 | 01 00 01 00 13 00 | 0x10 | conditional (bit5=0) |
Why the crash point is always EEA: the three queries run inside one device creation, in a fixed order (①Ensure → ②NativeFences → ③GPUUploadHeap), and they share the same target adapter. Query ① is the only one guaranteed to route to the host in a VM (descriptor bit5=1 + DxgkIsVmConnectedToHost=true) — so it is always the first to hit the defect; ② and ③ never get to execute.
Step 6 — The defective consumer and the fault
; dxgkrnl!DxgkIsFeatureEnabledVmBus (9549 RVA 0x6CCE0; 9444 RVA 0x6CE24, byte-identical instructions)
4006cd04 cmp dword ptr [rax+6C8h],2Bh ; VMBus interface version gate (observed value 0x2C ≥ 0x2B → open)
4006cd0b jae +0x4c
... (refusal path: log + return 0)
4006cd2c test rbx,rbx ; ★ THE ONLY check on the adapter
4006cd2f je +0x67 ; NULL → global channel (safe branch, exists)
4006cd31 lea rcx,[rbx+1258h] ; ★★ otherwise: unconditionally use the embedded per-adapter channel
4006cd40 call DXG_GUEST_VIRTUALGPU_VMBUS::VmBusSendIsFeatureEnabled
...
4006cd47 (NULL branch) call DXG_GUEST_GLOBAL_VMBUS::VmBusSendIsFeatureEnabled
; → VmBusSendIsFeatureEnabled (0x247504) → DXGVMBUSMESSAGE::InitializeMessage
357 fec cmp dword ptr [rbp+30h],0 ; channel type 0
357 ff2 jne ...
358 00a mov rax,qword ptr [rbp+48h] ; rax = [channel+0x48] = 0 ← no NULL check
358 00e mov rax,qword ptr [rax+12C4h] ; ★★ FAULT: read 0x12C4 from NULL
The full function contains no check on: adapter role (ext+0x1E1), channel created (+0x44), channel event (+0x38), or pairing. It equates "an adapter exists" with "this adapter has a usable vGPU channel". The correct behavior is the one Microsoft's own Linux source implements — microsoft/WSL2-Linux-Kernel, drivers/hv/dxgkrnl/dxgvmbus.c (branch linux-msft-wsl-6.6.y):
/* init_message(), line ~105: */
if (adapter)
msg->hdr->vgpu_luid = adapter->host_vgpu_luid;
/* dxgvmb_send_is_feature_enabled(), line 2078: */
if (adapter) {
command_vgpu_to_host_init1(&command->hdr, DXGK_VMBCOMMAND_ISFEATUREENABLED); /* 68 */
} else {
command_vm_to_host_init1(&command->hdr, DXGK_VMBCOMMAND_ISFEATUREENABLED_GLOBAL); /* 1022, dxgvmbus.h */
}
Windows lacks the if (adapter) guard in the message builder, and the caller never falls back to the global channel when the per-adapter channel was never created. Dump memory at crash time (from a kernel dump; ASLR-random addresses omitted): the faulting instruction reads [0 + 0x12C4]; the channel object (adapter+0x1258) has +0x48 == 0; the feature id 0x10000009 and a pointer to the BasicRender adapter appear together on the crashing stack frames.
26H1 vs 26H2 for steps 5–6: identical. The defect functions are instruction-for-instruction the same; the crash-site byte context is byte-identical (48 8b 45 48 | 48 8b 4b 08 | 48 8b 80 c4 12 00 00 | 48 89 41 08, at 0x35083A in 9444 and 0x35800A in 9549). If the same query were issued on 26H1, it would crash the same way. 26H1 survives only because it cannot issue the query.
3. Why "it only started after the update" — the three-part condition, settled
| Condition | Where it lives | Since when | 26H1 (9457) | 26H2 (9550) |
|---|---|---|---|---|
| A. Feature is known to dxgkrnl (OS table has sub-ID 9) | g_FeatureDescriptorTables (both builds {50,10,3,19}) | some update before 9444 (NOT KB5124010) | ✅ present | ✅ present |
| B. A client asks for feature 0x10000009 | d3d12core!CDevice::EnsureDXGKExclusiveEngineAccessSupport | added between 9278 → 9549 | ❌ absent | ✅ present (wil-switch gated) |
| C. The old defective reader | DxgkIsFeatureEnabledVmBus / InitializeMessage | since ≥ 26100.1591 (2024) | ✅ present (dormant) | ✅ present |
Result: 26H1 = A+C only → no crash. 26H2 = A+B+C → crash on every D3D12 device creation inside the sandbox.
Timeline (with sources):
| Date | Event | Source |
|---|---|---|
| 2026-02-06 | SDK 10.0.26100.7705 snapshot: symbol absent | KNSoft/WinSDK-Diff repo |
| 2026-08-05 | SDK 10.0.28000.2526: //DXGK_OS_FEATURE_EXCLUSIVE_ENGINE_ACCESS = 9, appears — commented | KNSoft/WinSDK-Diff |
| 2026-08-27 | SDK 10.0.28000.2705: still commented (cross-checked in a second independent mirror) | KNSoft/WinSDK-Diff; trcrsired/windows-msvc-sysroot (README: Windows Kits 10.0.28000.2705) |
| 2026-09-14 | 26H1 media built (26300.9457): dxgkrnl 9444 already contains OS-table entry #9; d3d12core 9278 does not query it | ISO Windows11_Client_x64_zh-cn_26300_9457.iso |
| 2026-09-22 | KB5124010 released (26300.9550 / 26200.9550 / 26100.9550; SSU KB5124009 = 26100.9539). Highlights list no graphics/sandbox items | support.microsoft.com/help/5124010 |
| 2026-10-02 | SDK 10.0.28000.2957: the line is un-commented — the ONLY snapshot where it is active (all 38 snapshots checked) | KNSoft/WinSDK-Diff commit history |
| 2026-10-14 | Issues #131/#132 still open; no fix in any released LCU | GitHub issue state |
Note the ordering: the OS binaries shipped the feature before the public SDK un-commented it. The SDK un-commenting (2026-10-02) is a policy date, not the enablement date; enablement (step A) predates 26H1's media, and the client-side trigger (step B) arrives with the KB5124010-era d3d12core.
4. What the feature is
0x10000009 decodes as category 1 (DXGK_FEATURE_CATEGORY_OS) × sub-ID 9 (DXGK_DEFINE_FEATURE_ID(1,9)), per the format documented on learn.microsoft.com (category in the upper 4 bits, sub-ID in the lower 28). The public DXGK_FEATURE_ID page currently names only one OS-category feature (DXGK_FEATURE_QUERYSTATISTICS_EXTENSIONS); sub-ID 9 is not named there yet. The name DXGK_OS_FEATURE_EXCLUSIVE_ENGINE_ACCESS = 9 (and the matching DXGK_FEATURE_EXCLUSIVE_ENGINE_ACCESS macro) appears un-commented only in the newest SDK header snapshots (see timeline; e.g. KNSoft/WinSDK-Diff branch 10.0.28000.0, file Include/shared/d3dukmdt.h line 2411/2475), while the 28000.2705-era snapshots ship it commented out. The driver's export surface matches: dxgkrnl.sys exports NtDxgkAcquireExclusiveEngineAccess, NtDxgkCheckEngineAccess, and NtDxgkIsFeatureEnabled in both 9444 and 9549. The requesting symbol name is also consistent: CDevice::EnsureDXGKExclusiveEngineAccessSupport, gated by a wil feature named Feature_D3DVideoEncoderExclusiveAccess.
5. Independent finding: <vGPU>Disable</vGPU> does not stop vGPU provisioning
While collecting the above evidence, one side-finding became provable and is worth an issue of its own, because users try it as a workaround: setting <VGpu>Disable</VGpu> in a .wsb has no effect on the guest receiving a paravirtualized GPU, and it does not avoid this crash.
Evidence chain:
- Same crash with both settings. 4 sessions were captured (3×
<VGpu>Disable</VGpu>, 1× <VGpu>Enable</VGpu>); all crash at the same RVA with the same argument object.
- Host HCS layer: zero difference. In the Hyper-V host compute service operational log (
Microsoft-Windows-Hyper-V-Compute-Operational, event 2007), every sandbox session — Disable or Enable alike — receives exactly one GPU-topology update: {"ResourcePath":"VirtualMachine/ComputeTopology/Gpu","RequestType":"Update","Settings":{"AssignmentMode":"Mirror","AllowVendorExtension":true}} → result 0x0. Positive control: the same log does reflect other .wsb differences — the session with <Networking>Enable</Networking> has a network adapter add/update; the Disable-networking sessions do not. So the log's granularity is sufficient; the <vGPU> setting simply produces no difference at this layer.
- Guest layer: with
<VGpu>Disable</VGpu>, the guest still enumerates the VRD (PCI\VEN_1414&DEV_008E) plus the software display adapter (2 display devices).
- Binary layer (why): in
WindowsSandbox.exe (System32, build from 26H2):
- The
.wsb parser fully supports the element: symbols Marshal::Details::ReadXmlGeneric<enum WindowsSandbox::Config::VGpu>, WindowsSandbox::Config::VGpu_EnumData(_Names) (enum values include Default/Disabled/Enable-style strings).
- The parsed value (field
+0x190 in the Config::Recipe structure) is consumed by exactly three code paths — Recipe::LoadSandboxDefaults (fills default), Recipe::ValidatePolicy (gates on the AllowVGPU policy; if denied, forces the value to Disabled and records the denial), and Recipe::ValidateConfiguration → SandboxConfiguration::EnumerateConfiguration (packs it into an ETW telemetry event — the function builds a _tlgEvent and event-data descriptors).
- A full scan of the binary finds no other reader of that field: all 27 code occurrences of displacement
0x190 were enumerated and symbol-resolved; none of the container/VM creation paths (CreateContainer, CreateStorage, the DisposableVmProvider orchestrator) read it.
⇒ In this build, the <vGPU> value never reaches the code that assembles the VM/container request. The GPU topology (Mirror) is applied unconditionally by the container platform for every sandbox session.
- Documentation context: the sandbox configuration doc says
<vGPU>Disable</vGPU> should make the sandbox "use software rendering" (source); the AllowVGPU policy CSP says the same (source). Default is enabled. The on-disk policy state on the affected host: AllowVGPU not configured (default = allowed; HKLM\SOFTWARE\Microsoft\PolicyManager\default\WindowsSandbox\AllowVGPU). ⇒ Documented intent vs. observed behavior disagree at the device-provisioning level. Whether <vGPU>Disable</vGPU> still influences guest-side rendering choices (as opposed to device presence) was not established and is listed as an open item (§7).
Impact of this finding: <VGpu>Disable</VGpu> cannot be used as a mitigation for the 0x3B crash, and users who set it (including the reporter) are unknowingly running with vGPU still provisioned. Either the implementation should honor it (skip the GPU topology update / use a non-Mirror assignment) or the documentation should say it does not change device provisioning.
| Earlier claim | Corrected | Basis |
|---|---|---|
| "The feature ID is new in KB5124010; OS table 1→10 in this update" (#132 comment) | Wrong timing. OS table is already 10 entries in 26H1's dxgkrnl 9444 ({50,10,3,19} in both 9444 and 9549). The table expansion predates 26H1; KB5124010's contribution is the d3d12core trigger, not the feature table. | Direct read of both PDBs/static tables |
| "DXGADAPTER grew +0x20 in this LCU" (an earlier draft framing) | Wrong attribution. The +0x1238→+0x1258 / +0x12A4→+0x12C4 delta is between 1591-era and 9444-era; 9444 and 9549 are layout-identical. | Byte comparison 9444 vs 9549 |
| "Event 33101 = virtual PCI negotiation failure" | Retracted earlier; confirmed again. Same-launch 33100 says 0x10005 negotiated successfully; 33101 is routine (35+ occurrences across all sessions). | Hyper-V Worker-Admin log |
| "The fix could be to also check created" | Refined. Any capability check works (channel created +0x44, adapter role ext+0x1E1, or pairing state); the cheap correct shape is: if (adapter && channel_created) per-adapter else global. The global-channel branch already exists in the function (9549: 0x6CD47) — only the condition is wrong. | Full disassembly |
7. Suggested fix and a mitigation caveat
- Gate the reader on capability, not existence (dxgkrnl): before using
[adapter+0x1258], verify the channel was created (+0x44) or the adapter is a vGPU role (ext+0x1E1); otherwise fall back to the global channel.
- Make the message builder NULL-safe (
InitializeMessage): adopt the if (adapter) guard from the Linux implementation so no caller can dereference a NULL adapter.
- Consider whether a per-adapter feature query should ever be issued against a software adapter (WARP/BasicRender) — it has no host-side counterpart by design.
- Mitigation caveat (important if you consider a KIR/feature-flag disable): the EEA query is already behind the wil switch
Feature_D3DVideoEncoderExclusiveAccess. If that switch is flipped off as a mitigation, the next queries in the same function (NativeFencesKernelFeatureEnabled → 0x25, then GPUUploadHeapOSSupported → 0x20000000, both unconditional at the call site) will begin to execute. Whether those can reach the same defect depends on their runtime routing (their descriptors differ: 0x4F / 0x13 vs EEA's 0x33). We could not verify their behavior on a live system and recommend evaluating them together with the switch, or fixing the kernel defect outright (preferred).
8. Open items (explicitly not claimed)
- Why the query lands on BasicRender (three candidates: caller enumerates all adapters; the D3D12 device itself sits on WARP; pairing fallback). The adapter is carried by the user request; it is not a kernel list-order artifact.
- Field names/semantics of
[db+0x3B8] / [db+0x3C0] (the routing decision points in IsFeatureEnabledHost). Code paths fully mapped; names not established.
- The wil switch distribution (
Feature_D3DVideoEncoderExclusiveAccess) — server-tiered; why enabled on the affected host is not observable externally.
- Business meaning of EEA beyond its name; the switch name suggests a video-encoder-related exclusivity feature, not verified.
- Whether
<vGPU>Disable</vGPU> still changes guest-side rendering behavior in this build (device provisioning it does not change — see §5).
- Behavior of sibling queries #2/#3 if the EEA switch were disabled (§7.4).
Appendix A — Source for every claim
Public URLs
System files / OS state (all from the affected host)
-
C:\Windows\System32\drivers\dxgkrnl.sys — 10.0.26100.9549 (SHA256 equals the 26H2 ISO copy)
-
C:\Windows\System32\D3D12Core.dll — 10.0.26100.9549 (same check)
- Host compute-service log
Microsoft-Windows-Hyper-V-Compute-Operational, event 2007 (GPU topology updates; per-session sequence)
-
Microsoft-Windows-Hyper-V-Worker-Admin events 33100/33101/33103/33104/33107/33108/18590
-
C:\Windows\System32\WindowsSandbox.exe (parses .wsb; symbols ReadXmlGeneric<Config::VGpu>, Recipe::{LoadSandboxDefaults,ValidatePolicy,ValidateConfiguration}, field Recipe+0x190, policy table {AllowVGPU, AllowNetworking, …})
- Registry:
HKLM\SOFTWARE\Microsoft\PolicyManager\default\WindowsSandbox\AllowVGPU (= default 1, not overridden by policy)
- Guest-side device state:
vrd.inf (DriverStore) PCI\VEN_1414&DEV_008E; guest enumerated 2 display devices
Binary-level (re-verifiable with cdb + Microsoft public PDBs)
- dxgkrnl 9549:
DxgkIsFeatureEnabledVmBus 0x6CCE0; InitializeMessage fault 0x35800A; IsFeatureEnabledUncached 0x432224; IsFeatureEnabledHost 0x43261C; DpiIsFeatureEnabled 0x42876C; DxgkIsFeatureEnabled 0x19C2C8; NtDxgkIsFeatureEnabled 0x42A2C0; descriptor tables base RVA 0xACD10 (OS table 0x13D350)
- dxgkrnl 9444: same functions at shifted RVAs (e.g.
DxgkIsFeatureEnabledVmBus 0x6CE24; fault site 0x35083A), instruction sequences byte-identical; descriptor tables base 0xABCF0 (OS table 0x13C1A0)
- d3d12core 9549:
CDevice::EnsureDXGKExclusiveEngineAccessSupport 0xD0504; call site LLOCompleteLayerConstruction+0x108a; immediate at 0xD0565. 9278: symbol absent; immediate absent.
- Crash stack (9549):
NtDxgkIsFeatureEnabled+0x33a ← DpiIsFeatureEnabled+0x5e ← DxgkIsFeatureEnabled+0x4c ← IsFeatureEnabledUncached+0x1ec ← IsFeatureEnabledHost+0xb8 ← DxgkIsFeatureEnabledVmBus+0x65 ← VmBusSendIsFeatureEnabled+0x5b ← InitializeMessage+0xde
- Dumps: enable guest kernel dumps or use the hidden sandbox dump-drop folder on the host (
C:\ProgramData\Microsoft\Windows\Containers\Dumps — the VM teardown deletes them, so copy while non-zero). Open with cdb/WinDbg; Microsoft public symbols load automatically.
- Binaries from media: mount either ISO, extract from
sources\install.wim (e.g. 7-Zip: 7z e install.wim "Windows\System32\drivers\dxgkrnl.sys") — PDBs from the Microsoft symbol server are available for both builds.
- Key commands (cdb):
uf dxgkrnl!DxgkIsFeatureEnabledVmBus, u dxgkrnl!DXGVMBUSMESSAGE::InitializeMessage+0xc0, dq dxgkrnl!g_FeatureDescriptorTables L8, x D3D12Core!CDevice::*, dt/u on WindowsSandbox!Sandbox::Server::Config::Recipe::*.
- HCS evidence:
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Hyper-V-Compute-Operational'; Id=2007} and filter for ComputeTopology/Gpu.
No WDK, driver development kit, or custom kernel debugging setup is required for any step above; the kernel debugging environment was not needed for the conclusions in this report.