mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
Compare commits
2 Commits
release-1.
...
dev/lhecke
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7131daa4d | ||
|
|
65f0200842 |
1
.github/actions/spelling/README.md
vendored
1
.github/actions/spelling/README.md
vendored
@@ -6,6 +6,7 @@ File | Purpose | Format | Info
|
||||
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
|
||||
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
|
||||
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
|
||||
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
|
||||
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
|
||||
|
||||
2
.github/actions/spelling/advice.md
vendored
2
.github/actions/spelling/advice.md
vendored
@@ -21,7 +21,7 @@ See the `README.md` in each directory for more information.
|
||||
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
|
||||
|
||||
|
||||
<details><summary>:clamp: If the flagged items are false positives</summary>
|
||||
<details><summary>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
12
.github/actions/spelling/allow/allow.txt
vendored
12
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,7 +1,7 @@
|
||||
admins
|
||||
allcolors
|
||||
apc
|
||||
Apc
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
@@ -14,8 +14,8 @@ CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
dcs
|
||||
dialytika
|
||||
dje
|
||||
downside
|
||||
@@ -34,10 +34,12 @@ gantt
|
||||
gcc
|
||||
geeksforgeeks
|
||||
ghe
|
||||
github
|
||||
gje
|
||||
godbolt
|
||||
hostname
|
||||
hostnames
|
||||
https
|
||||
hyperlink
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
@@ -54,9 +56,11 @@ Llast
|
||||
llvm
|
||||
Lmid
|
||||
locl
|
||||
lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
@@ -80,6 +84,7 @@ runtimes
|
||||
shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
@@ -88,6 +93,7 @@ tokenizes
|
||||
tonos
|
||||
toolset
|
||||
tshe
|
||||
ubuntu
|
||||
uiatextrange
|
||||
UIs
|
||||
und
|
||||
@@ -96,5 +102,7 @@ versioned
|
||||
vsdevcmd
|
||||
We'd
|
||||
wildcards
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
|
||||
12
.github/actions/spelling/allow/apis.txt
vendored
12
.github/actions/spelling/allow/apis.txt
vendored
@@ -32,10 +32,10 @@ DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
@@ -92,6 +92,7 @@ istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
@@ -103,13 +104,14 @@ lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUITEMINFOW
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
@@ -146,6 +148,7 @@ OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
@@ -155,8 +158,8 @@ rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
@@ -208,6 +211,7 @@ UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
winmain
|
||||
|
||||
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker for ignoring a comment to the end of the line
|
||||
// #no-spell-check.*$
|
||||
|
||||
# patch hunk comments
|
||||
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||
# git index header
|
||||
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
# cid urls
|
||||
(['"])cid:.*?\g{-1}
|
||||
|
||||
# data url in parens
|
||||
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
|
||||
# data url in quotes
|
||||
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
# data url
|
||||
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# magnet urls
|
||||
magnet:[?=:\w]+
|
||||
|
||||
# magnet urls
|
||||
"magnet:[^"]+"
|
||||
|
||||
# obs:
|
||||
"obs:[^"]*"
|
||||
|
||||
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
|
||||
# In this examples content, I'm using a number of different ways to match things to show various approaches
|
||||
# asciinema
|
||||
\basciinema\.org/a/[0-9a-zA-Z]+
|
||||
|
||||
# apple
|
||||
\bdeveloper\.apple\.com/[-\w?=/]+
|
||||
# Apple music
|
||||
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
|
||||
|
||||
# appveyor api
|
||||
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
|
||||
# appveyor project
|
||||
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
|
||||
|
||||
# Amazon
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
# AWS S3
|
||||
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS execute-api
|
||||
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
|
||||
# AWS ELB
|
||||
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
|
||||
# AWS SNS
|
||||
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS VPC
|
||||
vpc-\w+
|
||||
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
# YouTube music
|
||||
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
|
||||
# YouTube tag
|
||||
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
|
||||
# YouTube image
|
||||
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
|
||||
# Google Accounts
|
||||
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
|
||||
# Google Analytics
|
||||
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||
# Google APIs
|
||||
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||
# Google Storage
|
||||
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||
# Google Calendar
|
||||
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
|
||||
\w+\@group\.calendar\.google\.com\b
|
||||
# Google DataStudio
|
||||
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
|
||||
# The leading `/` here is as opposed to the `\b` above
|
||||
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
|
||||
# Google Docs
|
||||
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
|
||||
# Google Drive
|
||||
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
|
||||
# Google Groups
|
||||
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
|
||||
# Google Maps
|
||||
\bmaps\.google\.com/maps\?[\w&;=]*
|
||||
# Google themes
|
||||
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
# Google CDN
|
||||
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
|
||||
# Goo.gl
|
||||
/goo\.gl/[a-zA-Z0-9]+
|
||||
# Google Chrome Store
|
||||
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
|
||||
# Google Books
|
||||
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
|
||||
# Google Fonts
|
||||
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
|
||||
# Google Forms
|
||||
\bforms\.gle/\w+
|
||||
# Google Scholar
|
||||
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||
# Google Colab Research Drive
|
||||
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||
|
||||
# GitHub SHAs (api)
|
||||
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
# GitHub SHAs
|
||||
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
|
||||
# GitHub wiki
|
||||
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
# githubassets
|
||||
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
|
||||
# gist github
|
||||
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
|
||||
# git.io
|
||||
\bgit\.io/[0-9a-zA-Z]+
|
||||
# GitHub JSON
|
||||
"node_id": "[-a-zA-Z=;:/0-9+]*"
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
# GitLab merge requests
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
|
||||
# GitLab uploads
|
||||
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
|
||||
# GitLab commits
|
||||
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||
|
||||
# binanace
|
||||
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
|
||||
# bitbucket diff
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
|
||||
# bitbucket repositories commits
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
# bitbucket commits
|
||||
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
|
||||
# bit.ly
|
||||
\bbit\.ly/\w+
|
||||
|
||||
# bitrise
|
||||
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
|
||||
|
||||
# bootstrapcdn.com
|
||||
\bbootstrapcdn\.com/[-./\w]+
|
||||
|
||||
# cdn.cloudflare.com
|
||||
\bcdnjs\.cloudflare\.com/[./\w]+
|
||||
|
||||
# circleci
|
||||
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
|
||||
|
||||
# gitter
|
||||
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
|
||||
|
||||
# gravatar
|
||||
\bgravatar\.com/avatar/[0-9a-f]+
|
||||
|
||||
# ibm
|
||||
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
|
||||
|
||||
# imgur
|
||||
\bimgur\.com/[^.]+
|
||||
|
||||
# Internet Archive
|
||||
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
|
||||
|
||||
# discord
|
||||
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
|
||||
|
||||
# Disqus
|
||||
\bdisqus\.com/[-\w/%.()!?&=_]*
|
||||
|
||||
# medium link
|
||||
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
# microsoft store
|
||||
\bmicrosoft\.com/store/apps/\w+
|
||||
|
||||
# mvnrepository.com
|
||||
\bmvnrepository\.com/[-0-9a-z./]+
|
||||
|
||||
# now.sh
|
||||
/[0-9a-z-.]+\.now\.sh\b
|
||||
|
||||
# oracle
|
||||
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
|
||||
|
||||
# chromatic.com
|
||||
/\S+.chromatic.com\S*[")]
|
||||
|
||||
# codacy
|
||||
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
|
||||
|
||||
# compai
|
||||
\bcompai\.pub/v1/png/[0-9a-f]+
|
||||
|
||||
# mailgun api
|
||||
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
|
||||
# mailgun
|
||||
\b[0-9a-z]+.mailgun.org
|
||||
|
||||
# /message-id/
|
||||
/message-id/[-\w@./%]+
|
||||
|
||||
# Reddit
|
||||
\breddit\.com/r/[/\w_]*
|
||||
|
||||
# requestb.in
|
||||
\brequestb\.in/[0-9a-z]+
|
||||
|
||||
# sched
|
||||
\b[a-z0-9]+\.sched\.com\b
|
||||
|
||||
# Slack url
|
||||
slack://[a-zA-Z0-9?&=]+
|
||||
# Slack
|
||||
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
|
||||
# Slack edge
|
||||
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
|
||||
# Slack images
|
||||
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
|
||||
|
||||
# shields.io
|
||||
\bshields\.io/[-\w/%?=&.:+;,]*
|
||||
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# Sentry
|
||||
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||
|
||||
# Twitter markdown
|
||||
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
# Twitter hashtag
|
||||
\btwitter\.com/hashtag/[\w?_=&]*
|
||||
# Twitter status
|
||||
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
|
||||
# Twitter profile images
|
||||
\btwimg\.com/profile_images/[_\w./]*
|
||||
# Twitter media
|
||||
\btwimg\.com/media/[-_\w./?=]*
|
||||
# Twitter link shortened
|
||||
\bt\.co/\w+
|
||||
|
||||
# facebook
|
||||
\bfburl\.com/[0-9a-z_]+
|
||||
# facebook CDN
|
||||
\bfbcdn\.net/[\w/.,]*
|
||||
# facebook watch
|
||||
\bfb\.watch/[0-9A-Za-z]+
|
||||
|
||||
# dropbox
|
||||
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
|
||||
|
||||
# ipfs protocol
|
||||
ipfs://[0-9a-z]*
|
||||
# ipfs url
|
||||
/ipfs/[0-9a-z]*
|
||||
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# loom
|
||||
\bloom\.com/embed/[0-9a-f]+
|
||||
|
||||
# regex101
|
||||
\bregex101\.com/r/[^/\s"]+/\d+
|
||||
|
||||
# figma
|
||||
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
|
||||
|
||||
# freecodecamp.org
|
||||
\bfreecodecamp\.org/[-\w/.]+
|
||||
|
||||
# image.tmdb.org
|
||||
\bimage\.tmdb\.org/[/\w.]+
|
||||
|
||||
# mermaid
|
||||
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
|
||||
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# gitweb
|
||||
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||
|
||||
# HyperKitty lists
|
||||
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||
|
||||
# lists
|
||||
/thread\.html/[^"\s]+
|
||||
|
||||
# list-management
|
||||
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
|
||||
|
||||
# kubectl.kubernetes.io/last-applied-configuration
|
||||
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||
|
||||
# pgp
|
||||
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
|
||||
|
||||
# Spotify
|
||||
\bopen\.spotify\.com/embed/playlist/\w+
|
||||
|
||||
# Mastodon
|
||||
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||
|
||||
# scastie
|
||||
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||
|
||||
# images.unsplash.com
|
||||
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
|
||||
|
||||
# pastebin
|
||||
\bpastebin\.com/[\w/]+
|
||||
|
||||
# heroku
|
||||
\b\w+\.heroku\.com/source/archive/\w+
|
||||
|
||||
# quip
|
||||
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
|
||||
|
||||
# badgen.net
|
||||
\bbadgen\.net/badge/[^")\]'\s]+
|
||||
|
||||
# statuspage.io
|
||||
\w+\.statuspage\.io\b
|
||||
|
||||
# media.giphy.com
|
||||
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
|
||||
|
||||
# tinyurl
|
||||
\btinyurl\.com/\w+
|
||||
|
||||
# getopts
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
# IPv6
|
||||
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||
# c99 hex digits (not the full format, just one I've seen)
|
||||
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
# sha
|
||||
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
# hex in url queries
|
||||
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||
# ssh
|
||||
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
|
||||
|
||||
# PGP
|
||||
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
|
||||
# GPG keys
|
||||
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
|
||||
# Well known gpg keys
|
||||
.well-known/openpgpkey/[\w./]+
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
# integrity
|
||||
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
|
||||
|
||||
# https://www.gnu.org/software/groff/manual/groff.html
|
||||
# man troff content
|
||||
\\f[BCIPR]
|
||||
# '
|
||||
\\\(aq
|
||||
|
||||
# .desktop mime types
|
||||
^MimeTypes?=.*$
|
||||
# .desktop localized entries
|
||||
^[A-Z][a-z]+\[[a-z]+\]=.*$
|
||||
# Localized .desktop content
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# crypt
|
||||
"\$2[ayb]\$.{56}"
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# Input to GitHub JSON
|
||||
content: "[-a-zA-Z=;:/0-9+]*="
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.*/[gim]*\.test\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]*/[gim]*\s*
|
||||
# javascript match regex
|
||||
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||
# javascript regex
|
||||
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
|
||||
# sed regular expressions
|
||||
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||
|
||||
# go install
|
||||
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
|
||||
# kubectl - pods in CrashLoopBackOff
|
||||
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||
|
||||
# kubernetes object suffix
|
||||
-[0-9a-f]{10}-\w{5}\s
|
||||
|
||||
# posthog secrets
|
||||
posthog\.init\((['"])phc_[^"',]+\g{-1},
|
||||
|
||||
# xcode
|
||||
|
||||
# xcodeproject scenes
|
||||
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
|
||||
# font awesome classes
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
# Lorem
|
||||
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
# Note that the next example is no longer necessary if you are using
|
||||
# to match a string starting with a `#`, use a character-class:
|
||||
[#]backwards
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
# Compiler flags (Scala)
|
||||
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
# Compiler flags
|
||||
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||
38
.github/actions/spelling/excludes.txt
vendored
38
.github/actions/spelling/excludes.txt
vendored
@@ -2,14 +2,14 @@
|
||||
(?:(?i)\.png$)
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)dirs$
|
||||
(?:^|/)go\.mod$
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)sources(?:|\.dep)$
|
||||
(?:^|/)vendor/
|
||||
ignore$
|
||||
SUMS$
|
||||
\.a$
|
||||
\.ai$
|
||||
\.avi$
|
||||
\.bmp$
|
||||
@@ -20,6 +20,8 @@ SUMS$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
\.drawio$
|
||||
\.DS_Store$
|
||||
\.eot$
|
||||
\.eps$
|
||||
@@ -31,6 +33,7 @@ SUMS$
|
||||
\.icns$
|
||||
\.ico$
|
||||
\.jar$
|
||||
\.jks$
|
||||
\.jpeg$
|
||||
\.jpg$
|
||||
\.key$
|
||||
@@ -41,6 +44,7 @@ SUMS$
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
@@ -48,22 +52,41 @@ SUMS$
|
||||
\.pem$
|
||||
\.png$
|
||||
\.psd$
|
||||
\.pyc$
|
||||
\.runsettings$
|
||||
\.s$
|
||||
\.sig$
|
||||
\.so$
|
||||
\.svg$
|
||||
\.svgz$
|
||||
\.svgz?$
|
||||
\.tar$
|
||||
\.tgz$
|
||||
\.tiff?$
|
||||
\.ttf$
|
||||
\.vsdx$
|
||||
\.wav$
|
||||
\.webm$
|
||||
\.webp$
|
||||
\.woff
|
||||
\.woff2?$
|
||||
\.xcf$
|
||||
\.xls
|
||||
\.xlsx?$
|
||||
\.xpm$
|
||||
\.yml$
|
||||
\.zip$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.git-blame-ignore-revs\E$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
^build/config/
|
||||
^consolegit2gitfilters\.json$
|
||||
^dep/
|
||||
@@ -90,12 +113,5 @@ SUMS$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
7
.github/actions/spelling/expect/alphabet.txt
vendored
7
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
ABCDEFG
|
||||
ABCDEFGH
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBBBBBBBBBBDDDD
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
CCE
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
|
||||
717
.github/actions/spelling/expect/expect.txt
vendored
717
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
2
.github/actions/spelling/expect/web.txt
vendored
2
.github/actions/spelling/expect/web.txt
vendored
@@ -1,5 +1,3 @@
|
||||
http
|
||||
www
|
||||
WCAG
|
||||
winui
|
||||
appshellintegration
|
||||
|
||||
30
.github/actions/spelling/line_forbidden.patterns
vendored
30
.github/actions/spelling/line_forbidden.patterns
vendored
@@ -1,3 +1,11 @@
|
||||
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
|
||||
# \bm_data\b
|
||||
|
||||
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||
# to use this:
|
||||
#\bfit\(
|
||||
|
||||
# s.b. GitHub
|
||||
\bGithub\b
|
||||
|
||||
@@ -16,6 +24,12 @@
|
||||
# s.b. greater than
|
||||
\bgreater then\b
|
||||
|
||||
# s.b. into
|
||||
#\sin to\s
|
||||
|
||||
# s.b. opt-in
|
||||
\sopt in\s
|
||||
|
||||
# s.b. less than
|
||||
\bless then\b
|
||||
|
||||
@@ -27,10 +41,22 @@
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. preexisting
|
||||
[Pp]re-existing
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
[Pp]re-emptively
|
||||
[Pp]re[- ]emptively
|
||||
|
||||
# s.b. reentrancy
|
||||
[Rr]e[- ]entrancy
|
||||
|
||||
# s.b. reentrant
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# s.b. workaround(s)
|
||||
#\bwork[- ]arounds?\b
|
||||
|
||||
# Reject duplicate words
|
||||
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||
|
||||
57
.github/actions/spelling/patterns/patterns.txt
vendored
57
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -27,13 +27,68 @@ ROY\sG\.\sBIV
|
||||
# Python stringprefix / binaryprefix
|
||||
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3831 file-count: 582
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# hit-count: 71 file-count: 35
|
||||
# Compiler flags
|
||||
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
|
||||
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 41 file-count: 28
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 20 file-count: 9
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 10 file-count: 7
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
|
||||
# C/idl types + English ...
|
||||
\s(Guid|long|LONG|that) \g{-1}\s
|
||||
|
||||
# javadoc / .net
|
||||
(?:\@(?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# Commit message -- Signed-off-by and friends
|
||||
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
|
||||
|
||||
# Autogenerated revert commit message
|
||||
^This reverts commit [0-9a-f]{40}\.$
|
||||
|
||||
# vtmode
|
||||
--vtmode\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
|
||||
27
.github/actions/spelling/reject.txt
vendored
27
.github/actions/spelling/reject.txt
vendored
@@ -1,31 +1,12 @@
|
||||
benefitting
|
||||
occurences?
|
||||
Sorce
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
^spae$
|
||||
^spae-man$
|
||||
^spaebook$
|
||||
^spaecraft$
|
||||
^spaed$
|
||||
^spaedom$
|
||||
^spaeing$
|
||||
^spaeings$
|
||||
^spaeman$
|
||||
^spaer$
|
||||
^Spaerobee$
|
||||
^spaes$
|
||||
^spaewife$
|
||||
^spaewoman$
|
||||
^spaework$
|
||||
^spaewright$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether$
|
||||
^wether.*
|
||||
^wethers$
|
||||
^wetherteg$
|
||||
^[Ss]pae.*
|
||||
|
||||
106
.github/workflows/spelling2.yml
vendored
106
.github/workflows/spelling2.yml
vendored
@@ -1,10 +1,57 @@
|
||||
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
|
||||
name: Spell checking
|
||||
|
||||
# Comment management is handled through a secondary job, for details see:
|
||||
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
|
||||
#
|
||||
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
|
||||
# it needs `contents: write` in order to add a comment.
|
||||
#
|
||||
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
|
||||
# it needs `pull-requests: write` in order to manipulate those comments.
|
||||
|
||||
# Updating pull request branches is managed via comment handling.
|
||||
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
|
||||
#
|
||||
# These elements work together to make it happen:
|
||||
#
|
||||
# `on.issue_comment`
|
||||
# This event listens to comments by users asking to update the metadata.
|
||||
#
|
||||
# `jobs.update`
|
||||
# This job runs in response to an issue_comment and will push a new commit
|
||||
# to update the spelling metadata.
|
||||
#
|
||||
# `with.experimental_apply_changes_via_bot`
|
||||
# Tells the action to support and generate messages that enable it
|
||||
# to make a commit to update the spelling metadata.
|
||||
#
|
||||
# `with.ssh_key`
|
||||
# In order to trigger workflows when the commit is made, you can provide a
|
||||
# secret (typically, a write-enabled github deploy key).
|
||||
#
|
||||
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
branches: ["**"]
|
||||
tags-ignore: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
@@ -24,23 +71,64 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.20
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
suppress_push_for_open_pull_request: 1
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
extra_dictionary_limit: 10
|
||||
extra_dictionaries:
|
||||
cspell:software-terms/src/software-terms.txt
|
||||
cspell:python/src/python/python-lib.txt
|
||||
cspell:node/node.txt
|
||||
cspell:cpp/src/stdlib-c.txt
|
||||
cspell:cpp/src/stdlib-cpp.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/src/compiler-msvc.txt
|
||||
cspell:python/src/common/extra.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:cpp/src/lang-keywords.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:python/src/python/python.txt
|
||||
cspell:css/css.txt
|
||||
cspell:cpp/src/stdlib-cmath.txt
|
||||
check_extra_dictionaries: ''
|
||||
|
||||
comment:
|
||||
name: Report
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
# If your workflow isn't running on push, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name != 'push'
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.20
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
# If you workflow isn't running on pull_request*, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
@@ -174,8 +174,7 @@ public:
|
||||
const TextBuffer& GetTextBuffer() const noexcept override;
|
||||
const FontInfo& GetFontInfo() const noexcept override;
|
||||
|
||||
void LockConsole() noexcept override;
|
||||
void UnlockConsole() noexcept override;
|
||||
[[nodiscard]] std::unique_lock<til::ticket_lock> LockConsole() noexcept override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IRenderData
|
||||
|
||||
@@ -203,23 +203,17 @@ catch (...)
|
||||
// - Lock the terminal for reading the contents of the buffer. Ensures that the
|
||||
// contents of the terminal won't be changed in the middle of a paint
|
||||
// operation.
|
||||
// Callers should make sure to also call Terminal::UnlockConsole once
|
||||
// they're done with any querying they need to do.
|
||||
void Terminal::LockConsole() noexcept
|
||||
std::unique_lock<til::ticket_lock> Terminal::LockConsole() noexcept
|
||||
{
|
||||
_readWriteLock.lock();
|
||||
#ifndef NDEBUG
|
||||
#ifdef NDEBUG
|
||||
return std::unique_lock{ _readWriteLock };
|
||||
#else
|
||||
auto lock = std::unique_lock{ _readWriteLock };
|
||||
_lastLocker = GetCurrentThreadId();
|
||||
return lock;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Unlocks the terminal after a call to Terminal::LockConsole.
|
||||
void Terminal::UnlockConsole() noexcept
|
||||
{
|
||||
_readWriteLock.unlock();
|
||||
}
|
||||
|
||||
const bool Terminal::IsUiaDataInitialized() const noexcept
|
||||
{
|
||||
// GH#11135: Windows Terminal needs to create and return an automation peer
|
||||
|
||||
@@ -1912,8 +1912,7 @@ void ConptyRoundtripTests::ClearHostTrickeryTest()
|
||||
// We're _not_ checking the conpty output during this test, only the side effects.
|
||||
_checkConptyOutput = false;
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
Log::Comment(L"Setting up the host buffer...");
|
||||
hostSm.ProcessString(L"AAAAA");
|
||||
@@ -2404,8 +2403,7 @@ void ConptyRoundtripTests::BreakLinesOnCursorMovement()
|
||||
_checkConptyOutput = false;
|
||||
|
||||
// Lock must be taken to manipulate alt/main buffer state.
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
// Use DECALN to fill the buffer with 'E's.
|
||||
hostSm.ProcessString(L"\x1b#8");
|
||||
@@ -3895,8 +3893,7 @@ void ConptyRoundtripTests::SimpleAltBufferTest()
|
||||
|
||||
Log::Comment(L"========== Switch to the alt buffer ==========");
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
sm.ProcessString(L"\x1b[?1049h");
|
||||
// Don't leave ourselves in the alt buffer - that'll pollute other tests.
|
||||
auto leaveAltBuffer = wil::scope_exit([&] { sm.ProcessString(L"\x1b[?1049l"); });
|
||||
@@ -4056,8 +4053,7 @@ void ConptyRoundtripTests::AltBufferToAltBufferTest()
|
||||
|
||||
Log::Comment(L"========== Switch to the alt buffer ==========");
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
sm.ProcessString(L"\x1b[?1049h");
|
||||
// Don't leave ourselves in the alt buffer - that'll pollute other tests.
|
||||
auto leaveAltBuffer = wil::scope_exit([&] { sm.ProcessString(L"\x1b[?1049l"); });
|
||||
@@ -4120,8 +4116,7 @@ void ConptyRoundtripTests::AltBufferResizeCrash()
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& sm = si.GetStateMachine();
|
||||
|
||||
gci.LockConsole(); // Lock must be taken to manipulate alt/main buffer state.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
_flushFirstFrame();
|
||||
|
||||
|
||||
@@ -19,9 +19,8 @@ static void CALLBACK CursorTimerRoutineWrapper(_Inout_ PTP_CALLBACK_INSTANCE /*I
|
||||
// But I'm not too concerned that this will lead to issues at the time of writing,
|
||||
// as CursorBlinker is allocated as a static variable through the Globals class.
|
||||
// It'd be nice to fix this, but realistically it'll likely not lead to issues.
|
||||
gci.LockConsole();
|
||||
const auto guard = gci.LockConsole();
|
||||
gci.GetCursorBlinker().TimerRoutine(gci.GetActiveOutputBuffer());
|
||||
gci.UnlockConsole();
|
||||
}
|
||||
|
||||
CursorBlinker::CursorBlinker() :
|
||||
|
||||
@@ -108,8 +108,7 @@ void PtySignalInputThread::CreatePseudoWindow()
|
||||
ShowHideData msg = { 0 };
|
||||
_GetData(&msg, sizeof(msg));
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If the client app hasn't yet connected, stash our initial
|
||||
// visibility for when we do. We default to not being visible - if a
|
||||
@@ -132,8 +131,7 @@ void PtySignalInputThread::CreatePseudoWindow()
|
||||
}
|
||||
case PtySignal::ClearBuffer:
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If the client app hasn't yet connected, stash the new size in the launchArgs.
|
||||
// We'll later use the value in launchArgs to set up the console buffer
|
||||
@@ -150,8 +148,7 @@ void PtySignalInputThread::CreatePseudoWindow()
|
||||
ResizeWindowData resizeMsg = { 0 };
|
||||
_GetData(&resizeMsg, sizeof(resizeMsg));
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If the client app hasn't yet connected, stash the new size in the launchArgs.
|
||||
// We'll later use the value in launchArgs to set up the console buffer
|
||||
@@ -173,8 +170,7 @@ void PtySignalInputThread::CreatePseudoWindow()
|
||||
SetParentData reparentMessage = { 0 };
|
||||
_GetData(&reparentMessage, sizeof(reparentMessage));
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If the client app hasn't yet connected, stash the new owner.
|
||||
// We'll later (PtySignalInputThread::ConnectConsole) use the value
|
||||
|
||||
@@ -66,8 +66,7 @@ VtInputThread::VtInputThread(_In_ wil::unique_hfile hPipe,
|
||||
// gci's unlock, when you press C-c, it won't be dispatched until the
|
||||
// next console API call. For something like `powershell sleep 60`,
|
||||
// that won't happen for 60s
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -81,8 +81,7 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenInfo = OutContext.GetActiveBuffer();
|
||||
const auto bufferSize = screenInfo.GetBufferSize();
|
||||
@@ -121,8 +120,7 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenInfo = OutContext.GetActiveBuffer();
|
||||
const auto bufferSize = screenInfo.GetBufferSize();
|
||||
@@ -206,8 +204,7 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenBuffer = OutContext.GetActiveBuffer();
|
||||
const auto bufferSize = screenBuffer.GetBufferSize();
|
||||
@@ -266,8 +263,7 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// TODO: does this even need to be here or will it exit quickly?
|
||||
auto& screenInfo = OutContext.GetActiveBuffer();
|
||||
|
||||
@@ -1137,8 +1137,7 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto unlock{ wil::scope_exit([&] { UnlockConsole(); }) };
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenInfo{ context.GetActiveBuffer() };
|
||||
const auto& consoleInfo{ ServiceLocator::LocateGlobals().getConsoleInformation() };
|
||||
@@ -1318,8 +1317,7 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
std::unique_ptr<WriteData> writeDataWaiter;
|
||||
RETURN_IF_FAILED(WriteConsoleWImplHelper(context.GetActiveBuffer(), buffer, read, requiresVtQuirk, writeDataWaiter));
|
||||
|
||||
@@ -88,8 +88,7 @@ std::unordered_map<std::wstring,
|
||||
const std::wstring_view target,
|
||||
const std::wstring_view exeName) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, source.size() == 0);
|
||||
|
||||
@@ -211,8 +210,7 @@ std::unordered_map<std::wstring,
|
||||
til::at(target, 0) = ANSI_NULL;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Convert our input parameters to Unicode.
|
||||
const auto sourceW = ConvertToW(codepage, source);
|
||||
@@ -272,8 +270,7 @@ std::unordered_map<std::wstring,
|
||||
size_t& written,
|
||||
const std::wstring_view exeName) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -379,8 +376,7 @@ static std::wstring aliasesSeparator(L"=");
|
||||
// Ensure output variables are initialized
|
||||
bufferRequired = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Convert our input parameters to Unicode
|
||||
try
|
||||
@@ -403,8 +399,7 @@ static std::wstring aliasesSeparator(L"=");
|
||||
[[nodiscard]] HRESULT ApiRoutines::GetConsoleAliasesLengthWImpl(const std::wstring_view exeName,
|
||||
size_t& bufferRequired) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -543,8 +538,7 @@ void Alias::s_ClearCmdExeAliases()
|
||||
til::at(alias, 0) = '\0';
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Convert our input parameters to Unicode.
|
||||
const auto exeNameW = ConvertToW(codepage, exeName);
|
||||
@@ -594,8 +588,7 @@ void Alias::s_ClearCmdExeAliases()
|
||||
gsl::span<wchar_t> alias,
|
||||
size_t& written) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -653,9 +646,8 @@ void Alias::s_ClearCmdExeAliases()
|
||||
// - Check HRESULT with SUCCEEDED. Can return memory, safe math, safe string, or locale conversion errors.
|
||||
[[nodiscard]] HRESULT ApiRoutines::GetConsoleAliasExesLengthAImpl(size_t& bufferRequired) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
const auto lock = LockConsole();
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
|
||||
return GetConsoleAliasExesLengthImplHelper(false, gci.CP, bufferRequired);
|
||||
}
|
||||
@@ -668,8 +660,7 @@ void Alias::s_ClearCmdExeAliases()
|
||||
// - Check HRESULT with SUCCEEDED. Can return memory, safe math, safe string, or locale conversion errors.
|
||||
[[nodiscard]] HRESULT ApiRoutines::GetConsoleAliasExesLengthWImpl(size_t& bufferRequired) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
return GetConsoleAliasExesLengthImplHelper(true, 0, bufferRequired);
|
||||
}
|
||||
@@ -761,8 +752,7 @@ void Alias::s_ClearCmdExeAliases()
|
||||
til::at(aliasExes, 0) = '\0';
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Figure our how big our temporary Unicode buffer must be to retrieve output
|
||||
size_t bufferNeeded;
|
||||
@@ -807,8 +797,7 @@ void Alias::s_ClearCmdExeAliases()
|
||||
[[nodiscard]] HRESULT ApiRoutines::GetConsoleAliasExesWImpl(gsl::span<wchar_t> aliasExes,
|
||||
size_t& written) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "../interactivity/inc/ServiceLocator.hpp"
|
||||
#include "../types/inc/convert.hpp"
|
||||
|
||||
#include <til/ticket_lock.h>
|
||||
|
||||
using Microsoft::Console::Interactivity::ServiceLocator;
|
||||
using Microsoft::Console::VirtualTerminal::VtIo;
|
||||
|
||||
@@ -47,50 +45,24 @@ CONSOLE_INFORMATION::CONSOLE_INFORMATION() :
|
||||
ZeroMemory((void*)&OutputCPInfo, sizeof(OutputCPInfo));
|
||||
}
|
||||
|
||||
// Access to thread-local variables is thread-safe, because each thread
|
||||
// gets its own copy of this variable with a default value of 0.
|
||||
//
|
||||
// Whenever we want to acquire the lock we increment recursionCount and on
|
||||
// each release we decrement it again. We can then make the lock safe for
|
||||
// reentrancy by only acquiring/releasing the lock if the recursionCount is 0.
|
||||
// In a sense, recursionCount is counting the actual function
|
||||
// call recursion depth of the caller. This works as long as
|
||||
// the caller makes sure to properly call Unlock() once for each Lock().
|
||||
static thread_local ULONG recursionCount = 0;
|
||||
static til::ticket_lock lock;
|
||||
|
||||
bool CONSOLE_INFORMATION::IsConsoleLocked()
|
||||
std::unique_lock<til::recursive_ticket_lock> CONSOLE_INFORMATION::LockConsole()
|
||||
{
|
||||
return recursionCount != 0;
|
||||
return std::unique_lock{ _lock };
|
||||
}
|
||||
|
||||
#pragma prefast(suppress : 26135, "Adding lock annotation spills into entire project. Future work.")
|
||||
void CONSOLE_INFORMATION::LockConsole()
|
||||
til::recursive_ticket_lock_suspension CONSOLE_INFORMATION::SuspendConsoleLock()
|
||||
{
|
||||
// See description of recursionCount a few lines above.
|
||||
const auto rc = ++recursionCount;
|
||||
FAIL_FAST_IF(rc == 0);
|
||||
if (rc == 1)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
return _lock.suspend();
|
||||
}
|
||||
|
||||
#pragma prefast(suppress : 26135, "Adding lock annotation spills into entire project. Future work.")
|
||||
void CONSOLE_INFORMATION::UnlockConsole()
|
||||
bool CONSOLE_INFORMATION::IsConsoleLocked() const
|
||||
{
|
||||
// See description of recursionCount a few lines above.
|
||||
const auto rc = --recursionCount;
|
||||
FAIL_FAST_IF(rc == ULONG_MAX);
|
||||
if (rc == 0)
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
return _lock.is_locked();
|
||||
}
|
||||
|
||||
ULONG CONSOLE_INFORMATION::GetCSRecursionCount()
|
||||
ULONG CONSOLE_INFORMATION::GetCSRecursionCount() const
|
||||
{
|
||||
return recursionCount;
|
||||
return _lock.recursion_depth();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -401,9 +373,8 @@ void CONSOLE_INFORMATION::ShutdownMidiAudio()
|
||||
{
|
||||
// We lock the console here to make sure the shutdown promise is
|
||||
// set before the audio is unlocked in the thread that is playing.
|
||||
LockConsole();
|
||||
const auto guard = LockConsole();
|
||||
_midiAudio->Shutdown();
|
||||
UnlockConsole();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,7 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
|
||||
[[nodiscard]] HRESULT ImeStartComposition()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
// MSFT:29219348 Some IME implementations do not produce composition strings, and
|
||||
// their users have come to rely on the cursor that conhost traditionally left on
|
||||
@@ -105,8 +104,7 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
|
||||
[[nodiscard]] HRESULT ImeEndComposition()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
const auto pIme = &gci.ConsoleIme;
|
||||
pIme->RestoreCursorVisibility();
|
||||
@@ -122,8 +120,7 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
const auto pIme = &gci.ConsoleIme;
|
||||
pIme->WriteCompMessage(text, attributes, colorArray);
|
||||
@@ -137,8 +134,7 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
const auto pIme = &gci.ConsoleIme;
|
||||
pIme->ClearAllAreas();
|
||||
@@ -152,8 +148,7 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
const auto pIme = &gci.ConsoleIme;
|
||||
pIme->WriteResultMessage(text);
|
||||
|
||||
@@ -166,8 +166,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
std::deque<std::unique_ptr<IInputEvent>> partialEvents;
|
||||
if (!IsUnicode)
|
||||
@@ -458,8 +457,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
{
|
||||
written = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -502,8 +500,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
{
|
||||
written = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -816,8 +813,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
const Microsoft::Console::Types::Viewport& sourceRectangle,
|
||||
Microsoft::Console::Types::Viewport& readRectangle) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -838,8 +834,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
const Microsoft::Console::Types::Viewport& sourceRectangle,
|
||||
Microsoft::Console::Types::Viewport& readRectangle) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -962,8 +957,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
const Viewport& requestRectangle,
|
||||
Viewport& writtenRectangle) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -983,8 +977,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
const Viewport& requestRectangle,
|
||||
Viewport& writtenRectangle) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1012,8 +1005,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
{
|
||||
written = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1033,8 +1025,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
{
|
||||
written = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1062,8 +1053,7 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
{
|
||||
written = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ struct NullDeviceComm : public IDeviceComm
|
||||
auto& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
|
||||
// Process handle list manipulation must be done under lock
|
||||
gci.LockConsole();
|
||||
const auto guard = gci.LockConsole();
|
||||
ConsoleProcessHandle* pProcessHandle{ nullptr };
|
||||
RETURN_IF_FAILED(gci.ProcessHandleList.AllocProcessData(GetCurrentProcessId(),
|
||||
GetCurrentThreadId(),
|
||||
@@ -95,8 +95,6 @@ struct NullDeviceComm : public IDeviceComm
|
||||
|
||||
CommandHistory::s_Allocate(fakeTitle, (HANDLE)pProcessHandle);
|
||||
|
||||
gci.UnlockConsole();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -134,8 +132,7 @@ extern "C" __declspec(dllexport) int LLVMFuzzerTestOneInput(const uint8_t* data,
|
||||
const auto u16String{ til::u8u16(std::string_view{ reinterpret_cast<const char*>(data), size }) };
|
||||
til::CoordType scrollY{};
|
||||
auto sizeInBytes{ u16String.size() * 2 };
|
||||
gci.LockConsole();
|
||||
auto u = wil::scope_exit([&]() { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
(void)WriteCharsLegacy(gci.GetActiveOutputBuffer(),
|
||||
u16String.data(),
|
||||
u16String.data(),
|
||||
|
||||
@@ -43,8 +43,7 @@ void ApiRoutines::GetConsoleInputModeImpl(InputBuffer& context, ULONG& mode) noe
|
||||
{
|
||||
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GetConsoleMode);
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
mode = context.InputMode;
|
||||
|
||||
@@ -68,8 +67,7 @@ void ApiRoutines::GetConsoleOutputModeImpl(SCREEN_INFORMATION& context, ULONG& m
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
mode = context.GetActiveBuffer().OutputMode;
|
||||
}
|
||||
@@ -87,8 +85,7 @@ void ApiRoutines::GetConsoleOutputModeImpl(SCREEN_INFORMATION& context, ULONG& m
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto readyEventCount = context.GetNumberOfReadyEvents();
|
||||
RETURN_IF_FAILED(SizeTToULong(readyEventCount, &events));
|
||||
@@ -108,8 +105,7 @@ void ApiRoutines::GetConsoleScreenBufferInfoExImpl(const SCREEN_INFORMATION& con
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
data.bFullscreenSupported = FALSE; // traditional full screen with the driver support is no longer supported.
|
||||
// see MSFT: 19918103
|
||||
@@ -162,8 +158,7 @@ void ApiRoutines::GetConsoleCursorInfoImpl(const SCREEN_INFORMATION& context,
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
size = context.GetActiveBuffer().GetTextBuffer().GetCursor().GetSize();
|
||||
isVisible = context.GetTextBuffer().GetCursor().IsVisible();
|
||||
@@ -179,8 +174,7 @@ void ApiRoutines::GetConsoleSelectionInfoImpl(CONSOLE_SELECTION_INFO& consoleSel
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto& selection = Selection::Instance();
|
||||
if (selection.IsInSelectingState())
|
||||
@@ -208,8 +202,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
buttons = ServiceLocator::LocateSystemConfigurationProvider()->GetNumberOfMouseButtons();
|
||||
}
|
||||
@@ -230,8 +223,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
@@ -263,8 +255,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto& activeScreenInfo = context.GetActiveBuffer();
|
||||
|
||||
@@ -306,8 +297,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
try
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& activeScreenInfo = context.GetActiveBuffer();
|
||||
|
||||
@@ -340,8 +330,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto oldQuickEditMode{ WI_IsFlagSet(gci.Flags, CONSOLE_QUICK_EDIT_MODE) };
|
||||
|
||||
@@ -416,8 +405,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Flags we don't understand are invalid.
|
||||
RETURN_HR_IF(E_INVALIDARG, WI_IsAnyFlagSet(mode, ~OUTPUT_MODES));
|
||||
@@ -466,8 +454,7 @@ void ApiRoutines::SetConsoleActiveScreenBufferImpl(SCREEN_INFORMATION& newContex
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
SetActiveScreenBuffer(newContext.GetActiveBuffer());
|
||||
}
|
||||
@@ -482,8 +469,7 @@ void ApiRoutines::FlushConsoleInputBuffer(InputBuffer& context) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
context.Flush();
|
||||
}
|
||||
@@ -500,8 +486,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto& screenInfo = context.GetActiveBuffer();
|
||||
|
||||
@@ -522,8 +507,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenInfo = context.GetActiveBuffer();
|
||||
|
||||
@@ -592,8 +576,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
data.dwSize.Y == SHRT_MAX));
|
||||
// clang-format on
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& gci = g.getConsoleInformation();
|
||||
@@ -716,8 +699,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& buffer = context.GetActiveBuffer();
|
||||
|
||||
@@ -801,8 +783,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If more than 100% or less than 0% cursor height, reject it.
|
||||
RETURN_HR_IF(E_INVALIDARG, (size > 100 || size == 0));
|
||||
@@ -829,8 +810,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto Window = windowRect;
|
||||
@@ -938,8 +918,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& buffer = context.GetActiveBuffer();
|
||||
|
||||
@@ -996,8 +975,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, WI_IsAnyFlagSet(attribute, ~VALID_TEXT_ATTRIBUTES));
|
||||
|
||||
@@ -1040,8 +1018,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
return DoSrvSetConsoleOutputCodePage(codepage);
|
||||
}
|
||||
CATCH_RETURN();
|
||||
@@ -1058,8 +1035,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont
|
||||
try
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Return if it's not known as a valid codepage ID.
|
||||
RETURN_HR_IF(E_INVALIDARG, !(IsValidCodePage(codepage)));
|
||||
@@ -1087,8 +1063,7 @@ void ApiRoutines::GetConsoleInputCodePageImpl(ULONG& codepage) noexcept
|
||||
try
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
codepage = gci.CP;
|
||||
}
|
||||
@@ -1103,8 +1078,7 @@ void ApiRoutines::GetConsoleOutputCodePageImpl(ULONG& codepage) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
codepage = gci.OutputCP;
|
||||
}
|
||||
@@ -1122,8 +1096,7 @@ void ApiRoutines::GetConsoleWindowImpl(HWND& hwnd) noexcept
|
||||
// Set return to null before we do anything in case of failures/errors.
|
||||
hwnd = nullptr;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
const IConsoleWindow* pWindow = ServiceLocator::LocateConsoleWindow();
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
if (pWindow != nullptr)
|
||||
@@ -1155,8 +1128,7 @@ void ApiRoutines::GetConsoleHistoryInfoImpl(CONSOLE_HISTORY_INFO& consoleHistory
|
||||
try
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
consoleHistoryInfo.HistoryBufferSize = gci.GetHistoryBufferSize();
|
||||
consoleHistoryInfo.NumberOfHistoryBuffers = gci.GetNumberOfHistoryBuffers();
|
||||
@@ -1180,8 +1152,7 @@ HRESULT ApiRoutines::SetConsoleHistoryInfoImpl(const CONSOLE_HISTORY_INFO& conso
|
||||
RETURN_HR_IF(E_INVALIDARG, consoleHistoryInfo.NumberOfHistoryBuffers > SHORT_MAX);
|
||||
RETURN_HR_IF(E_INVALIDARG, WI_IsAnyFlagSet(consoleHistoryInfo.dwFlags, ~CHI_VALID_FLAGS));
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
CommandHistory::s_ResizeAll(consoleHistoryInfo.HistoryBufferSize);
|
||||
gci.SetNumberOfHistoryBuffers(consoleHistoryInfo.NumberOfHistoryBuffers);
|
||||
@@ -1202,8 +1173,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Initialize flags portion of structure
|
||||
flags = 0;
|
||||
@@ -1241,9 +1211,8 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
// SetIsFullscreen() below ultimately calls SetwindowLong, which ultimately calls SendMessage(). If we retain
|
||||
// the console lock, we'll deadlock since ConsoleWindowProc takes the lock before processing messages. Instead,
|
||||
// we'll release early.
|
||||
LockConsole();
|
||||
{
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& screenInfo = context.GetActiveBuffer();
|
||||
|
||||
@@ -1431,8 +1400,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
return GetConsoleTitleAImplHelper(title, written, needed, false);
|
||||
}
|
||||
@@ -1454,8 +1422,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
return GetConsoleTitleWImplHelper(title, written, needed, false);
|
||||
}
|
||||
@@ -1477,8 +1444,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
return GetConsoleTitleAImplHelper(title, written, needed, true);
|
||||
}
|
||||
@@ -1500,8 +1466,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
return GetConsoleTitleWImplHelper(title, written, needed, true);
|
||||
}
|
||||
@@ -1535,8 +1500,7 @@ void ApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept
|
||||
// - S_OK, E_INVALIDARG, or failure code from thrown exception
|
||||
[[nodiscard]] HRESULT ApiRoutines::SetConsoleTitleWImpl(const std::wstring_view title) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
ServiceLocator::LocateGlobals().getConsoleInformation().SetTitle(title);
|
||||
return S_OK;
|
||||
|
||||
@@ -10,21 +10,22 @@
|
||||
|
||||
using Microsoft::Console::Interactivity::ServiceLocator;
|
||||
|
||||
void LockConsole()
|
||||
LockConsoleGuard::LockConsoleGuard(std::unique_lock<til::recursive_ticket_lock>&& guard) noexcept :
|
||||
_guard{ std::move(guard) }
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole();
|
||||
}
|
||||
|
||||
void UnlockConsole()
|
||||
LockConsoleGuard::~LockConsoleGuard()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
if (gci.GetCSRecursionCount() == 1)
|
||||
{
|
||||
ProcessCtrlEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
gci.UnlockConsole();
|
||||
}
|
||||
}
|
||||
|
||||
LockConsoleGuard LockConsole()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
return LockConsoleGuard{ gci.LockConsole() };
|
||||
}
|
||||
|
||||
@@ -17,5 +17,15 @@ Revision History:
|
||||
|
||||
#pragma once
|
||||
|
||||
void LockConsole();
|
||||
void UnlockConsole();
|
||||
#include <til/ticket_lock.h>
|
||||
|
||||
struct LockConsoleGuard
|
||||
{
|
||||
explicit LockConsoleGuard(std::unique_lock<til::recursive_ticket_lock>&& guard) noexcept;
|
||||
~LockConsoleGuard();
|
||||
|
||||
private:
|
||||
std::unique_lock<til::recursive_ticket_lock> _guard;
|
||||
};
|
||||
|
||||
LockConsoleGuard LockConsole();
|
||||
|
||||
@@ -588,8 +588,7 @@ HRESULT ApiRoutines::ExpungeConsoleCommandHistoryAImpl(const std::string_view ex
|
||||
// - Check HRESULT with SUCCEEDED. Can return memory, safe math, safe string, or locale conversion errors.
|
||||
HRESULT ApiRoutines::ExpungeConsoleCommandHistoryWImpl(const std::wstring_view exeName) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -636,8 +635,7 @@ HRESULT ApiRoutines::SetConsoleNumberOfCommandsAImpl(const std::string_view exeN
|
||||
HRESULT ApiRoutines::SetConsoleNumberOfCommandsWImpl(const std::wstring_view exeName,
|
||||
const size_t numberOfCommands) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -668,8 +666,7 @@ HRESULT GetConsoleCommandHistoryLengthImplHelper(const std::wstring_view exeName
|
||||
// Ensure output variables are initialized
|
||||
historyLength = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
const auto pCommandHistory = CommandHistory::s_FindByExe(exeName);
|
||||
if (nullptr != pCommandHistory)
|
||||
@@ -721,8 +718,7 @@ HRESULT ApiRoutines::GetConsoleCommandHistoryLengthAImpl(const std::string_view
|
||||
// Ensure output variables are initialized
|
||||
length = 0;
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -742,8 +738,7 @@ HRESULT ApiRoutines::GetConsoleCommandHistoryLengthAImpl(const std::string_view
|
||||
HRESULT ApiRoutines::GetConsoleCommandHistoryLengthWImpl(const std::wstring_view exeName,
|
||||
size_t& length) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -853,8 +848,7 @@ HRESULT ApiRoutines::GetConsoleCommandHistoryAImpl(const std::string_view exeNam
|
||||
til::at(commandHistory, 0) = ANSI_NULL;
|
||||
}
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Convert our input parameters to Unicode.
|
||||
const auto exeNameW = ConvertToW(codepage, exeName);
|
||||
@@ -904,8 +898,7 @@ HRESULT ApiRoutines::GetConsoleCommandHistoryWImpl(const std::wstring_view exeNa
|
||||
gsl::span<wchar_t> commandHistory,
|
||||
size_t& written) noexcept
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -521,6 +521,5 @@ void CloseConsoleProcessState()
|
||||
// not running under lock (eg PtySignalInputThread::_GetData), then the
|
||||
// ctrl event will never actually get dispatched.
|
||||
// So, lock and unlock here, to make sure the ctrl event gets handled.
|
||||
LockConsole();
|
||||
UnlockConsole();
|
||||
std::ignore = LockConsole();
|
||||
}
|
||||
|
||||
@@ -375,19 +375,22 @@ void ConhostInternalGetSet::PlayMidiNote(const int noteNumber, const int velocit
|
||||
{
|
||||
// We create the audio instance on demand, and lock it for the duration
|
||||
// of the note output so it can't be destroyed while in use.
|
||||
auto& midiAudio = ServiceLocator::LocateGlobals().getConsoleInformation().GetMidiAudio();
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto& midiAudio = gci.GetMidiAudio();
|
||||
midiAudio.Lock();
|
||||
|
||||
// We then unlock the console, so the UI doesn't hang while we're busy.
|
||||
UnlockConsole();
|
||||
{
|
||||
// We then unlock the console, so the UI doesn't hang while we're busy.
|
||||
const auto guard = gci.SuspendConsoleLock();
|
||||
|
||||
// This call will block for the duration, unless shutdown early.
|
||||
midiAudio.PlayNote(noteNumber, velocity, duration);
|
||||
// This call will block for the duration, unless shutdown early.
|
||||
midiAudio.PlayNote(noteNumber, velocity, duration);
|
||||
|
||||
// Once complete, we reacquire the console lock and unlock the audio.
|
||||
}
|
||||
|
||||
// Once complete, we reacquire the console lock and unlock the audio.
|
||||
// If the console has shutdown in the meantime, the Unlock call
|
||||
// will throw an exception, forcing the thread to exit ASAP.
|
||||
LockConsole();
|
||||
midiAudio.Unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,16 +86,11 @@ std::vector<Viewport> RenderData::GetSelectionRects() noexcept
|
||||
// operation.
|
||||
// Callers should make sure to also call RenderData::UnlockConsole once
|
||||
// they're done with any querying they need to do.
|
||||
void RenderData::LockConsole() noexcept
|
||||
std::unique_lock<til::ticket_lock> RenderData::LockConsole() noexcept
|
||||
{
|
||||
::LockConsole();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Unlocks the console after a call to RenderData::LockConsole.
|
||||
void RenderData::UnlockConsole() noexcept
|
||||
{
|
||||
::UnlockConsole();
|
||||
__debugbreak();
|
||||
return {};
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@@ -31,8 +31,7 @@ public:
|
||||
|
||||
std::vector<Microsoft::Console::Types::Viewport> GetSelectionRects() noexcept override;
|
||||
|
||||
void LockConsole() noexcept override;
|
||||
void UnlockConsole() noexcept override;
|
||||
[[nodiscard]] std::unique_lock<til::ticket_lock> LockConsole() noexcept override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IRenderData
|
||||
|
||||
@@ -30,6 +30,8 @@ Revision History:
|
||||
#include "../host/RenderData.hpp"
|
||||
#include "../audio/midi/MidiAudio.hpp"
|
||||
|
||||
#include <til/ticket_lock.h>
|
||||
|
||||
// clang-format off
|
||||
// Flags flags
|
||||
#define CONSOLE_IS_ICONIC 0x00000001
|
||||
@@ -103,10 +105,10 @@ public:
|
||||
|
||||
ConsoleImeInfo ConsoleIme;
|
||||
|
||||
static void LockConsole();
|
||||
static void UnlockConsole();
|
||||
static bool IsConsoleLocked();
|
||||
static ULONG GetCSRecursionCount();
|
||||
[[nodiscard]] std::unique_lock<til::recursive_ticket_lock> LockConsole();
|
||||
[[nodiscard]] til::recursive_ticket_lock_suspension SuspendConsoleLock();
|
||||
bool IsConsoleLocked() const;
|
||||
ULONG GetCSRecursionCount() const;
|
||||
|
||||
Microsoft::Console::VirtualTerminal::VtIo* GetVtIo();
|
||||
|
||||
@@ -147,6 +149,8 @@ public:
|
||||
RenderData renderData;
|
||||
|
||||
private:
|
||||
til::recursive_ticket_lock _lock;
|
||||
|
||||
std::wstring _Title;
|
||||
std::wstring _Prefix; // Eg Select, Mark - things that we manually prepend to the title.
|
||||
std::wstring _TitleAndPrefix;
|
||||
|
||||
@@ -249,7 +249,7 @@ static bool s_IsOnDesktop()
|
||||
[[nodiscard]] NTSTATUS RemoveConsole(_In_ ConsoleProcessHandle* ProcessData)
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
const auto guard = LockConsole();
|
||||
auto Status = STATUS_SUCCESS;
|
||||
|
||||
CommandHistory::s_Free((HANDLE)ProcessData);
|
||||
@@ -266,8 +266,6 @@ static bool s_IsOnDesktop()
|
||||
}
|
||||
}
|
||||
|
||||
UnlockConsole();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -708,8 +706,7 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand,
|
||||
try
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// This fails a lot and it's totally expected. It only works for a few East Asian code pages.
|
||||
// As such, just return it. Do NOT use a wil macro here. It is very noisy.
|
||||
|
||||
@@ -694,8 +694,7 @@ til::CoordType RetrieveNumberOfSpaces(_In_ til::CoordType sOriginalCursorPositio
|
||||
{
|
||||
try
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
waiter.reset();
|
||||
|
||||
|
||||
@@ -340,8 +340,7 @@ class ApiRoutinesTests
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
|
||||
gci.LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
// Ensure global state is updated for our codepage.
|
||||
gci.OutputCP = dwCodePage;
|
||||
@@ -430,8 +429,7 @@ class ApiRoutinesTests
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
|
||||
gci.LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
const std::wstring testText(L"Test text");
|
||||
|
||||
@@ -616,8 +614,7 @@ class ApiRoutinesTests
|
||||
// Make sure we clear the margins on exit so they can't break other tests.
|
||||
auto clearMargins = wil::scope_exit([&] { stateMachine.ProcessString(L"\x1b[r"); });
|
||||
|
||||
gci.LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole();
|
||||
|
||||
CHAR_INFO fill;
|
||||
fill.Char.UnicodeChar = L'A';
|
||||
|
||||
@@ -251,8 +251,7 @@ class ScreenBufferTests
|
||||
void ScreenBufferTests::SingleAlternateBufferCreationTest()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
Log::Comment(L"Testing creating one alternate buffer, then returning to the main buffer.");
|
||||
const auto psiOriginal = &gci.GetActiveOutputBuffer();
|
||||
@@ -283,8 +282,7 @@ void ScreenBufferTests::SingleAlternateBufferCreationTest()
|
||||
void ScreenBufferTests::MultipleAlternateBufferCreationTest()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
Log::Comment(
|
||||
L"Testing creating one alternate buffer, then creating another "
|
||||
@@ -330,8 +328,7 @@ void ScreenBufferTests::MultipleAlternateBufferCreationTest()
|
||||
void ScreenBufferTests::MultipleAlternateBuffersFromMainCreationTest()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
Log::Comment(
|
||||
L"Testing creating one alternate buffer, then creating another"
|
||||
@@ -375,8 +372,7 @@ void ScreenBufferTests::MultipleAlternateBuffersFromMainCreationTest()
|
||||
void ScreenBufferTests::AlternateBufferCursorInheritanceTest()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
auto& mainCursor = mainBuffer.GetTextBuffer().GetCursor();
|
||||
@@ -872,8 +868,7 @@ void ScreenBufferTests::TestGetReverseTab()
|
||||
void ScreenBufferTests::TestAltBufferTabStops()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
// Make sure we're in VT mode
|
||||
@@ -2029,8 +2024,7 @@ void ScreenBufferTests::ResizeCursorUnchanged()
|
||||
void ScreenBufferTests::ResizeAltBuffer()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& si = gci.GetActiveOutputBuffer().GetActiveBuffer();
|
||||
auto& stateMachine = si.GetStateMachine();
|
||||
@@ -2084,8 +2078,7 @@ void ScreenBufferTests::ResizeAltBufferGetScreenBufferInfo()
|
||||
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& gci = g.getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer().GetActiveBuffer();
|
||||
auto& stateMachine = mainBuffer.GetStateMachine();
|
||||
@@ -2352,8 +2345,7 @@ void ScreenBufferTests::GetWordBoundaryTrimZerosOff()
|
||||
void ScreenBufferTests::TestAltBufferCursorState()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
Log::Comment(L"Creating one alternate buffer");
|
||||
auto& original = gci.GetActiveOutputBuffer();
|
||||
@@ -2392,8 +2384,7 @@ void ScreenBufferTests::TestAltBufferCursorState()
|
||||
void ScreenBufferTests::TestAltBufferVtDispatching()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
Log::Comment(L"Creating one alternate buffer");
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
// Make sure we're in VT mode
|
||||
@@ -2484,8 +2475,7 @@ void ScreenBufferTests::TestAltBufferVtDispatching()
|
||||
void ScreenBufferTests::TestAltBufferRIS()
|
||||
{
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& stateMachine = si.GetStateMachine();
|
||||
@@ -2963,8 +2953,7 @@ void ScreenBufferTests::SetGlobalColorTable()
|
||||
// tested.
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
VERIFY_IS_FALSE(mainBuffer._IsAltBuffer());
|
||||
@@ -3070,8 +3059,7 @@ void ScreenBufferTests::SetColorTableThreeDigits()
|
||||
// Changing the value of the color table above index 99 should work
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
VERIFY_IS_FALSE(mainBuffer._IsAltBuffer());
|
||||
@@ -3154,8 +3142,7 @@ void ScreenBufferTests::SetDefaultForegroundColor()
|
||||
// Setting the default foreground color should work
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
VERIFY_IS_FALSE(mainBuffer._IsAltBuffer());
|
||||
@@ -3199,8 +3186,7 @@ void ScreenBufferTests::SetDefaultBackgroundColor()
|
||||
// Setting the default Background color should work
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to swap buffers.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
VERIFY_IS_FALSE(mainBuffer._IsAltBuffer());
|
||||
@@ -5143,8 +5129,7 @@ void ScreenBufferTests::RestoreDownAltBufferWithTerminalScrolling()
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.SetTerminalScrolling(true);
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& siMain = gci.GetActiveOutputBuffer();
|
||||
auto coordFontSize = siMain.GetScreenFontSize();
|
||||
@@ -5210,8 +5195,7 @@ void ScreenBufferTests::SnapCursorWithTerminalScrolling()
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& gci = g.getConsoleInformation();
|
||||
gci.SetTerminalScrolling(true);
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& cursor = si.GetTextBuffer().GetCursor();
|
||||
@@ -5284,8 +5268,7 @@ void ScreenBufferTests::ClearAlternateBuffer()
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& siMain = gci.GetActiveOutputBuffer();
|
||||
auto WriteText = [&](TextBuffer& tbi) {
|
||||
@@ -6766,8 +6749,7 @@ void ScreenBufferTests::TestWriteConsoleVTQuirkMode()
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"useQuirk", useQuirk), L"whether to enable the quirk");
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
auto& mainBuffer = gci.GetActiveOutputBuffer();
|
||||
auto& cursor = mainBuffer.GetTextBuffer().GetCursor();
|
||||
@@ -7134,8 +7116,7 @@ void ScreenBufferTests::TestDeferredMainBufferResize()
|
||||
L"main buffer till we swap back to it, for performance.");
|
||||
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
|
||||
const auto lock = gci.LockConsole(); // Lock must be taken to manipulate buffer.
|
||||
|
||||
// HUGELY cribbed from ConptyRoundtripTests::MethodSetup. This fakes the
|
||||
// console into thinking that it's in ConPTY mode. Yes, we need all this
|
||||
|
||||
@@ -282,12 +282,9 @@ public:
|
||||
return std::vector<Microsoft::Console::Types::Viewport>{};
|
||||
}
|
||||
|
||||
void LockConsole() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void UnlockConsole() noexcept override
|
||||
std::unique_lock<til::ticket_lock> LockConsole() noexcept override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<COLORREF, COLORREF> GetAttributeColors(const TextAttribute& /*attr*/) const noexcept override
|
||||
|
||||
@@ -53,4 +53,89 @@ namespace til
|
||||
std::atomic<uint32_t> _next_ticket{ 0 };
|
||||
std::atomic<uint32_t> _now_serving{ 0 };
|
||||
};
|
||||
|
||||
struct recursive_ticket_lock
|
||||
{
|
||||
struct recursive_ticket_lock_suspension
|
||||
{
|
||||
recursive_ticket_lock_suspension(recursive_ticket_lock& lock) :
|
||||
_lock{ lock }
|
||||
{
|
||||
}
|
||||
|
||||
~recursive_ticket_lock_suspension()
|
||||
{
|
||||
if (_owner)
|
||||
{
|
||||
_lock._lock.lock(); // lock-lock-lock lol
|
||||
_lock._owner.store(_owner, std::memory_order_relaxed);
|
||||
_lock._recursion = _recursion;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend struct recursive_ticket_lock;
|
||||
|
||||
recursive_ticket_lock& _lock;
|
||||
uint32_t _owner = 0;
|
||||
uint32_t _recursion = 0;
|
||||
};
|
||||
|
||||
void lock() noexcept
|
||||
{
|
||||
const auto id = GetCurrentThreadId();
|
||||
|
||||
if (_owner.load(std::memory_order_relaxed) != id)
|
||||
{
|
||||
_lock.lock();
|
||||
_owner.store(id, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
_recursion++;
|
||||
}
|
||||
|
||||
void unlock() noexcept
|
||||
{
|
||||
if (--_recursion == 0)
|
||||
{
|
||||
_owner.store(0, std::memory_order_relaxed);
|
||||
_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] recursive_ticket_lock_suspension suspend() noexcept
|
||||
{
|
||||
const auto id = GetCurrentThreadId();
|
||||
recursive_ticket_lock_suspension guard{ *this };
|
||||
|
||||
if (_owner.load(std::memory_order_relaxed) == id)
|
||||
{
|
||||
guard._owner = id;
|
||||
guard._recursion = _recursion;
|
||||
_owner.store(0, std::memory_order_relaxed);
|
||||
_recursion = 0;
|
||||
_lock.unlock();
|
||||
}
|
||||
|
||||
return guard;
|
||||
}
|
||||
|
||||
uint32_t is_locked() const noexcept
|
||||
{
|
||||
const auto id = GetCurrentThreadId();
|
||||
return _owner.load(std::memory_order_relaxed) == id;
|
||||
}
|
||||
|
||||
uint32_t recursion_depth() const noexcept
|
||||
{
|
||||
return is_locked() ? _recursion : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
ticket_lock _lock;
|
||||
std::atomic<uint32_t> _owner = 0;
|
||||
uint32_t _recursion = 0;
|
||||
};
|
||||
|
||||
using recursive_ticket_lock_suspension = recursive_ticket_lock::recursive_ticket_lock_suspension;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ void ServiceLocator::SetOneCoreTeardownFunction(void (*pfn)()) noexcept
|
||||
#ifndef NDEBUG
|
||||
// By locking the console, we ensure no background tasks are accessing the
|
||||
// classes we're going to destruct down below (for instance: CursorBlinker).
|
||||
s_globals.getConsoleInformation().LockConsole();
|
||||
const auto guard = s_globals.getConsoleInformation().LockConsole();
|
||||
#endif
|
||||
|
||||
// A History Lesson from MSFT: 13576341:
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
// ConIoSrv.h, included above. For security-related considerations, see Trust.h
|
||||
// in the ConIoSrv directory.
|
||||
|
||||
extern void LockConsole();
|
||||
extern void UnlockConsole();
|
||||
|
||||
using namespace Microsoft::Console::Render;
|
||||
using namespace Microsoft::Console::Interactivity::OneCore;
|
||||
|
||||
@@ -259,7 +256,7 @@ VOID ConIoSrvComm::ServiceInputPipe()
|
||||
|
||||
if (Ret != FALSE)
|
||||
{
|
||||
LockConsole();
|
||||
const auto lock = LockConsole();
|
||||
switch (Event.Type)
|
||||
{
|
||||
case CIS_EVENT_TYPE_INPUT:
|
||||
@@ -280,7 +277,6 @@ VOID ConIoSrvComm::ServiceInputPipe()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UnlockConsole();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -53,8 +53,7 @@ INT_PTR CALLBACK FindDialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM l
|
||||
|
||||
std::wstring wstr(szBuf, StringLength);
|
||||
lastFindString = wstr;
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
Search search(gci.renderData,
|
||||
wstr,
|
||||
@@ -92,7 +91,6 @@ void DoFind()
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
const auto pWindow = ServiceLocator::LocateConsoleWindow();
|
||||
|
||||
UnlockConsole();
|
||||
if (pWindow != nullptr)
|
||||
{
|
||||
const auto hwnd = pWindow->GetWindowHandle();
|
||||
|
||||
@@ -1022,35 +1022,36 @@ DWORD WINAPI ConsoleInputThreadProcWin32(LPVOID /*lpParameter*/)
|
||||
{
|
||||
InitEnvironmentVariables();
|
||||
|
||||
LockConsole();
|
||||
HHOOK hhook = nullptr;
|
||||
auto Status = STATUS_SUCCESS;
|
||||
{
|
||||
const auto lock = LockConsole();
|
||||
|
||||
if (!ServiceLocator::LocateGlobals().launchArgs.IsHeadless())
|
||||
{
|
||||
// If we're not headless, set up the main conhost window.
|
||||
Status = InitWindowsSubsystem(&hhook);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are headless (because we're a pseudo console), we
|
||||
// will still need a window handle in the win32 environment
|
||||
// in case anyone sends messages at that HWND (vim.exe is an example.)
|
||||
//
|
||||
// IMPORTANT! We have to CreateWindow on the same thread that will pump
|
||||
// the messages, which is this thread. If you DON'T, then a DPI change
|
||||
// in the owning hwnd will cause us to get a dpi change as well, which
|
||||
// we'll never deque and handle, effectively HANGING THE OWNER HWND.
|
||||
// ServiceLocator::LocatePseudoWindow();
|
||||
//
|
||||
// Instead of just calling LocatePseudoWindow, make sure to go through
|
||||
// VtIo's CreatePseudoWindow, which will make sure that the window is
|
||||
// successfully created with the owner configured when the window is
|
||||
// first created. See GH#13066 for details.
|
||||
ServiceLocator::LocateGlobals().getConsoleInformation().GetVtIo()->CreatePseudoWindow();
|
||||
if (!ServiceLocator::LocateGlobals().launchArgs.IsHeadless())
|
||||
{
|
||||
// If we're not headless, set up the main conhost window.
|
||||
Status = InitWindowsSubsystem(&hhook);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are headless (because we're a pseudo console), we
|
||||
// will still need a window handle in the win32 environment
|
||||
// in case anyone sends messages at that HWND (vim.exe is an example.)
|
||||
//
|
||||
// IMPORTANT! We have to CreateWindow on the same thread that will pump
|
||||
// the messages, which is this thread. If you DON'T, then a DPI change
|
||||
// in the owning hwnd will cause us to get a dpi change as well, which
|
||||
// we'll never deque and handle, effectively HANGING THE OWNER HWND.
|
||||
// ServiceLocator::LocatePseudoWindow();
|
||||
//
|
||||
// Instead of just calling LocatePseudoWindow, make sure to go through
|
||||
// VtIo's CreatePseudoWindow, which will make sure that the window is
|
||||
// successfully created with the owner configured when the window is
|
||||
// first created. See GH#13066 for details.
|
||||
ServiceLocator::LocateGlobals().getConsoleInformation().GetVtIo()->CreatePseudoWindow();
|
||||
}
|
||||
}
|
||||
|
||||
UnlockConsole();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ServiceLocator::LocateGlobals().ntstatusConsoleInputInitStatus = Status;
|
||||
|
||||
@@ -67,9 +67,8 @@ using namespace Microsoft::Console::Types;
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& gci = g.getConsoleInformation();
|
||||
LRESULT Status = 0;
|
||||
auto Unlock = TRUE;
|
||||
|
||||
LockConsole();
|
||||
const auto lock = LockConsole();
|
||||
|
||||
auto& ScreenInfo = GetScreenInfo();
|
||||
if (hWnd == nullptr) // TODO: this might not be possible anymore
|
||||
@@ -84,7 +83,6 @@ using namespace Microsoft::Console::Types;
|
||||
Status = DefWindowProcW(hWnd, Message, wParam, lParam);
|
||||
}
|
||||
|
||||
UnlockConsole();
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -214,7 +212,6 @@ using namespace Microsoft::Console::Types;
|
||||
pSuggestionSize->cy = rectProposed.height();
|
||||
|
||||
// Format our final suggestion for consumption.
|
||||
UnlockConsole();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -476,9 +473,6 @@ using namespace Microsoft::Console::Types;
|
||||
{
|
||||
auto hHeirMenu = Menu::s_GetHeirMenuHandle();
|
||||
|
||||
Unlock = FALSE;
|
||||
UnlockConsole();
|
||||
|
||||
TrackPopupMenuEx(hHeirMenu,
|
||||
TPM_RIGHTBUTTON | (GetSystemMetrics(SM_MENUDROPALIGNMENT) == 0 ? TPM_LEFTALIGN : TPM_RIGHTALIGN),
|
||||
GET_X_LPARAM(lParam),
|
||||
@@ -499,8 +493,6 @@ using namespace Microsoft::Console::Types;
|
||||
switch (wParam & 0x00FF)
|
||||
{
|
||||
case HTCAPTION:
|
||||
UnlockConsole();
|
||||
Unlock = FALSE;
|
||||
SetActiveWindow(hWnd);
|
||||
SendMessageTimeoutW(hWnd, WM_SYSCOMMAND, SC_MOVE | wParam, lParam, SMTO_NORMAL, INFINITE, nullptr);
|
||||
break;
|
||||
@@ -560,7 +552,6 @@ using namespace Microsoft::Console::Types;
|
||||
else if (wParam == ID_CONSOLE_FIND)
|
||||
{
|
||||
DoFind();
|
||||
Unlock = FALSE;
|
||||
}
|
||||
else if (wParam == ID_CONSOLE_SELECTALL)
|
||||
{
|
||||
@@ -670,9 +661,6 @@ using namespace Microsoft::Console::Types;
|
||||
|
||||
case CM_BEEP:
|
||||
{
|
||||
UnlockConsole();
|
||||
Unlock = FALSE;
|
||||
|
||||
// Don't fall back to Beep() on win32 systems -- if the user configures their system for no sound, we should
|
||||
// respect that.
|
||||
PlaySoundW((LPCWSTR)SND_ALIAS_SYSTEMHAND, nullptr, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
|
||||
@@ -752,21 +740,11 @@ using namespace Microsoft::Console::Types;
|
||||
default:
|
||||
CallDefWin:
|
||||
{
|
||||
if (Unlock)
|
||||
{
|
||||
UnlockConsole();
|
||||
Unlock = FALSE;
|
||||
}
|
||||
Status = DefWindowProcW(hWnd, Message, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unlock)
|
||||
{
|
||||
UnlockConsole();
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,70 +109,68 @@ try
|
||||
{
|
||||
FAIL_FAST_IF_NULL(pEngine); // This is a programming error. Fail fast.
|
||||
|
||||
_pData->LockConsole();
|
||||
auto unlock = wil::scope_exit([&]() {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
// Last chance check if anything scrolled without an explicit invalidate notification since the last frame.
|
||||
_CheckViewportAndScroll();
|
||||
|
||||
// Try to start painting a frame
|
||||
const auto hr = pEngine->StartPaint();
|
||||
RETURN_IF_FAILED(hr);
|
||||
|
||||
// Return early if there's nothing to paint.
|
||||
// The renderer itself tracks if there's something to do with the title, the
|
||||
// engine won't know that.
|
||||
if (S_FALSE == hr)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
const auto lock = _pData->LockConsole();
|
||||
|
||||
auto endPaint = wil::scope_exit([&]() {
|
||||
LOG_IF_FAILED(pEngine->EndPaint());
|
||||
// Last chance check if anything scrolled without an explicit invalidate notification since the last frame.
|
||||
_CheckViewportAndScroll();
|
||||
|
||||
// If the engine tells us it really wants to redraw immediately,
|
||||
// tell the thread so it doesn't go to sleep and ticks again
|
||||
// at the next opportunity.
|
||||
if (pEngine->RequiresContinuousRedraw())
|
||||
// Try to start painting a frame
|
||||
const auto hr = pEngine->StartPaint();
|
||||
RETURN_IF_FAILED(hr);
|
||||
|
||||
// Return early if there's nothing to paint.
|
||||
// The renderer itself tracks if there's something to do with the title, the
|
||||
// engine won't know that.
|
||||
if (S_FALSE == hr)
|
||||
{
|
||||
NotifyPaintFrame();
|
||||
return S_OK;
|
||||
}
|
||||
});
|
||||
|
||||
// A. Prep Colors
|
||||
RETURN_IF_FAILED(_UpdateDrawingBrushes(pEngine, {}, false, true));
|
||||
auto endPaint = wil::scope_exit([&]() {
|
||||
LOG_IF_FAILED(pEngine->EndPaint());
|
||||
|
||||
// B. Perform Scroll Operations
|
||||
RETURN_IF_FAILED(_PerformScrolling(pEngine));
|
||||
// If the engine tells us it really wants to redraw immediately,
|
||||
// tell the thread so it doesn't go to sleep and ticks again
|
||||
// at the next opportunity.
|
||||
if (pEngine->RequiresContinuousRedraw())
|
||||
{
|
||||
NotifyPaintFrame();
|
||||
}
|
||||
});
|
||||
|
||||
// C. Prepare the engine with additional information before we start drawing.
|
||||
RETURN_IF_FAILED(_PrepareRenderInfo(pEngine));
|
||||
// A. Prep Colors
|
||||
RETURN_IF_FAILED(_UpdateDrawingBrushes(pEngine, {}, false, true));
|
||||
|
||||
// 1. Paint Background
|
||||
RETURN_IF_FAILED(_PaintBackground(pEngine));
|
||||
// B. Perform Scroll Operations
|
||||
RETURN_IF_FAILED(_PerformScrolling(pEngine));
|
||||
|
||||
// 2. Paint Rows of Text
|
||||
_PaintBufferOutput(pEngine);
|
||||
// C. Prepare the engine with additional information before we start drawing.
|
||||
RETURN_IF_FAILED(_PrepareRenderInfo(pEngine));
|
||||
|
||||
// 3. Paint overlays that reside above the text buffer
|
||||
_PaintOverlays(pEngine);
|
||||
// 1. Paint Background
|
||||
RETURN_IF_FAILED(_PaintBackground(pEngine));
|
||||
|
||||
// 4. Paint Selection
|
||||
_PaintSelection(pEngine);
|
||||
// 2. Paint Rows of Text
|
||||
_PaintBufferOutput(pEngine);
|
||||
|
||||
// 5. Paint Cursor
|
||||
_PaintCursor(pEngine);
|
||||
// 3. Paint overlays that reside above the text buffer
|
||||
_PaintOverlays(pEngine);
|
||||
|
||||
// 6. Paint window title
|
||||
RETURN_IF_FAILED(_PaintTitle(pEngine));
|
||||
// 4. Paint Selection
|
||||
_PaintSelection(pEngine);
|
||||
|
||||
// Force scope exit end paint to finish up collecting information and possibly painting
|
||||
endPaint.reset();
|
||||
// 5. Paint Cursor
|
||||
_PaintCursor(pEngine);
|
||||
|
||||
// Force scope exit unlock to let go of global lock so other threads can run
|
||||
unlock.reset();
|
||||
// 6. Paint window title
|
||||
RETURN_IF_FAILED(_PaintTitle(pEngine));
|
||||
|
||||
// Force scope exit end paint to finish up collecting information and possibly painting
|
||||
endPaint.reset();
|
||||
|
||||
// Force scope exit unlock to let go of global lock so other threads can run
|
||||
}
|
||||
|
||||
// Trigger out-of-lock presentation for renderers that can support it
|
||||
RETURN_IF_FAILED(pEngine->Present());
|
||||
|
||||
@@ -35,8 +35,7 @@ using Microsoft::Console::Interactivity::ServiceLocator;
|
||||
|
||||
a->dwProcessCount = BufferSize / sizeof(ULONG);
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
/*
|
||||
* If there's not enough space in the array to hold all the pids, we'll
|
||||
@@ -73,8 +72,7 @@ using Microsoft::Console::Interactivity::ServiceLocator;
|
||||
const auto a = &m->u.consoleMsgL2.GenerateConsoleCtrlEvent;
|
||||
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GenerateConsoleCtrlEvent);
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// Make sure the process group id is valid.
|
||||
if (a->ProcessGroupId != 0)
|
||||
|
||||
@@ -47,7 +47,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
|
||||
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
const auto CreateInformation = &pMessage->CreateObject;
|
||||
|
||||
LockConsole();
|
||||
const auto lock = LockConsole();
|
||||
|
||||
// If a generic object was requested, use the desired access to determine which type of object the caller is expecting.
|
||||
if (CreateInformation->ObjectType == CD_IO_OBJECT_TYPE_GENERIC)
|
||||
@@ -92,7 +92,6 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
UnlockConsole();
|
||||
pMessage->SetReplyStatus(Status);
|
||||
return pMessage;
|
||||
}
|
||||
@@ -109,8 +108,6 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
|
||||
handle.release();
|
||||
}
|
||||
|
||||
UnlockConsole();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -122,12 +119,11 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
|
||||
// - A pointer to the reply message.
|
||||
PCONSOLE_API_MSG IoDispatchers::ConsoleCloseObject(_In_ PCONSOLE_API_MSG pMessage)
|
||||
{
|
||||
LockConsole();
|
||||
const auto lock = LockConsole();
|
||||
|
||||
delete pMessage->GetObjectHandle();
|
||||
pMessage->SetReplyStatus(STATUS_SUCCESS);
|
||||
|
||||
UnlockConsole();
|
||||
return pMessage;
|
||||
}
|
||||
|
||||
@@ -401,8 +397,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
|
||||
ConsoleProcessHandle* ProcessData = nullptr;
|
||||
NTSTATUS Status;
|
||||
|
||||
LockConsole();
|
||||
|
||||
const auto lock = LockConsole();
|
||||
const auto cleanup = wil::scope_exit([&]() noexcept {
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -413,9 +408,6 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
|
||||
gci.ProcessHandleList.FreeProcessData(ProcessData);
|
||||
}
|
||||
}
|
||||
|
||||
// FreeProcessData() above requires the console to be locked.
|
||||
UnlockConsole();
|
||||
});
|
||||
|
||||
const auto dwProcessId = (DWORD)pReceiveMsg->Descriptor.Process;
|
||||
|
||||
@@ -14,8 +14,9 @@ Author(s):
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "inc/viewport.hpp"
|
||||
#include <til/ticket_lock.h>
|
||||
#include "../renderer/inc/FontInfo.hpp"
|
||||
#include "inc/viewport.hpp"
|
||||
|
||||
class TextBuffer;
|
||||
|
||||
@@ -41,8 +42,7 @@ namespace Microsoft::Console::Types
|
||||
|
||||
virtual std::vector<Microsoft::Console::Types::Viewport> GetSelectionRects() noexcept = 0;
|
||||
|
||||
virtual void LockConsole() noexcept = 0;
|
||||
virtual void UnlockConsole() noexcept = 0;
|
||||
virtual [[nodiscard]] std::unique_lock<til::ticket_lock> LockConsole() noexcept = 0;
|
||||
};
|
||||
|
||||
// See docs/virtual-dtors.md for an explanation of why this is weird.
|
||||
|
||||
@@ -223,10 +223,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// make a safe array
|
||||
@@ -273,10 +270,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_mayben
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// make a safe array
|
||||
@@ -379,15 +373,3 @@ Viewport ScreenInfoUiaProviderBase::_getViewport() const noexcept
|
||||
{
|
||||
return _pData->GetViewport();
|
||||
}
|
||||
|
||||
void ScreenInfoUiaProviderBase::_LockConsole() noexcept
|
||||
{
|
||||
// TODO GitHub #2141: Lock and Unlock in conhost should decouple Ctrl+C dispatch and use smarter handling
|
||||
_pData->LockConsole();
|
||||
}
|
||||
|
||||
void ScreenInfoUiaProviderBase::_UnlockConsole() noexcept
|
||||
{
|
||||
// TODO GitHub #2141: Lock and Unlock in conhost should decouple Ctrl+C dispatch and use smarter handling
|
||||
_pData->UnlockConsole();
|
||||
}
|
||||
|
||||
@@ -126,7 +126,5 @@ namespace Microsoft::Console::Types
|
||||
til::size _getScreenBufferCoords() const noexcept;
|
||||
const TextBuffer& _getTextBuffer() const noexcept;
|
||||
Viewport _getViewport() const noexcept;
|
||||
void _LockConsole() noexcept;
|
||||
void _UnlockConsole() noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -202,10 +202,7 @@ bool UiaTextRangeBase::IsDegenerate() const noexcept
|
||||
|
||||
IFACEMETHODIMP UiaTextRangeBase::Compare(_In_opt_ ITextRangeProvider* pRange, _Out_ BOOL* pRetVal) noexcept
|
||||
{
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
*pRetVal = FALSE;
|
||||
@@ -229,10 +226,7 @@ try
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pRetVal);
|
||||
*pRetVal = 0;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// get the text range that we're comparing to
|
||||
@@ -261,10 +255,7 @@ CATCH_RETURN();
|
||||
|
||||
IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) noexcept
|
||||
{
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
try
|
||||
@@ -451,10 +442,7 @@ try
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// AttributeIDs that require special handling
|
||||
@@ -619,10 +607,7 @@ try
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const std::wstring queryText{ text, SysStringLen(text) };
|
||||
@@ -750,10 +735,7 @@ try
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
VariantInit(pRetVal);
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// AttributeIDs that require special handling
|
||||
@@ -847,10 +829,7 @@ IFACEMETHODIMP UiaTextRangeBase::GetBoundingRectangles(_Outptr_result_maybenull_
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
try
|
||||
@@ -958,14 +937,12 @@ try
|
||||
RETURN_HR_IF(E_INVALIDARG, maxLength < -1);
|
||||
*pRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const auto text = _getTextValue(maxLength);
|
||||
Unlock.reset();
|
||||
std::wstring text;
|
||||
{
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
text = _getTextValue(maxLength);
|
||||
}
|
||||
|
||||
*pRetVal = SysAllocString(text.c_str());
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, *pRetVal);
|
||||
@@ -1030,10 +1007,7 @@ try
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
*pRetVal = 0;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// We can abstract this movement by moving _start
|
||||
@@ -1098,10 +1072,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
*pRetVal = 0;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
RETURN_HR_IF(S_OK, count == 0);
|
||||
|
||||
@@ -1155,10 +1126,7 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByRange(_In_ TextPatternRangeEndpoi
|
||||
_In_ TextPatternRangeEndpoint targetEndpoint) noexcept
|
||||
try
|
||||
{
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
|
||||
const UiaTextRangeBase* range = static_cast<UiaTextRangeBase*>(pTargetRange);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, range);
|
||||
@@ -1182,10 +1150,7 @@ CATCH_RETURN();
|
||||
IFACEMETHODIMP UiaTextRangeBase::Select() noexcept
|
||||
try
|
||||
{
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto lock = _pData->LockConsole();
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
if (IsDegenerate())
|
||||
@@ -1224,70 +1189,69 @@ IFACEMETHODIMP UiaTextRangeBase::RemoveFromSelection() noexcept
|
||||
IFACEMETHODIMP UiaTextRangeBase::ScrollIntoView(_In_ BOOL alignToTop) noexcept
|
||||
try
|
||||
{
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
const auto lock = _pData->LockConsole();
|
||||
|
||||
const auto oldViewport = _pData->GetViewport().ToInclusive();
|
||||
const auto viewportHeight = _getViewportHeight(oldViewport);
|
||||
// range rows
|
||||
const auto startScreenInfoRow = _start.Y;
|
||||
const auto endScreenInfoRow = _end.Y;
|
||||
// screen buffer rows
|
||||
const til::CoordType topRow = 0;
|
||||
const auto bottomRow = _pData->GetTextBuffer().TotalRowCount() - 1;
|
||||
|
||||
auto newViewport = oldViewport;
|
||||
|
||||
// there's a bunch of +1/-1s here for setting the viewport. These
|
||||
// are to account for the inclusivity of the viewport boundaries.
|
||||
if (alignToTop)
|
||||
til::inclusive_rect newViewport;
|
||||
{
|
||||
// determine if we can align the start row to the top
|
||||
if (startScreenInfoRow + viewportHeight <= bottomRow)
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const auto oldViewport = _pData->GetViewport().ToInclusive();
|
||||
const auto viewportHeight = _getViewportHeight(oldViewport);
|
||||
// range rows
|
||||
const auto startScreenInfoRow = _start.Y;
|
||||
const auto endScreenInfoRow = _end.Y;
|
||||
// screen buffer rows
|
||||
const til::CoordType topRow = 0;
|
||||
const auto bottomRow = _pData->GetTextBuffer().TotalRowCount() - 1;
|
||||
|
||||
newViewport = oldViewport;
|
||||
|
||||
// there's a bunch of +1/-1s here for setting the viewport. These
|
||||
// are to account for the inclusivity of the viewport boundaries.
|
||||
if (alignToTop)
|
||||
{
|
||||
// we can align to the top
|
||||
newViewport.Top = startScreenInfoRow;
|
||||
newViewport.Bottom = startScreenInfoRow + viewportHeight - 1;
|
||||
// determine if we can align the start row to the top
|
||||
if (startScreenInfoRow + viewportHeight <= bottomRow)
|
||||
{
|
||||
// we can align to the top
|
||||
newViewport.Top = startScreenInfoRow;
|
||||
newViewport.Bottom = startScreenInfoRow + viewportHeight - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't align to the top so we'll just move the viewport
|
||||
// to the bottom of the screen buffer
|
||||
newViewport.Bottom = bottomRow;
|
||||
newViewport.Top = bottomRow - viewportHeight + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't align to the top so we'll just move the viewport
|
||||
// to the bottom of the screen buffer
|
||||
newViewport.Bottom = bottomRow;
|
||||
newViewport.Top = bottomRow - viewportHeight + 1;
|
||||
// we need to align to the bottom
|
||||
// check if we can align to the bottom
|
||||
if (endScreenInfoRow >= viewportHeight)
|
||||
{
|
||||
// GH#7839: endScreenInfoRow may be ExclusiveEnd
|
||||
// ExclusiveEnd is past the bottomRow
|
||||
// so we need to clamp to the bottom row to stay in bounds
|
||||
|
||||
// we can align to bottom
|
||||
newViewport.Bottom = std::min(endScreenInfoRow, bottomRow);
|
||||
newViewport.Top = newViewport.Bottom - viewportHeight + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't align to bottom so we'll move the viewport to
|
||||
// the top of the screen buffer
|
||||
newViewport.Top = topRow;
|
||||
newViewport.Bottom = topRow + viewportHeight - 1;
|
||||
}
|
||||
}
|
||||
|
||||
assert(newViewport.Top >= topRow);
|
||||
assert(newViewport.Bottom <= bottomRow);
|
||||
assert(_getViewportHeight(oldViewport) == _getViewportHeight(newViewport));
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to align to the bottom
|
||||
// check if we can align to the bottom
|
||||
if (endScreenInfoRow >= viewportHeight)
|
||||
{
|
||||
// GH#7839: endScreenInfoRow may be ExclusiveEnd
|
||||
// ExclusiveEnd is past the bottomRow
|
||||
// so we need to clamp to the bottom row to stay in bounds
|
||||
|
||||
// we can align to bottom
|
||||
newViewport.Bottom = std::min(endScreenInfoRow, bottomRow);
|
||||
newViewport.Top = newViewport.Bottom - viewportHeight + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't align to bottom so we'll move the viewport to
|
||||
// the top of the screen buffer
|
||||
newViewport.Top = topRow;
|
||||
newViewport.Bottom = topRow + viewportHeight - 1;
|
||||
}
|
||||
}
|
||||
|
||||
assert(newViewport.Top >= topRow);
|
||||
assert(newViewport.Bottom <= bottomRow);
|
||||
assert(_getViewportHeight(oldViewport) == _getViewportHeight(newViewport));
|
||||
|
||||
Unlock.reset();
|
||||
|
||||
const gsl::not_null<ScreenInfoUiaProviderBase*> provider = static_cast<ScreenInfoUiaProviderBase*>(_pProvider);
|
||||
provider->ChangeViewport(newViewport);
|
||||
|
||||
Reference in New Issue
Block a user