Skip to content

fix: check the two return values Code Analysis flags - #519

Closed
danalec wants to merge 1 commit into
VirtualDrivers:masterfrom
danalec:fix/code-analysis-errors
Closed

danalec wants to merge 1 commit into
VirtualDrivers:masterfrom
danalec:fix/code-analysis-errors

Conversation

@danalec

@danalec danalec commented Oct 17, 2026 •

Copy link
Copy Markdown

Summary

Two unchecked return values, both flagged by Code Analysis. On MSVC 18 these
stop the build; on the currently pinned CI toolset they do not surface at all,
so they have gone unnoticed. Neither is cosmetic.

1. AvRevertMmThreadCharacteristics receives a handle that may be NULL

AvSetMmThreadCharacteristicsW returns NULL on failure, and that NULL was
passed straight into AvRevertMmThreadCharacteristics, which does not accept
it:

Driver.cpp(3251): warning C28183: 'AvTaskHandle' could be '0', and is a copy of
the value found in 'AvSetMmThreadCharacteristicsW'()... this does not adhere to
the specification for the function 'AvRevertMmThreadCharacteristics'
Driver.cpp(3263): error C2220: the following warning is treated as an error

The revert now happens only when the handle is valid, with a log line for the
other case. When the characteristics were never set there is nothing to revert,
so the new branch is a log and no call.

2. CoCreateGuid failure is discarded

Driver.cpp(3835): warning C6031: Return value ignored: 'CoCreateGuid'
Driver.cpp(3874): error C2220: the following warning is treated as an error

MonitorInfo is zero-initialised, so a failed CoCreateGuid leaves
MonitorContainerId as GUID_NULL, which is then handed to
IddCxMonitorCreate as if it were a valid container ID. The result is now
checked; on failure the driver logs and skips creating that monitor rather than
registering it under GUID_NULL.

Verification

Built Debug and Release on x64 and ARM64 — four configurations, each producing
MttVDD.dll, MttVDD.inf and a signed mttvdd.cat, with TreatWarningAsError
on.

I found this by building a clean origin/master and finding it does not
compile on a newer toolset. Worth noting how it presents: the first C2220
aborts the compile before the next warning is emitted, so silencing C28183
does not produce a green build — it only moves the error to the next line. Both
had to be fixed to see whether anything else was behind them.

Not verified on hardware. No install, no monitor, no HDR toggle — this was a
build fix, and the change in behaviour is confined to two error paths that
previously did not exist.

If the two warnings do not appear on your CI toolset, that is expected — the
underlying defects are the same either way, and both are one-line guards.

Two unchecked return values. On MSVC 18 both stop the build; on the pinned CI
toolset neither surfaces. Neither defect is cosmetic.

AvSetMmThreadCharacteristicsW returns NULL on failure, and that NULL went
straight into AvRevertMmThreadCharacteristics, which does not accept it.
Reported as C28183 and promoted to C2220 by TreatWarningAsError. The revert now
happens only when the handle is valid; when the characteristics were never set
there is nothing to revert, so that branch is a log and no call.

CoCreateGuid had its HRESULT discarded (C6031 -> C2220). MonitorInfo is
zero-initialised, so a failure left MonitorContainerId as GUID_NULL, which was
then handed to IddCxMonitorCreate as if it were valid. The result is now
checked, and on failure the driver logs and skips creating that monitor rather
than registering it under GUID_NULL.

Note how this presents: the first C2220 aborts the compile before the next
warning is emitted, so silencing C28183 does not give a green build, it only
moves the error to the next line. Both had to be fixed to find out whether
anything was behind them.

Verified: Debug and Release on x64 and ARM64, 0 errors, all four producing
MttVDD.dll, MttVDD.inf and a signed mttvdd.cat.
@danalec
danalec marked this pull request as ready for review October 17, 2026 02:26
danalec added a commit to danalec/Virtual-Display-Driver that referenced this pull request Oct 20, 2026
…nging

Two defects, both on paths that only fail under a race or under a rare
condition, which is why they survived review.

CoCreateGuid had its HRESULT discarded. MonitorInfo is zero-initialised, so a
failed CoCreateGuid left MonitorContainerId as GUID_NULL, and that was then
handed to IddCxMonitorCreate as if it were a valid container ID. The result is
checked now, and on failure the driver logs and does not create that monitor.

The frame loop's wait list is built conditionally: the buffer event goes in
only when it is neither null nor INVALID_HANDLE_VALUE, and the terminate event
only when its handle exists. The terminate event therefore has no fixed index.
Testing WAIT_OBJECT_0 for "buffer available" first meant that a signalled
terminate event at index 0 took the continue branch, and the thread re-entered
IddCxSwapChainReleaseAndAcquireBuffer forever -- a hang in EvtDriverUnload.
The wait result is decided by handle identity now.

The invariant is that the loop exits in finitely many steps, not that it exits
on the first wait. With both handles signalled, WaitForMultipleObjects returns
the lower index, which is the buffer; the acquire resets that event, and the
next wait returns terminate.

Also here: the hardware cursor event is now closed by the driver. IddCx signals
it but does not own it, and the driver used to leak the previous one on
reassignment for the same monitor and the last one on unassign. s_KnownMonitorEdid
is read under a lock now, because maincalc() reassigns it on another thread
while CreateMonitor reads it. The EDID base block is 128 bytes and
calculateChecksum() reads it unconditionally, so a short EDID was read past
the end. AssignSwapChain can run on more than one thread, so its counter is
atomic. And the device is validated before it is dereferenced: the check used
to sit below the As() call, so a null m_Device was already dereferenced by the
time it ran.

Verified: Debug and Release on x64 and ARM64, 0 errors, all four producing
MttVDD.dll, MttVDD.inf and a signed mttvdd.cat.

Note: the two fixes that make the current master compile on a newer toolset
(AvTaskHandle and CoCreateGuid) are in VirtualDrivers#519 and are not repeated here.
@danalec

danalec commented Oct 20, 2026

Copy link
Copy Markdown
Author

Closing this without merging.

The work is real and it is verified -- every branch builds clean in Debug and
Release on x64 and ARM64 -- but the review surface turned out to be larger
than this series can reasonably ask of a maintainer, and the individual
pieces were not going to be picked up one by one either.

The code stays available on the fork, split into reviewable pieces:

fix/code-analysis-errors 1 file +14/-2
fix/driver-1-concurrency 2 files +134/-36
fix/driver-2-settings 1 file +257/-188
fix/driver-3-defaults 1 file +103/-69
fix/driver-4-metadata 1 file +85/-12
fix/driver-5-modes 1 file +192/-63
fix/driver-6-log-xml 1 file +223/-51
fix/driver-7-monitor 2 files +134/-36
fix/driver-8-callbacks 1 file +120/-89
fix/driver-9-validation 1 file +117/-40
fix/driver-10-pipe 1 file +242/-62
fix/driver-11-build 5 files +6/-214
fix/driver-12-config-docs 4 files +261/-98

If any of it is ever wanted, the branches are there and this PR can be
reopened.

@danalec danalec closed this Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant