diff --git a/README.md b/README.md index dce014def..26e87403b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ This is useful for: - Writing a terminal emulator (eg. via [xterm.js](https://github.com/sourcelair/xterm.js)). - Getting certain programs to *think* you're a terminal, such as when you need a program to send you control sequences. -`node-pty` supports Linux, macOS and Windows. Windows support is possible by utilizing the [Windows conpty API](https://blogs.msdn.microsoft.com/commandline/2018/08/02/windows-command-line-introducing-the-windows-pseudo-console-conpty/) on Windows 1809+ and the [winpty](https://github.com/rprichard/winpty) library in older version. +`node-pty` supports Linux, macOS and Windows. Windows support is possible by utilizing the [Windows conpty API](https://blogs.msdn.microsoft.com/commandline/2018/08/02/windows-command-line-introducing-the-windows-pseudo-console-conpty/) on Windows 1809+. + +> **Note:** Support for the `winpty` library has been removed. Windows 10 version 1809 (build 18309) or later is now required. ## API @@ -150,10 +152,6 @@ By default `PAUSE` and `RESUME` are XON/XOFF control codes (as shown above). To This happens when PowerShell is launched with no `SystemRoot` environment variable present. -### ConnectNamedPipe failed: Windows error 232 - -This error can occur due to anti-virus software intercepting winpty from creating a pty. To workaround this you can exclude this file from your anti-virus scanning `node-pty\build\Release\winpty-agent.exe` - ## pty.js This project is forked from [chjj/pty.js](https://github.com/chjj/pty.js) with the primary goals being to provide better support for later Node.js versions and Windows. diff --git a/binding.gyp b/binding.gyp index ac745a626..c6d410256 100644 --- a/binding.gyp +++ b/binding.gyp @@ -48,26 +48,6 @@ 'sources' : [ 'src/win/conpty_console_list.cc' ], - }, - { - 'target_name': 'pty', - 'include_dirs' : [ - ' on the -# command-line to override the default. - -.SECONDEXPANSION : - -.PHONY : default -default : all - -PREFIX := /usr/local -UNIX_ADAPTER_EXE := winpty.exe -MINGW_ENABLE_CXX11_FLAG := -std=c++11 -USE_PCH := 1 - -COMMON_CXXFLAGS := -UNIX_CXXFLAGS := -MINGW_CXXFLAGS := -MINGW_LDFLAGS := -UNIX_LDFLAGS := - -# Include config.mk but complain if it hasn't been created yet. -ifeq "$(wildcard config.mk)" "" - $(error config.mk does not exist. Please run ./configure) -endif -include config.mk - -COMMON_CXXFLAGS += \ - -MMD -Wall \ - -DUNICODE \ - -D_UNICODE \ - -D_WIN32_WINNT=0x0501 \ - -Ibuild/gen - -UNIX_CXXFLAGS += \ - $(COMMON_CXXFLAGS) - -MINGW_CXXFLAGS += \ - $(COMMON_CXXFLAGS) \ - -O2 \ - $(MINGW_ENABLE_CXX11_FLAG) - -MINGW_LDFLAGS += -static -static-libgcc -static-libstdc++ -UNIX_LDFLAGS += $(UNIX_LDFLAGS_STATIC) - -ifeq "$(USE_PCH)" "1" -MINGW_CXXFLAGS += -include build/mingw/PrecompiledHeader.h -PCH_DEP := build/mingw/PrecompiledHeader.h.gch -else -PCH_DEP := -endif - -build/gen/GenVersion.h : VERSION.txt $(COMMIT_HASH_DEP) | $$(@D)/.mkdir - $(info Updating build/gen/GenVersion.h) - @echo "const char GenVersion_Version[] = \"$(shell cat VERSION.txt | tr -d '\r\n')\";" > build/gen/GenVersion.h - @echo "const char GenVersion_Commit[] = \"$(COMMIT_HASH)\";" >> build/gen/GenVersion.h - -build/mingw/PrecompiledHeader.h : src/shared/PrecompiledHeader.h | $$(@D)/.mkdir - $(info Copying $< to $@) - @cp $< $@ - -build/mingw/PrecompiledHeader.h.gch : build/mingw/PrecompiledHeader.h | $$(@D)/.mkdir - $(info Compiling $<) - @$(MINGW_CXX) $(MINGW_CXXFLAGS) -c -o $@ $< - --include build/mingw/PrecompiledHeader.h.d - -define def_unix_target -build/$1/%.o : src/%.cc | $$$$(@D)/.mkdir - $$(info Compiling $$<) - @$$(UNIX_CXX) $$(UNIX_CXXFLAGS) $2 -I src/include -c -o $$@ $$< -endef - -define def_mingw_target -build/$1/%.o : src/%.cc $$(PCH_DEP) | $$$$(@D)/.mkdir - $$(info Compiling $$<) - @$$(MINGW_CXX) $$(MINGW_CXXFLAGS) $2 -I src/include -c -o $$@ $$< -endef - -include src/subdir.mk - -.PHONY : all -all : $(ALL_TARGETS) - -.PHONY : tests -tests : $(TEST_PROGRAMS) - -.PHONY : install-bin -install-bin : all - mkdir -p $(PREFIX)/bin - install -m 755 -p -s build/$(UNIX_ADAPTER_EXE) $(PREFIX)/bin - install -m 755 -p -s build/winpty.dll $(PREFIX)/bin - install -m 755 -p -s build/winpty-agent.exe $(PREFIX)/bin - -.PHONY : install-debugserver -install-debugserver : all - mkdir -p $(PREFIX)/bin - install -m 755 -p -s build/winpty-debugserver.exe $(PREFIX)/bin - -.PHONY : install-lib -install-lib : all - mkdir -p $(PREFIX)/lib - install -m 644 -p build/winpty.lib $(PREFIX)/lib - -.PHONY : install-doc -install-doc : - mkdir -p $(PREFIX)/share/doc/winpty - install -m 644 -p LICENSE $(PREFIX)/share/doc/winpty - install -m 644 -p README.md $(PREFIX)/share/doc/winpty - install -m 644 -p RELEASES.md $(PREFIX)/share/doc/winpty - -.PHONY : install-include -install-include : - mkdir -p $(PREFIX)/include/winpty - install -m 644 -p src/include/winpty.h $(PREFIX)/include/winpty - install -m 644 -p src/include/winpty_constants.h $(PREFIX)/include/winpty - -.PHONY : install -install : \ - install-bin \ - install-debugserver \ - install-lib \ - install-doc \ - install-include - -.PHONY : clean -clean : - rm -fr build - -.PHONY : clean-msvc -clean-msvc : - rm -fr src/Default src/Release src/.vs src/gen - rm -f src/*.vcxproj src/*.vcxproj.filters src/*.sln src/*.sdf - -.PHONY : distclean -distclean : clean - rm -f config.mk - -.PRECIOUS : %.mkdir -%.mkdir : - $(info Creating directory $(dir $@)) - @mkdir -p $(dir $@) - @touch $@ - -src/%.h : - @echo "Missing header file $@ (stale dependency file?)" diff --git a/deps/winpty/README.md b/deps/winpty/README.md deleted file mode 100644 index a6520fc35..000000000 --- a/deps/winpty/README.md +++ /dev/null @@ -1,151 +0,0 @@ -# winpty - -[![Build Status](https://tea-ci.org/api/badges/rprichard/winpty/status.svg)](https://tea-ci.org/rprichard/winpty) - -winpty is a Windows software package providing an interface similar to a Unix -pty-master for communicating with Windows console programs. The package -consists of a library (libwinpty) and a tool for Cygwin and MSYS for running -Windows console programs in a Cygwin/MSYS pty. - -The software works by starting the `winpty-agent.exe` process with a new, -hidden console window, which bridges between the console API and terminal -input/output escape codes. It polls the hidden console's screen buffer for -changes and generates a corresponding stream of output. - -The Unix adapter allows running Windows console programs (e.g. CMD, PowerShell, -IronPython, etc.) under `mintty` or Cygwin's `sshd` with -properly-functioning input (e.g. arrow and function keys) and output (e.g. line -buffering). The library could be also useful for writing a non-Cygwin SSH -server. - -## Supported Windows versions - -winpty runs on Windows XP through Windows 10, including server versions. It -can be compiled into either 32-bit or 64-bit binaries. - -## Cygwin/MSYS adapter (`winpty.exe`) - -### Prerequisites - -You need the following to build winpty: - -* A Cygwin or MSYS installation -* GNU make -* A MinGW g++ toolchain capable of compiling C++11 code to build `winpty.dll` - and `winpty-agent.exe` -* A g++ toolchain targeting Cygwin or MSYS to build `winpty.exe` - -Winpty requires two g++ toolchains as it is split into two parts. The -`winpty.dll` and `winpty-agent.exe` binaries interface with the native -Windows command prompt window so they are compiled with the native MinGW -toolchain. The `winpty.exe` binary interfaces with the MSYS/Cygwin terminal so -it is compiled with the MSYS/Cygwin toolchain. - -MinGW appears to be split into two distributions -- MinGW (creates 32-bit -binaries) and MinGW-w64 (creates both 32-bit and 64-bit binaries). Either -one is generally acceptable. - -#### Cygwin packages - -The default g++ compiler for Cygwin targets Cygwin itself, but Cygwin also -packages MinGW-w64 compilers. As of this writing, the necessary packages are: - -* Either `mingw64-i686-gcc-g++` or `mingw64-x86_64-gcc-g++`. Select the - appropriate compiler for your CPU architecture. -* `gcc-g++` -* `make` - -As of this writing (2016-01-23), only the MinGW-w64 compiler is acceptable. -The MinGW compiler (e.g. from the `mingw-gcc-g++` package) is no longer -maintained and is too buggy. - -#### MSYS packages - -For the original MSYS, use the `mingw-get` tool (MinGW Installation Manager), -and select at least these components: - -* `mingw-developer-toolkit` -* `mingw32-base` -* `mingw32-gcc-g++` -* `msys-base` -* `msys-system-builder` - -When running `./configure`, make sure that `mingw32-g++` is in your -`PATH`. It will be in the `C:\MinGW\bin` directory. - -#### MSYS2 packages - -For MSYS2, use `pacman` and install at least these packages: - -* `msys/gcc` -* `mingw32/mingw-w64-i686-gcc` or `mingw64/mingw-w64-x86_64-gcc`. Select - the appropriate compiler for your CPU architecture. -* `make` - -MSYS2 provides three start menu shortcuts for starting MSYS2: - -* MinGW-w64 Win32 Shell -* MinGW-w64 Win64 Shell -* MSYS2 Shell - -To build winpty, use the MinGW-w64 {Win32,Win64} shortcut of the architecture -matching MSYS2. These shortcuts will put the g++ compiler from the -`{mingw32,mingw64}/mingw-w64-{i686,x86_64}-gcc` packages into the `PATH`. - -Alternatively, instead of installing `mingw32/mingw-w64-i686-gcc` or -`mingw64/mingw-w64-x86_64-gcc`, install the `mingw-w64-cross-gcc` and -`mingw-w64-cross-crt-git` packages. These packages install cross-compilers -into `/opt/bin`, and then any of the three shortcuts will work. - -### Building the Unix adapter - -In the project directory, run `./configure`, then `make`, then `make install`. -By default, winpty is installed into `/usr/local`. Pass `PREFIX=` to -`make install` to override this default. - -### Using the Unix adapter - -To run a Windows console program in `mintty` or Cygwin `sshd`, prepend -`winpty` to the command-line: - - $ winpty powershell - Windows PowerShell - Copyright (C) 2009 Microsoft Corporation. All rights reserved. - - PS C:\rprichard\proj\winpty> 10 + 20 - 30 - PS C:\rprichard\proj\winpty> exit - -## Embedding winpty / MSVC compilation - -See `src/include/winpty.h` for the prototypes of functions exported by -`winpty.dll`. - -Only the `winpty.exe` binary uses Cygwin; all the other binaries work without -it and can be compiled with either MinGW or MSVC. To compile using MSVC, -download gyp and run `gyp -I configurations.gypi` in the `src` subdirectory. -This will generate a `winpty.sln` and associated project files. See the -`src/winpty.gyp` and `src/configurations.gypi` files for notes on dealing with -MSVC versions and different architectures. - -Compiling winpty with MSVC currently requires MSVC 2013 or newer. - -## Debugging winpty - -winpty comes with a tool for collecting timestamped debugging output. To use -it: - -1. Run `winpty-debugserver.exe` on the same computer as winpty. -2. Set the `WINPTY_DEBUG` environment variable to `trace` for the - `winpty.exe` process and/or the process using `libwinpty.dll`. - -winpty also recognizes a `WINPTY_SHOW_CONSOLE` environment variable. Set it -to 1 to prevent winpty from hiding the console window. - -## Copyright - -This project is distributed under the MIT license (see the `LICENSE` file in -the project root). - -By submitting a pull request for this project, you agree to license your -contribution under the MIT license to this project. diff --git a/deps/winpty/RELEASES.md b/deps/winpty/RELEASES.md deleted file mode 100644 index 768cdf90e..000000000 --- a/deps/winpty/RELEASES.md +++ /dev/null @@ -1,280 +0,0 @@ -# Next Version - -Input handling changes: - - * Improve Ctrl-C handling with programs that use unprocessed input. (e.g. - Ctrl-C now cancels input with PowerShell on Windows 10.) - [#116](https://github.com/rprichard/winpty/issues/116) - * Fix a theoretical issue with input event ordering. - [#117](https://github.com/rprichard/winpty/issues/117) - * Ctrl/Shift+{Arrow,Home,End} keys now work with IntelliJ. - [#118](https://github.com/rprichard/winpty/issues/118) - -# Version 0.4.3 (2017-05-17) - -Input handling changes: - - * winpty sets `ENHANCED_KEY` for arrow and navigation keys. This fixes an - issue with the Ruby REPL. - [#99](https://github.com/rprichard/winpty/issues/99) - * AltGr keys are handled better now. - [#109](https://github.com/rprichard/winpty/issues/109) - * In `ENABLE_VIRTUAL_TERMINAL_INPUT` mode, when typing Home/End with a - modifier (e.g. Ctrl), winpty now generates an H/F escape sequence like - `^[[1;5F` rather than a 1/4 escape like `^[[4;5~`. - [#114](https://github.com/rprichard/winpty/issues/114) - -Resizing and scraping fixes: - - * winpty now synthesizes a `WINDOW_BUFFER_SIZE_EVENT` event after resizing - the console to better propagate window size changes to console programs. - In particular, this affects WSL and Cygwin. - [#110](https://github.com/rprichard/winpty/issues/110) - * Better handling of resizing for certain full-screen programs, like - WSL less. - [#112](https://github.com/rprichard/winpty/issues/112) - * Hide the cursor if it's currently outside the console window. This change - fixes an issue with Far Manager. - [#113](https://github.com/rprichard/winpty/issues/113) - * winpty now avoids using console fonts smaller than 5px high to improve - half-vs-full-width character handling. See - https://github.com/Microsoft/vscode/issues/19665. - [b4db322010](https://github.com/rprichard/winpty/commit/b4db322010d2d897e6c496fefc4f0ecc9b84c2f3) - -Cygwin/MSYS adapter fix: - - * The way the `winpty` Cygwin/MSYS2 adapter searches for the program to - launch changed. It now resolves symlinks and searches the PATH explicitly. - [#81](https://github.com/rprichard/winpty/issues/81) - [#98](https://github.com/rprichard/winpty/issues/98) - -This release does not include binaries for the old MSYS1 project anymore. -MSYS2 will continue to be supported. See -https://github.com/rprichard/winpty/issues/97. - -# Version 0.4.2 (2017-01-18) - -This release improves WSL support (i.e. Bash-on-Windows): - - * winpty generates more correct input escape sequences for WSL programs that - enable an alternate input mode using DECCKM. This bug affected arrow keys - and Home/End in WSL programs such as `vim`, `mc`, and `less`. - [#90](https://github.com/rprichard/winpty/issues/90) - * winpty now recognizes the `COMMON_LVB_REVERSE_VIDEO` and - `COMMON_LVB_UNDERSCORE` text attributes. The Windows console uses these - attributes to implement the SGR.4(Underline) and SGR.7(Negative) modes in - its VT handling. This change affects WSL pager status bars, man pages, etc. - -The build system no longer has a "version suffix" mechanism, so passing -`VERSION_SUFFIX=` to make or `-D VERSION_SUFFIX=` to gyp now -has no effect. AFAIK, the mechanism was never used publicly. -[67a34b6c03](https://github.com/rprichard/winpty/commit/67a34b6c03557a5c2e0a2bdd502c2210921d8f3e) - -# Version 0.4.1 (2017-01-03) - -Bug fixes: - - * This version fixes a bug where the `winpty-agent.exe` process could read - past the end of a buffer. - [#94](https://github.com/rprichard/winpty/issues/94) - -# Version 0.4.0 (2016-06-28) - -The winpty library has a new API that should be easier for embedding. -[880c00c69e](https://github.com/rprichard/winpty/commit/880c00c69eeca73643ddb576f02c5badbec81f56) - -User-visible changes: - - * winpty now automatically puts the terminal into mouse mode when it detects - that the console has left QuickEdit mode. The `--mouse` option still forces - the terminal into mouse mode. In principle, an option could be added to - suppress terminal mode, but hopefully it won't be necessary. There is a - script in the `misc` subdirectory, `misc/ConinMode.ps1`, that can change - the QuickEdit mode from the command-line. - * winpty now passes keyboard escapes to `bash.exe` in the Windows Subsystem - for Linux. - [#82](https://github.com/rprichard/winpty/issues/82) - -Bug fixes: - - * By default, `winpty.dll` avoids calling `SetProcessWindowStation` within - the calling process. - [#58](https://github.com/rprichard/winpty/issues/58) - * Fixed an uninitialized memory bug that could have crashed winpty. - [#80](https://github.com/rprichard/winpty/issues/80) - * winpty now works better with very large and very small terminal windows. - It resizes the console font according to the number of columns. - [#61](https://github.com/rprichard/winpty/issues/61) - * winpty no longer uses Mark to freeze the console on Windows 10. The Mark - command could interfere with the cursor position, corrupting the data in - the screen buffer. - [#79](https://github.com/rprichard/winpty/issues/79) - -# Version 0.3.0 (2016-05-20) - -User-visible changes: - - * The UNIX adapter is renamed from `console.exe` to `winpty.exe` to be - consistent with MSYS2. The name `winpty.exe` is less likely to conflict - with another program and is easier to search for online (e.g. for someone - unfamiliar with winpty). - * The UNIX adapter now clears the `TERM` variable. - [#43](https://github.com/rprichard/winpty/issues/43) - * An escape character appearing in a console screen buffer cell is converted - to a '?'. - [#47](https://github.com/rprichard/winpty/issues/47) - -Bug fixes: - - * A major bug affecting XP users was fixed. - [#67](https://github.com/rprichard/winpty/issues/67) - * Fixed an incompatibility with ConEmu where winpty hung if ConEmu's - "Process 'start'" feature was enabled. - [#70](https://github.com/rprichard/winpty/issues/70) - * Fixed a bug where `cmd.exe` sometimes printed the message, - `Not enough storage is available to process this command.`. - [#74](https://github.com/rprichard/winpty/issues/74) - -Many changes internally: - - * The codebase is switched from C++03 to C++11 and uses exceptions internally. - No exceptions are thrown across the C APIs defined in `winpty.h`. - * This version drops support for the original MinGW compiler packaged with - Cygwin (`i686-pc-mingw32-g++`). The MinGW-w64 compiler is still supported, - as is the MinGW distributed at mingw.org. Compiling with MSVC now requires - MSVC 2013 or newer. Windows XP is still supported. - [ec3eae8df5](https://github.com/rprichard/winpty/commit/ec3eae8df5bbbb36d7628d168b0815638d122f37) - * Pipe security is improved. winpty works harder to produce unique pipe names - and includes a random component in the name. winpty secures pipes with a - DACL that prevents arbitrary users from connecting to its pipes. winpty now - passes `PIPE_REJECT_REMOTE_CLIENTS` on Vista and up, and it verifies that - the pipe client PID is correct, again on Vista and up. When connecting to a - named pipe, winpty uses the `SECURITY_IDENTIFICATION` flag to restrict - impersonation. Previous versions *should* still be secure. - * `winpty-debugserver.exe` now has an `--everyone` flag that allows capturing - debug output from other users. - * The code now compiles cleanly with MSVC's "Security Development Lifecycle" - (`/SDL`) checks enabled. - -# Version 0.2.2 (2016-02-25) - -Minor bug fixes and enhancements: - - * Fix a bug that generated spurious mouse input records when an incomplete - mouse escape sequence was seen. - * Fix a buffer overflow bug in `winpty-debugserver.exe` affecting messages of - exactly 4096 bytes. - * For MSVC builds, add a `src/configurations.gypi` file that can be included - on the gyp command-line to enable 32-bit and 64-bit builds. - * `winpty-agent --show-input` mode: Flush stdout after each line. - * Makefile builds: generate a `build/winpty.lib` import library to accompany - `build/winpty.dll`. - -# Version 0.2.1 (2015-12-19) - - * The main project source was moved into a `src` directory for better code - organization and to fix - [#51](https://github.com/rprichard/winpty/issues/51). - * winpty recognizes many more escape sequences, including: - * putty/rxvt's F1-F4 keys - [#40](https://github.com/rprichard/winpty/issues/40) - * the Linux virtual console's F1-F5 keys - * the "application numpad" keys (e.g. enabled with DECPAM) - * Fixed handling of Shift-Alt-O and Alt-[. - * Added support for mouse input. The UNIX adapter has a `--mouse` argument - that puts the terminal into mouse mode, but the agent recognizes mouse - input even without the argument. The agent recognizes double-clicks using - Windows' double-click interval setting (i.e. GetDoubleClickTime). - [#57](https://github.com/rprichard/winpty/issues/57) - -Changes to debugging interfaces: - - * The `WINPTY_DEBUG` variable is now a comma-separated list. The old - behavior (i.e. tracing) is enabled with `WINPTY_DEBUG=trace`. - * The UNIX adapter program now has a `--showkey` argument that dumps input - bytes. - * The `winpty-agent.exe` program has a `--show-input` argument that dumps - `INPUT_RECORD` records. (It omits mouse events unless `--with-mouse` is - also specified.) The agent also responds to `WINPTY_DEBUG=trace,input`, - which logs input bytes and synthesized console events, and it responds to - `WINPTY_DEBUG=trace,dump_input_map`, which dumps the internal table of - escape sequences. - -# Version 0.2.0 (2015-11-13) - -No changes to the API, but many small changes to the implementation. The big -changes include: - - * Support for 64-bit Cygwin and MSYS2 - * Support for Windows 10 - * Better Unicode support (especially East Asian languages) - -Details: - - * The `configure` script recognizes 64-bit Cygwin and MSYS2 environments and - selects the appropriate compiler. - * winpty works much better with the upgraded console in Windows 10. The - `conhost.exe` hang can still occur, but only with certain programs, and - is much less likely to occur. With the new console, use Mark instead of - SelectAll, for better performance. - [#31](https://github.com/rprichard/winpty/issues/31) - [#30](https://github.com/rprichard/winpty/issues/30) - [#53](https://github.com/rprichard/winpty/issues/53) - * The UNIX adapter now calls `setlocale(LC_ALL, "")` to set the locale. - * Improved Unicode support. When a console is started with an East Asian code - page, winpty now chooses an East Asian font rather than Consolas / Lucida - Console. Selecting the right font helps synchronize character widths - between the console and terminal. (It's not perfect, though.) - [#41](https://github.com/rprichard/winpty/issues/41) - * winpty now more-or-less works with programs that change the screen buffer - or resize the original screen buffer. If the screen buffer height changes, - winpty switches to a "direct mode", where it makes no effort to track - scrolling. In direct mode, it merely syncs snapshots of the console to the - terminal. Caveats: - * Changing the screen buffer (i.e. `SetConsoleActiveScreenBuffer`) - breaks winpty on Windows 7. This problem can eventually be mitigated, - but never completely fixed, due to Windows 7 bugginess. - * Resizing the original screen buffer can hang `conhost.exe` on Windows 10. - Enabling the legacy console is a workaround. - * If a program changes the screen buffer and then exits, relying on the OS - to restore the original screen buffer, that restoration probably will not - happen with winpty. winpty's behavior can probably be improved here. - * Improved color handling: - * DkGray-on-Black text was previously hiddenly completely. Now it is - output as DkGray, with a fallback to LtGray on terminals that don't - recognize the intense colors. - [#39](https://github.com/rprichard/winpty/issues/39). - * The console is always initialized to LtGray-on-Black, regardless of the - user setting, which matches the console color heuristic, which translates - LtGray-on-Black to "reset SGR parameters." - * Shift-Tab is recognized correctly now. - [#19](https://github.com/rprichard/winpty/issues/19) - * Add a `--version` argument to `winpty-agent.exe` and the UNIX adapter. The - argument reports the nominal version (i.e. the `VERSION.txt`) file, with a - "VERSION_SUFFIX" appended (defaulted to `-dev`), and a git commit hash, if - the `git` command successfully reports a hash during the build. The `git` - command is invoked by either `make` or `gyp`. - * The agent now combines `ReadConsoleOutputW` calls when it polls the console - buffer for changes, which may slightly reduce its CPU overhead. - [#44](https://github.com/rprichard/winpty/issues/44). - * A `gyp` file is added to help compile with MSVC. - * The code can now be compiled as C++11 code, though it isn't by default. - [bde8922e08](https://github.com/rprichard/winpty/commit/bde8922e08c3638e01ecc7b581b676c314163e3c) - * If winpty can't create a new window station, it charges ahead rather than - aborting. This situation might happen if winpty were started from an SSH - session. - * Debugging improvements: - * `WINPTYDBG` is renamed to `WINPTY_DEBUG`, and a new `WINPTY_SHOW_CONSOLE` - variable keeps the underlying console visible. - * A `winpty-debugserver.exe` program is built and shipped by default. It - collects the trace output enabled with `WINPTY_DEBUG`. - * The `Makefile` build of winpty now compiles `winpty-agent.exe` and - `winpty.dll` with -O2. - -# Version 0.1.1 (2012-07-28) - -Minor bugfix release. - -# Version 0.1 (2012-04-17) - -Initial release. diff --git a/deps/winpty/VERSION.txt b/deps/winpty/VERSION.txt deleted file mode 100644 index 5d47ff8c4..000000000 --- a/deps/winpty/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -0.4.4-dev diff --git a/deps/winpty/configure b/deps/winpty/configure deleted file mode 100644 index 6d37d65b0..000000000 --- a/deps/winpty/configure +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2011-2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# -# findTool(desc, commandList) -# -# Searches commandLine for the first command in the PATH and returns it. -# Prints an error and aborts the script if no match is found. -# -FINDTOOL_OUT="" -function findTool { - DESC=$1 - OPTIONS=$2 - for CMD in ${OPTIONS}; do - if (which $CMD &>/dev/null) then - echo "Found $DESC: $CMD" - FINDTOOL_OUT="$CMD" - return - fi - done - echo "Error: could not find $DESC. One of these should be in your PATH:" - for CMD in ${OPTIONS}; do - echo " * $CMD" - done - exit 1 -} - -IS_CYGWIN=0 -IS_MSYS1=0 -IS_MSYS2=0 - -# Link parts of the Cygwin binary statically to aid in redistribution? The -# binary still links dynamically against the main DLL. The MinGW binaries are -# also statically linked and therefore depend only on Windows DLLs. I started -# linking the Cygwin/MSYS binary statically, because G++ 4.7 changed the -# Windows C++ ABI. -UNIX_LDFLAGS_STATIC='-static -static-libgcc -static-libstdc++' - -# Detect the environment -- Cygwin or MSYS. -case $(uname -s) in - CYGWIN*) - echo 'uname -s identifies a Cygwin environment.' - IS_CYGWIN=1 - case $(uname -m) in - i686) - echo 'uname -m identifies an i686 environment.' - UNIX_CXX=i686-pc-cygwin-g++ - MINGW_CXX=i686-w64-mingw32-g++ - ;; - x86_64) - echo 'uname -m identifies an x86_64 environment.' - UNIX_CXX=x86_64-pc-cygwin-g++ - MINGW_CXX=x86_64-w64-mingw32-g++ - ;; - *) - echo 'Error: uname -m did not match either i686 or x86_64.' - exit 1 - ;; - esac - ;; - MSYS*|MINGW*) - # MSYS2 notes: - # - MSYS2 offers two shortcuts to open an environment: - # - MinGW-w64 Win32 Shell. This env reports a `uname -s` of - # MINGW32_NT-6.1 on 32-bit Win7. The MinGW-w64 compiler - # (i686-w64-mingw32-g++.exe) is in the PATH. - # - MSYS2 Shell. `uname -s` instead reports MSYS_NT-6.1. - # The i686-w64-mingw32-g++ compiler is not in the PATH. - # - MSYS2 appears to use MinGW-w64, not the older mingw.org. - # MSYS notes: - # - `uname -s` is always MINGW32_NT-6.1 on Win7. - echo 'uname -s identifies an MSYS/MSYS2 environment.' - case $(uname -m) in - i686) - echo 'uname -m identifies an i686 environment.' - UNIX_CXX=i686-pc-msys-g++ - if echo "$(uname -r)" | grep '^1[.]' > /dev/null; then - # The MSYS-targeting compiler for the original 32-bit-only - # MSYS does not recognize the -static-libstdc++ flag, and - # it does not work with -static, because it tries to link - # statically with the core MSYS library and fails. - # - # Distinguish between the two using the major version - # number of `uname -r`: - # - # MSYS uname -r: 1.0.18(0.48/3/2) - # MSYS2 uname -r: 2.0.0(0.284/5/3) - # - # This is suboptimal because MSYS2 is not actually the - # second version of MSYS--it's a brand-new fork of Cygwin. - # - IS_MSYS1=1 - UNIX_LDFLAGS_STATIC= - MINGW_CXX=mingw32-g++ - else - IS_MSYS2=1 - MINGW_CXX=i686-w64-mingw32-g++.exe - fi - ;; - x86_64) - echo 'uname -m identifies an x86_64 environment.' - IS_MSYS2=1 - UNIX_CXX=x86_64-pc-msys-g++ - MINGW_CXX=x86_64-w64-mingw32-g++ - ;; - *) - echo 'Error: uname -m did not match either i686 or x86_64.' - exit 1 - ;; - esac - ;; - *) - echo 'Error: uname -s did not match either CYGWIN* or MINGW*.' - exit 1 - ;; -esac - -# Search the PATH and pick the first match. -findTool "Cygwin/MSYS G++ compiler" "$UNIX_CXX" -UNIX_CXX=$FINDTOOL_OUT -findTool "MinGW G++ compiler" "$MINGW_CXX" -MINGW_CXX=$FINDTOOL_OUT - -# Write config files. -echo Writing config.mk -echo UNIX_CXX=$UNIX_CXX > config.mk -echo UNIX_LDFLAGS_STATIC=$UNIX_LDFLAGS_STATIC >> config.mk -echo MINGW_CXX=$MINGW_CXX >> config.mk - -if test $IS_MSYS1 = 1; then - echo UNIX_CXXFLAGS += -DWINPTY_TARGET_MSYS1 >> config.mk - # The MSYS1 MinGW compiler has a bug that prevents inclusion of algorithm - # and math.h in normal C++11 mode. The workaround is to enable the gnu++11 - # mode instead. The bug was fixed on 2015-07-31, but as of 2016-02-26, the - # fix apparently hasn't been released. See - # http://ehc.ac/p/mingw/bugs/2250/. - echo MINGW_ENABLE_CXX11_FLAG := -std=gnu++11 >> config.mk -fi - -if test -d .git -a -f .git/HEAD -a -f .git/index && git rev-parse HEAD >&/dev/null; then - echo "Commit info: git" - echo 'COMMIT_HASH = $(shell git rev-parse HEAD)' >> config.mk - echo 'COMMIT_HASH_DEP := config.mk .git/HEAD .git/index' >> config.mk -else - echo "Commit info: none" - echo 'COMMIT_HASH := none' >> config.mk - echo 'COMMIT_HASH_DEP := config.mk' >> config.mk -fi diff --git a/deps/winpty/misc/.gitignore b/deps/winpty/misc/.gitignore deleted file mode 100644 index 23751645f..000000000 --- a/deps/winpty/misc/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.exe -UnixEcho \ No newline at end of file diff --git a/deps/winpty/misc/BufferResizeTests.cc b/deps/winpty/misc/BufferResizeTests.cc deleted file mode 100644 index a5bb07482..000000000 --- a/deps/winpty/misc/BufferResizeTests.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include - -#include "TestUtil.cc" - -void dumpInfoToTrace() { - CONSOLE_SCREEN_BUFFER_INFO info; - assert(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info)); - trace("win=(%d,%d,%d,%d)", - (int)info.srWindow.Left, - (int)info.srWindow.Top, - (int)info.srWindow.Right, - (int)info.srWindow.Bottom); - trace("buf=(%d,%d)", - (int)info.dwSize.X, - (int)info.dwSize.Y); - trace("cur=(%d,%d)", - (int)info.dwCursorPosition.X, - (int)info.dwCursorPosition.Y); -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - setWindowPos(0, 0, 1, 1); - - if (false) { - // Reducing the buffer height can move the window up. - setBufferSize(80, 25); - setWindowPos(0, 20, 80, 5); - Sleep(2000); - setBufferSize(80, 10); - } - - if (false) { - // Reducing the buffer height moves the window up and the buffer - // contents up too. - setBufferSize(80, 25); - setWindowPos(0, 20, 80, 5); - setCursorPos(0, 20); - printf("TEST1\nTEST2\nTEST3\nTEST4\n"); - fflush(stdout); - Sleep(2000); - setBufferSize(80, 10); - } - - if (false) { - // Reducing the buffer width can move the window left. - setBufferSize(80, 25); - setWindowPos(40, 0, 40, 25); - Sleep(2000); - setBufferSize(60, 25); - } - - if (false) { - // Sometimes the buffer contents are shifted up; sometimes they're - // shifted down. It seems to depend on the cursor position? - - // setBufferSize(80, 25); - // setWindowPos(0, 20, 80, 5); - // setCursorPos(0, 20); - // printf("TESTa\nTESTb\nTESTc\nTESTd\nTESTe"); - // fflush(stdout); - // setCursorPos(0, 0); - // printf("TEST1\nTEST2\nTEST3\nTEST4\nTEST5"); - // fflush(stdout); - // setCursorPos(0, 24); - // Sleep(5000); - // setBufferSize(80, 24); - - setBufferSize(80, 20); - setWindowPos(0, 10, 80, 10); - setCursorPos(0, 18); - - printf("TEST1\nTEST2"); - fflush(stdout); - setCursorPos(0, 18); - - Sleep(2000); - setBufferSize(80, 18); - } - - dumpInfoToTrace(); - Sleep(30000); - - return 0; -} diff --git a/deps/winpty/misc/ChangeScreenBuffer.cc b/deps/winpty/misc/ChangeScreenBuffer.cc deleted file mode 100644 index 701a2cb4a..000000000 --- a/deps/winpty/misc/ChangeScreenBuffer.cc +++ /dev/null @@ -1,53 +0,0 @@ -// A test program for CreateConsoleScreenBuffer / SetConsoleActiveScreenBuffer -// - -#include -#include -#include -#include -#include - -#include "TestUtil.cc" - -int main() -{ - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE childBuffer = CreateConsoleScreenBuffer( - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CONSOLE_TEXTMODE_BUFFER, NULL); - - SetConsoleActiveScreenBuffer(childBuffer); - - while (true) { - char buf[1024]; - CONSOLE_SCREEN_BUFFER_INFO info; - - assert(GetConsoleScreenBufferInfo(origBuffer, &info)); - trace("child.size=(%d,%d)", (int)info.dwSize.X, (int)info.dwSize.Y); - trace("child.cursor=(%d,%d)", (int)info.dwCursorPosition.X, (int)info.dwCursorPosition.Y); - trace("child.window=(%d,%d,%d,%d)", - (int)info.srWindow.Left, (int)info.srWindow.Top, - (int)info.srWindow.Right, (int)info.srWindow.Bottom); - trace("child.maxSize=(%d,%d)", (int)info.dwMaximumWindowSize.X, (int)info.dwMaximumWindowSize.Y); - - int ch = getch(); - sprintf(buf, "%02x\n", ch); - DWORD actual = 0; - WriteFile(childBuffer, buf, strlen(buf), &actual, NULL); - if (ch == 0x1b/*ESC*/ || ch == 0x03/*CTRL-C*/) - break; - - if (ch == 'b') { - setBufferSize(origBuffer, 40, 25); - } else if (ch == 'w') { - setWindowPos(origBuffer, 1, 1, 38, 23); - } else if (ch == 'c') { - setCursorPos(origBuffer, 10, 10); - } - } - - SetConsoleActiveScreenBuffer(origBuffer); - - return 0; -} diff --git a/deps/winpty/misc/ClearConsole.cc b/deps/winpty/misc/ClearConsole.cc deleted file mode 100644 index f95f8c84c..000000000 --- a/deps/winpty/misc/ClearConsole.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Demonstrates that console clearing sets each cell's character to SP, not - * NUL, and it sets the attribute of each cell to the current text attribute. - * - * This confirms the MSDN instruction in the "Clearing the Screen" article. - * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682022(v=vs.85).aspx - * It advises using GetConsoleScreenBufferInfo to get the current text - * attribute, then FillConsoleOutputCharacter and FillConsoleOutputAttribute to - * write to the console buffer. - */ - -#include - -#include -#include -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - SetConsoleTextAttribute(conout, 0x24); - system("cls"); - - setWindowPos(0, 0, 1, 1); - setBufferSize(80, 25); - setWindowPos(0, 0, 80, 25); - - CHAR_INFO buf; - COORD bufSize = { 1, 1 }; - COORD bufCoord = { 0, 0 }; - SMALL_RECT rect = { 5, 5, 5, 5 }; - BOOL ret; - DWORD actual; - COORD writeCoord = { 5, 5 }; - - // After cls, each cell's character is a space, and its attributes are the - // default text attributes. - ret = ReadConsoleOutputW(conout, &buf, bufSize, bufCoord, &rect); - assert(ret && buf.Char.UnicodeChar == L' ' && buf.Attributes == 0x24); - - // Nevertheless, it is possible to change a cell to NUL. - ret = FillConsoleOutputCharacterW(conout, L'\0', 1, writeCoord, &actual); - assert(ret && actual == 1); - ret = ReadConsoleOutputW(conout, &buf, bufSize, bufCoord, &rect); - assert(ret && buf.Char.UnicodeChar == L'\0' && buf.Attributes == 0x24); - - // As well as a 0 attribute. (As one would expect, the cell is - // black-on-black.) - ret = FillConsoleOutputAttribute(conout, 0, 1, writeCoord, &actual); - assert(ret && actual == 1); - ret = ReadConsoleOutputW(conout, &buf, bufSize, bufCoord, &rect); - assert(ret && buf.Char.UnicodeChar == L'\0' && buf.Attributes == 0); - ret = FillConsoleOutputCharacterW(conout, L'X', 1, writeCoord, &actual); - assert(ret && actual == 1); - ret = ReadConsoleOutputW(conout, &buf, bufSize, bufCoord, &rect); - assert(ret && buf.Char.UnicodeChar == L'X' && buf.Attributes == 0); - - // The 'X' is invisible. - countDown(3); - - ret = FillConsoleOutputAttribute(conout, 0x42, 1, writeCoord, &actual); - assert(ret && actual == 1); - - countDown(5); -} diff --git a/deps/winpty/misc/ConinMode.cc b/deps/winpty/misc/ConinMode.cc deleted file mode 100644 index 1e1428d8b..000000000 --- a/deps/winpty/misc/ConinMode.cc +++ /dev/null @@ -1,117 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -static HANDLE getConin() { - HANDLE conin = GetStdHandle(STD_INPUT_HANDLE); - if (conin == INVALID_HANDLE_VALUE) { - fprintf(stderr, "error: cannot get stdin\n"); - exit(1); - } - return conin; -} - -static DWORD getConsoleMode() { - DWORD mode = 0; - if (!GetConsoleMode(getConin(), &mode)) { - fprintf(stderr, "error: GetConsoleMode failed (is stdin a console?)\n"); - exit(1); - } - return mode; -} - -static void setConsoleMode(DWORD mode) { - if (!SetConsoleMode(getConin(), mode)) { - fprintf(stderr, "error: SetConsoleMode failed (is stdin a console?)\n"); - exit(1); - } -} - -static long parseInt(const std::string &s) { - errno = 0; - char *endptr = nullptr; - long result = strtol(s.c_str(), &endptr, 0); - if (errno != 0 || !endptr || *endptr != '\0') { - fprintf(stderr, "error: could not parse integral argument '%s'\n", s.c_str()); - exit(1); - } - return result; -} - -static void usage() { - printf("Usage: ConinMode [verb] [options]\n"); - printf("Verbs:\n"); - printf(" [info] Dumps info about mode flags.\n"); - printf(" get Prints the mode DWORD.\n"); - printf(" set VALUE Sets the mode to VALUE, which can be decimal, hex, or octal.\n"); - printf(" set VALUE MASK\n"); - printf(" Same as `set VALUE`, but only alters the bits in MASK.\n"); - exit(1); -} - -struct { - const char *name; - DWORD value; -} kInputFlags[] = { - "ENABLE_PROCESSED_INPUT", ENABLE_PROCESSED_INPUT, // 0x0001 - "ENABLE_LINE_INPUT", ENABLE_LINE_INPUT, // 0x0002 - "ENABLE_ECHO_INPUT", ENABLE_ECHO_INPUT, // 0x0004 - "ENABLE_WINDOW_INPUT", ENABLE_WINDOW_INPUT, // 0x0008 - "ENABLE_MOUSE_INPUT", ENABLE_MOUSE_INPUT, // 0x0010 - "ENABLE_INSERT_MODE", ENABLE_INSERT_MODE, // 0x0020 - "ENABLE_QUICK_EDIT_MODE", ENABLE_QUICK_EDIT_MODE, // 0x0040 - "ENABLE_EXTENDED_FLAGS", ENABLE_EXTENDED_FLAGS, // 0x0080 - "ENABLE_VIRTUAL_TERMINAL_INPUT", 0x0200/*ENABLE_VIRTUAL_TERMINAL_INPUT*/, // 0x0200 -}; - -int main(int argc, char *argv[]) { - std::vector args; - for (size_t i = 1; i < argc; ++i) { - args.push_back(argv[i]); - } - - if (args.empty() || args.size() == 1 && args[0] == "info") { - DWORD mode = getConsoleMode(); - printf("mode: 0x%lx\n", mode); - for (const auto &flag : kInputFlags) { - printf("%-29s 0x%04lx %s\n", flag.name, flag.value, flag.value & mode ? "ON" : "off"); - mode &= ~flag.value; - } - for (int i = 0; i < 32; ++i) { - if (mode & (1u << i)) { - printf("Unrecognized flag: %04x\n", (1u << i)); - } - } - return 0; - } - - const auto verb = args[0]; - - if (verb == "set") { - if (args.size() == 2) { - const DWORD newMode = parseInt(args[1]); - setConsoleMode(newMode); - } else if (args.size() == 3) { - const DWORD mode = parseInt(args[1]); - const DWORD mask = parseInt(args[2]); - const int newMode = (getConsoleMode() & ~mask) | (mode & mask); - setConsoleMode(newMode); - } else { - usage(); - } - } else if (verb == "get") { - if (args.size() != 1) { - usage(); - } - printf("0x%lx\n", getConsoleMode()); - } else { - usage(); - } - - return 0; -} diff --git a/deps/winpty/misc/ConinMode.ps1 b/deps/winpty/misc/ConinMode.ps1 deleted file mode 100644 index ecfe8f039..000000000 --- a/deps/winpty/misc/ConinMode.ps1 +++ /dev/null @@ -1,116 +0,0 @@ -# -# PowerShell script for controlling the console QuickEdit and InsertMode flags. -# -# Turn QuickEdit off to interact with mouse-driven console programs. -# -# Usage: -# -# powershell .\ConinMode.ps1 [Options] -# -# Options: -# -QuickEdit [on/off] -# -InsertMode [on/off] -# -Mode [integer] -# - -param ( - [ValidateSet("on", "off")][string] $QuickEdit, - [ValidateSet("on", "off")][string] $InsertMode, - [int] $Mode -) - -$signature = @' -[DllImport("kernel32.dll", SetLastError = true)] -public static extern IntPtr GetStdHandle(int nStdHandle); - -[DllImport("kernel32.dll", SetLastError = true)] -public static extern uint GetConsoleMode( - IntPtr hConsoleHandle, - out uint lpMode); - -[DllImport("kernel32.dll", SetLastError = true)] -public static extern uint SetConsoleMode( - IntPtr hConsoleHandle, - uint dwMode); - -public const int STD_INPUT_HANDLE = -10; -public const int ENABLE_INSERT_MODE = 0x0020; -public const int ENABLE_QUICK_EDIT_MODE = 0x0040; -public const int ENABLE_EXTENDED_FLAGS = 0x0080; -'@ - -$WinAPI = Add-Type -MemberDefinition $signature ` - -Name WinAPI -Namespace ConinModeScript ` - -PassThru - -function GetConIn { - $ret = $WinAPI::GetStdHandle($WinAPI::STD_INPUT_HANDLE) - if ($ret -eq -1) { - throw "error: cannot get stdin" - } - return $ret -} - -function GetConsoleMode { - $conin = GetConIn - $mode = 0 - $ret = $WinAPI::GetConsoleMode($conin, [ref]$mode) - if ($ret -eq 0) { - throw "GetConsoleMode failed (is stdin a console?)" - } - return $mode -} - -function SetConsoleMode($mode) { - $conin = GetConIn - $ret = $WinAPI::SetConsoleMode($conin, $mode) - if ($ret -eq 0) { - throw "SetConsoleMode failed (is stdin a console?)" - } -} - -$oldMode = GetConsoleMode -$newMode = $oldMode -$doingSomething = $false - -if ($PSBoundParameters.ContainsKey("Mode")) { - $newMode = $Mode - $doingSomething = $true -} - -if ($QuickEdit + $InsertMode -ne "") { - if (!($newMode -band $WinAPI::ENABLE_EXTENDED_FLAGS)) { - # We can't enable an extended flag without overwriting the existing - # QuickEdit/InsertMode flags. AFAICT, there is no way to query their - # existing values, so at least we can choose sensible defaults. - $newMode = $newMode -bor $WinAPI::ENABLE_EXTENDED_FLAGS - $newMode = $newMode -bor $WinAPI::ENABLE_QUICK_EDIT_MODE - $newMode = $newMode -bor $WinAPI::ENABLE_INSERT_MODE - $doingSomething = $true - } -} - -if ($QuickEdit -eq "on") { - $newMode = $newMode -bor $WinAPI::ENABLE_QUICK_EDIT_MODE - $doingSomething = $true -} elseif ($QuickEdit -eq "off") { - $newMode = $newMode -band (-bnot $WinAPI::ENABLE_QUICK_EDIT_MODE) - $doingSomething = $true -} - -if ($InsertMode -eq "on") { - $newMode = $newMode -bor $WinAPI::ENABLE_INSERT_MODE - $doingSomething = $true -} elseif ($InsertMode -eq "off") { - $newMode = $newMode -band (-bnot $WinAPI::ENABLE_INSERT_MODE) - $doingSomething = $true -} - -if ($doingSomething) { - echo "old mode: $oldMode" - SetConsoleMode $newMode - $newMode = GetConsoleMode - echo "new mode: $newMode" -} else { - echo "mode: $oldMode" -} diff --git a/deps/winpty/misc/ConoutMode.cc b/deps/winpty/misc/ConoutMode.cc deleted file mode 100644 index 100e0c7be..000000000 --- a/deps/winpty/misc/ConoutMode.cc +++ /dev/null @@ -1,113 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -static HANDLE getConout() { - HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - if (conout == INVALID_HANDLE_VALUE) { - fprintf(stderr, "error: cannot get stdout\n"); - exit(1); - } - return conout; -} - -static DWORD getConsoleMode() { - DWORD mode = 0; - if (!GetConsoleMode(getConout(), &mode)) { - fprintf(stderr, "error: GetConsoleMode failed (is stdout a console?)\n"); - exit(1); - } - return mode; -} - -static void setConsoleMode(DWORD mode) { - if (!SetConsoleMode(getConout(), mode)) { - fprintf(stderr, "error: SetConsoleMode failed (is stdout a console?)\n"); - exit(1); - } -} - -static long parseInt(const std::string &s) { - errno = 0; - char *endptr = nullptr; - long result = strtol(s.c_str(), &endptr, 0); - if (errno != 0 || !endptr || *endptr != '\0') { - fprintf(stderr, "error: could not parse integral argument '%s'\n", s.c_str()); - exit(1); - } - return result; -} - -static void usage() { - printf("Usage: ConoutMode [verb] [options]\n"); - printf("Verbs:\n"); - printf(" [info] Dumps info about mode flags.\n"); - printf(" get Prints the mode DWORD.\n"); - printf(" set VALUE Sets the mode to VALUE, which can be decimal, hex, or octal.\n"); - printf(" set VALUE MASK\n"); - printf(" Same as `set VALUE`, but only alters the bits in MASK.\n"); - exit(1); -} - -struct { - const char *name; - DWORD value; -} kOutputFlags[] = { - "ENABLE_PROCESSED_OUTPUT", ENABLE_PROCESSED_OUTPUT, // 0x0001 - "ENABLE_WRAP_AT_EOL_OUTPUT", ENABLE_WRAP_AT_EOL_OUTPUT, // 0x0002 - "ENABLE_VIRTUAL_TERMINAL_PROCESSING", 0x0004/*ENABLE_VIRTUAL_TERMINAL_PROCESSING*/, // 0x0004 - "DISABLE_NEWLINE_AUTO_RETURN", 0x0008/*DISABLE_NEWLINE_AUTO_RETURN*/, // 0x0008 - "ENABLE_LVB_GRID_WORLDWIDE", 0x0010/*ENABLE_LVB_GRID_WORLDWIDE*/, //0x0010 -}; - -int main(int argc, char *argv[]) { - std::vector args; - for (size_t i = 1; i < argc; ++i) { - args.push_back(argv[i]); - } - - if (args.empty() || args.size() == 1 && args[0] == "info") { - DWORD mode = getConsoleMode(); - printf("mode: 0x%lx\n", mode); - for (const auto &flag : kOutputFlags) { - printf("%-34s 0x%04lx %s\n", flag.name, flag.value, flag.value & mode ? "ON" : "off"); - mode &= ~flag.value; - } - for (int i = 0; i < 32; ++i) { - if (mode & (1u << i)) { - printf("Unrecognized flag: %04x\n", (1u << i)); - } - } - return 0; - } - - const auto verb = args[0]; - - if (verb == "set") { - if (args.size() == 2) { - const DWORD newMode = parseInt(args[1]); - setConsoleMode(newMode); - } else if (args.size() == 3) { - const DWORD mode = parseInt(args[1]); - const DWORD mask = parseInt(args[2]); - const int newMode = (getConsoleMode() & ~mask) | (mode & mask); - setConsoleMode(newMode); - } else { - usage(); - } - } else if (verb == "get") { - if (args.size() != 1) { - usage(); - } - printf("0x%lx\n", getConsoleMode()); - } else { - usage(); - } - - return 0; -} diff --git a/deps/winpty/misc/DebugClient.py b/deps/winpty/misc/DebugClient.py deleted file mode 100644 index cd12df892..000000000 --- a/deps/winpty/misc/DebugClient.py +++ /dev/null @@ -1,42 +0,0 @@ -#!python -# Run with native CPython. Needs pywin32 extensions. - -# Copyright (c) 2011-2012 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import winerror -import win32pipe -import win32file -import win32api -import sys -import pywintypes -import time - -if len(sys.argv) != 2: - print("Usage: %s message" % sys.argv[0]) - sys.exit(1) - -message = "[%05.3f %s]: %s" % (time.time() % 100000, sys.argv[0], sys.argv[1]) - -win32pipe.CallNamedPipe( - "\\\\.\\pipe\\DebugServer", - message.encode(), - 16, - win32pipe.NMPWAIT_WAIT_FOREVER) diff --git a/deps/winpty/misc/DebugServer.py b/deps/winpty/misc/DebugServer.py deleted file mode 100644 index 3fc068bae..000000000 --- a/deps/winpty/misc/DebugServer.py +++ /dev/null @@ -1,63 +0,0 @@ -#!python -# -# Run with native CPython. Needs pywin32 extensions. - -# Copyright (c) 2011-2012 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import win32pipe -import win32api -import win32file -import time -import threading -import sys - -# A message may not be larger than this size. -MSG_SIZE=4096 - -serverPipe = win32pipe.CreateNamedPipe( - "\\\\.\\pipe\\DebugServer", - win32pipe.PIPE_ACCESS_DUPLEX, - win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE, - win32pipe.PIPE_UNLIMITED_INSTANCES, - MSG_SIZE, - MSG_SIZE, - 10 * 1000, - None) -while True: - win32pipe.ConnectNamedPipe(serverPipe, None) - (ret, data) = win32file.ReadFile(serverPipe, MSG_SIZE) - print(data.decode()) - sys.stdout.flush() - - # The client uses CallNamedPipe to send its message. CallNamedPipe waits - # for a reply message. If I send a reply, however, using WriteFile, then - # sometimes WriteFile fails with: - # pywintypes.error: (232, 'WriteFile', 'The pipe is being closed.') - # I can't figure out how to write a strictly correct pipe server, but if - # I comment out the WriteFile line, then everything seems to work. I - # think the DisconnectNamedPipe call aborts the client's CallNamedPipe - # call normally. - - try: - win32file.WriteFile(serverPipe, b'OK') - except: - pass - win32pipe.DisconnectNamedPipe(serverPipe) diff --git a/deps/winpty/misc/DumpLines.py b/deps/winpty/misc/DumpLines.py deleted file mode 100644 index 40049961b..000000000 --- a/deps/winpty/misc/DumpLines.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -import sys - -for i in range(1, int(sys.argv[1]) + 1): - print i, "X" * 78 diff --git a/deps/winpty/misc/EnableExtendedFlags.txt b/deps/winpty/misc/EnableExtendedFlags.txt deleted file mode 100644 index 37914dac2..000000000 --- a/deps/winpty/misc/EnableExtendedFlags.txt +++ /dev/null @@ -1,46 +0,0 @@ -Note regarding ENABLE_EXTENDED_FLAGS (2016-05-30) - -There is a complicated interaction between the ENABLE_EXTENDED_FLAGS flag -and the ENABLE_QUICK_EDIT_MODE and ENABLE_INSERT_MODE flags (presumably for -backwards compatibility?). I studied the behavior on Windows 7 and Windows -10, with both the old and new consoles, and I didn't see any differences -between versions. Here's what I seemed to observe: - - - The console has three flags internally: - - QuickEdit - - InsertMode - - ExtendedFlags - - - SetConsoleMode psuedocode: - void SetConsoleMode(..., DWORD mode) { - ExtendedFlags = (mode & (ENABLE_EXTENDED_FLAGS - | ENABLE_QUICK_EDIT_MODE - | ENABLE_INSERT_MODE )) != 0; - if (ExtendedFlags) { - QuickEdit = (mode & ENABLE_QUICK_EDIT_MODE) != 0; - InsertMode = (mode & ENABLE_INSERT_MODE) != 0; - } - } - - - Setting QuickEdit or InsertMode from the properties dialog GUI does not - affect the ExtendedFlags setting -- it simply toggles the one flag. - - - GetConsoleMode psuedocode: - GetConsoleMode(..., DWORD *result) { - if (ExtendedFlags) { - *result |= ENABLE_EXTENDED_FLAGS; - if (QuickEdit) { *result |= ENABLE_QUICK_EDIT_MODE; } - if (InsertMode) { *result |= ENABLE_INSERT_MODE; } - } - } - -Effectively, the ExtendedFlags flags controls whether the other two flags -are visible/controlled by the user application. If they aren't visible, -though, there is no way for the user application to make them visible, -except by overwriting their values! Calling SetConsoleMode with just -ENABLE_EXTENDED_FLAGS would clear the extended flags we want to read. - -Consequently, if a program temporarily alters the QuickEdit flag (e.g. to -enable mouse input), it cannot restore the original values of the QuickEdit -and InsertMode flags, UNLESS every other console program cooperates by -keeping the ExtendedFlags flag set. diff --git a/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt b/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt deleted file mode 100644 index 067bd3824..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt +++ /dev/null @@ -1,528 +0,0 @@ -================================== -Code Page 437, Consolas font -================================== - -Options: -face "Consolas" -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -FontSurvey "-face \"Consolas\" -family 0x36" - -Windows 7 ---------- - -Size 1: 1,3 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 1,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 2,5 BAD (HHHHHH) -Size 6: 3,6 BAD (HHHHHH) -Size 7: 3,6 BAD (HHHHHH) -Size 8: 4,8 BAD (HHHHHH) -Size 9: 4,9 BAD (HHHHHH) -Size 10: 5,10 BAD (HHHHHH) -Size 11: 5,11 BAD (HHHHHH) -Size 12: 6,12 BAD (HHHHHH) -Size 13: 6,13 BAD (HHHHHH) -Size 14: 7,14 BAD (HHHHHH) -Size 15: 7,15 BAD (HHHHHH) -Size 16: 8,16 BAD (HHHHHH) -Size 17: 8,17 BAD (HHHHHH) -Size 18: 8,18 BAD (HHHHHH) -Size 19: 9,19 BAD (HHHHHH) -Size 20: 9,20 BAD (HHHHHH) -Size 21: 10,22 BAD (HHHHHH) -Size 22: 10,22 BAD (HHHHHH) -Size 23: 11,23 BAD (HHHHHH) -Size 24: 11,24 BAD (HHHHHH) -Size 25: 12,25 BAD (HHHHHH) -Size 26: 12,26 BAD (HHHHHH) -Size 27: 13,27 BAD (HHHHHH) -Size 28: 13,28 BAD (HHHHHH) -Size 29: 14,29 BAD (HHHHHH) -Size 30: 14,30 BAD (HHHHHH) -Size 31: 15,31 BAD (HHHHHH) -Size 32: 15,32 BAD (HHHHHH) -Size 33: 15,33 BAD (HHHHHH) -Size 34: 16,34 BAD (HHHHHH) -Size 35: 16,36 BAD (HHHHHH) -Size 36: 17,36 BAD (HHHHHH) -Size 37: 17,37 BAD (HHHHHH) -Size 38: 18,38 BAD (HHHHHH) -Size 39: 18,39 BAD (HHHHHH) -Size 40: 19,40 BAD (HHHHHH) -Size 41: 19,41 BAD (HHHHHH) -Size 42: 20,42 BAD (HHHHHH) -Size 43: 20,43 BAD (HHHHHH) -Size 44: 21,44 BAD (HHHHHH) -Size 45: 21,45 BAD (HHHHHH) -Size 46: 22,46 BAD (HHHHHH) -Size 47: 22,47 BAD (HHHHHH) -Size 48: 23,48 BAD (HHHHHH) -Size 49: 23,49 BAD (HHHHHH) -Size 50: 23,50 BAD (HHHHHH) -Size 51: 24,51 BAD (HHHHHH) -Size 52: 24,52 BAD (HHHHHH) -Size 53: 25,53 BAD (HHHHHH) -Size 54: 25,54 BAD (HHHHHH) -Size 55: 26,55 BAD (HHHHHH) -Size 56: 26,56 BAD (HHHHHH) -Size 57: 27,57 BAD (HHHHHH) -Size 58: 27,58 BAD (HHHHHH) -Size 59: 28,59 BAD (HHHHHH) -Size 60: 28,60 BAD (HHHHHH) -Size 61: 29,61 BAD (HHHHHH) -Size 62: 29,62 BAD (HHHHHH) -Size 63: 30,64 BAD (HHHHHH) -Size 64: 30,64 BAD (HHHHHH) -Size 65: 31,65 BAD (HHHHHH) -Size 66: 31,66 BAD (HHHHHH) -Size 67: 31,67 BAD (HHHHHH) -Size 68: 32,68 BAD (HHHHHH) -Size 69: 32,69 BAD (HHHHHH) -Size 70: 33,70 BAD (HHHHHH) -Size 71: 33,71 BAD (HHHHHH) -Size 72: 34,72 BAD (HHHHHH) -Size 73: 34,73 BAD (HHHHHH) -Size 74: 35,74 BAD (HHHHHH) -Size 75: 35,75 BAD (HHHHHH) -Size 76: 36,76 BAD (HHHHHH) -Size 77: 36,77 BAD (HHHHHH) -Size 78: 37,78 BAD (HHHHHH) -Size 79: 37,79 BAD (HHHHHH) -Size 80: 38,80 BAD (HHHHHH) -Size 81: 38,81 BAD (HHHHHH) -Size 82: 39,82 BAD (HHHHHH) -Size 83: 39,83 BAD (HHHHHH) -Size 84: 39,84 BAD (HHHHHH) -Size 85: 40,85 BAD (HHHHHH) -Size 86: 40,86 BAD (HHHHHH) -Size 87: 41,87 BAD (HHHHHH) -Size 88: 41,88 BAD (HHHHHH) -Size 89: 42,89 BAD (HHHHHH) -Size 90: 42,90 BAD (HHHHHH) -Size 91: 43,91 BAD (HHHHHH) -Size 92: 43,92 BAD (HHHHHH) -Size 93: 44,93 BAD (HHHHHH) -Size 94: 44,94 BAD (HHHHHH) -Size 95: 45,95 BAD (HHHHHH) -Size 96: 45,96 BAD (HHHHHH) -Size 97: 46,97 BAD (HHHHHH) -Size 98: 46,98 BAD (HHHHHH) -Size 99: 46,99 BAD (HHHHHH) -Size 100: 47,100 BAD (HHHHHH) - -Windows 8 ---------- - -Size 1: 1,3 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 1,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 2,5 BAD (HHHHHH) -Size 6: 3,6 BAD (HHHHHH) -Size 7: 3,6 BAD (HHHHHH) -Size 8: 4,8 BAD (HHHHHH) -Size 9: 4,9 BAD (HHHHHH) -Size 10: 5,10 BAD (HHHHHH) -Size 11: 5,11 BAD (HHHHHH) -Size 12: 6,12 BAD (HHHHHH) -Size 13: 6,13 BAD (HHHHHH) -Size 14: 7,14 BAD (HHHHHH) -Size 15: 7,15 BAD (HHHHHH) -Size 16: 8,16 BAD (HHHHHH) -Size 17: 8,17 BAD (HHHHHH) -Size 18: 8,18 BAD (HHHHHH) -Size 19: 9,19 BAD (HHHHHH) -Size 20: 9,20 BAD (HHHHHH) -Size 21: 10,22 BAD (HHHHHH) -Size 22: 10,22 BAD (HHHHHH) -Size 23: 11,23 BAD (HHHHHH) -Size 24: 11,24 BAD (HHHHHH) -Size 25: 12,25 BAD (HHHHHH) -Size 26: 12,26 BAD (HHHHHH) -Size 27: 13,27 BAD (HHHHHH) -Size 28: 13,28 BAD (HHHHHH) -Size 29: 14,29 BAD (HHHHHH) -Size 30: 14,30 BAD (HHHHHH) -Size 31: 15,31 BAD (HHHHHH) -Size 32: 15,32 BAD (HHHHHH) -Size 33: 15,33 BAD (HHHHHH) -Size 34: 16,34 BAD (HHHHHH) -Size 35: 16,36 BAD (HHHHHH) -Size 36: 17,36 BAD (HHHHHH) -Size 37: 17,37 BAD (HHHHHH) -Size 38: 18,38 BAD (HHHHHH) -Size 39: 18,39 BAD (HHHHHH) -Size 40: 19,40 BAD (HHHHHH) -Size 41: 19,41 BAD (HHHHHH) -Size 42: 20,42 BAD (HHHHHH) -Size 43: 20,43 BAD (HHHHHH) -Size 44: 21,44 BAD (HHHHHH) -Size 45: 21,45 BAD (HHHHHH) -Size 46: 22,46 BAD (HHHHHH) -Size 47: 22,47 BAD (HHHHHH) -Size 48: 23,48 BAD (HHHHHH) -Size 49: 23,49 BAD (HHHHHH) -Size 50: 23,50 BAD (HHHHHH) -Size 51: 24,51 BAD (HHHHHH) -Size 52: 24,52 BAD (HHHHHH) -Size 53: 25,53 BAD (HHHHHH) -Size 54: 25,54 BAD (HHHHHH) -Size 55: 26,55 BAD (HHHHHH) -Size 56: 26,56 BAD (HHHHHH) -Size 57: 27,57 BAD (HHHHHH) -Size 58: 27,58 BAD (HHHHHH) -Size 59: 28,59 BAD (HHHHHH) -Size 60: 28,60 BAD (HHHHHH) -Size 61: 29,61 BAD (HHHHHH) -Size 62: 29,62 BAD (HHHHHH) -Size 63: 30,64 BAD (HHHHHH) -Size 64: 30,64 BAD (HHHHHH) -Size 65: 31,65 BAD (HHHHHH) -Size 66: 31,66 BAD (HHHHHH) -Size 67: 31,67 BAD (HHHHHH) -Size 68: 32,68 BAD (HHHHHH) -Size 69: 32,69 BAD (HHHHHH) -Size 70: 33,70 BAD (HHHHHH) -Size 71: 33,71 BAD (HHHHHH) -Size 72: 34,72 BAD (HHHHHH) -Size 73: 34,73 BAD (HHHHHH) -Size 74: 35,74 BAD (HHHHHH) -Size 75: 35,75 BAD (HHHHHH) -Size 76: 36,76 BAD (HHHHHH) -Size 77: 36,77 BAD (HHHHHH) -Size 78: 37,78 BAD (HHHHHH) -Size 79: 37,79 BAD (HHHHHH) -Size 80: 38,80 BAD (HHHHHH) -Size 81: 38,81 BAD (HHHHHH) -Size 82: 39,82 BAD (HHHHHH) -Size 83: 39,83 BAD (HHHHHH) -Size 84: 39,84 BAD (HHHHHH) -Size 85: 40,85 BAD (HHHHHH) -Size 86: 40,86 BAD (HHHHHH) -Size 87: 41,87 BAD (HHHHHH) -Size 88: 41,88 BAD (HHHHHH) -Size 89: 42,89 BAD (HHHHHH) -Size 90: 42,90 BAD (HHHHHH) -Size 91: 43,91 BAD (HHHHHH) -Size 92: 43,92 BAD (HHHHHH) -Size 93: 44,93 BAD (HHHHHH) -Size 94: 44,94 BAD (HHHHHH) -Size 95: 45,95 BAD (HHHHHH) -Size 96: 45,96 BAD (HHHHHH) -Size 97: 46,97 BAD (HHHHHH) -Size 98: 46,98 BAD (HHHHHH) -Size 99: 46,99 BAD (HHHHHH) -Size 100: 47,100 BAD (HHHHHH) - -Windows 8.1 ------------ - -Size 1: 1,3 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 1,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 2,5 BAD (HHHHHH) -Size 6: 3,6 BAD (HHHHHH) -Size 7: 3,6 BAD (HHHHHH) -Size 8: 4,8 BAD (HHHHHH) -Size 9: 4,9 BAD (HHHHHH) -Size 10: 5,10 BAD (HHHHHH) -Size 11: 5,11 BAD (HHHHHH) -Size 12: 6,12 BAD (HHHHHH) -Size 13: 6,13 BAD (HHHHHH) -Size 14: 7,14 BAD (HHHHHH) -Size 15: 7,15 BAD (HHHHHH) -Size 16: 8,16 BAD (HHHHHH) -Size 17: 8,17 BAD (HHHHHH) -Size 18: 8,18 BAD (HHHHHH) -Size 19: 9,19 BAD (HHHHHH) -Size 20: 9,20 BAD (HHHHHH) -Size 21: 10,22 BAD (HHHHHH) -Size 22: 10,22 BAD (HHHHHH) -Size 23: 11,23 BAD (HHHHHH) -Size 24: 11,24 BAD (HHHHHH) -Size 25: 12,25 BAD (HHHHHH) -Size 26: 12,26 BAD (HHHHHH) -Size 27: 13,27 BAD (HHHHHH) -Size 28: 13,28 BAD (HHHHHH) -Size 29: 14,29 BAD (HHHHHH) -Size 30: 14,30 BAD (HHHHHH) -Size 31: 15,31 BAD (HHHHHH) -Size 32: 15,32 BAD (HHHHHH) -Size 33: 15,33 BAD (HHHHHH) -Size 34: 16,34 BAD (HHHHHH) -Size 35: 16,36 BAD (HHHHHH) -Size 36: 17,36 BAD (HHHHHH) -Size 37: 17,37 BAD (HHHHHH) -Size 38: 18,38 BAD (HHHHHH) -Size 39: 18,39 BAD (HHHHHH) -Size 40: 19,40 BAD (HHHHHH) -Size 41: 19,41 BAD (HHHHHH) -Size 42: 20,42 BAD (HHHHHH) -Size 43: 20,43 BAD (HHHHHH) -Size 44: 21,44 BAD (HHHHHH) -Size 45: 21,45 BAD (HHHHHH) -Size 46: 22,46 BAD (HHHHHH) -Size 47: 22,47 BAD (HHHHHH) -Size 48: 23,48 BAD (HHHHHH) -Size 49: 23,49 BAD (HHHHHH) -Size 50: 23,50 BAD (HHHHHH) -Size 51: 24,51 BAD (HHHHHH) -Size 52: 24,52 BAD (HHHHHH) -Size 53: 25,53 BAD (HHHHHH) -Size 54: 25,54 BAD (HHHHHH) -Size 55: 26,55 BAD (HHHHHH) -Size 56: 26,56 BAD (HHHHHH) -Size 57: 27,57 BAD (HHHHHH) -Size 58: 27,58 BAD (HHHHHH) -Size 59: 28,59 BAD (HHHHHH) -Size 60: 28,60 BAD (HHHHHH) -Size 61: 29,61 BAD (HHHHHH) -Size 62: 29,62 BAD (HHHHHH) -Size 63: 30,64 BAD (HHHHHH) -Size 64: 30,64 BAD (HHHHHH) -Size 65: 31,65 BAD (HHHHHH) -Size 66: 31,66 BAD (HHHHHH) -Size 67: 31,67 BAD (HHHHHH) -Size 68: 32,68 BAD (HHHHHH) -Size 69: 32,69 BAD (HHHHHH) -Size 70: 33,70 BAD (HHHHHH) -Size 71: 33,71 BAD (HHHHHH) -Size 72: 34,72 BAD (HHHHHH) -Size 73: 34,73 BAD (HHHHHH) -Size 74: 35,74 BAD (HHHHHH) -Size 75: 35,75 BAD (HHHHHH) -Size 76: 36,76 BAD (HHHHHH) -Size 77: 36,77 BAD (HHHHHH) -Size 78: 37,78 BAD (HHHHHH) -Size 79: 37,79 BAD (HHHHHH) -Size 80: 38,80 BAD (HHHHHH) -Size 81: 38,81 BAD (HHHHHH) -Size 82: 39,82 BAD (HHHHHH) -Size 83: 39,83 BAD (HHHHHH) -Size 84: 39,84 BAD (HHHHHH) -Size 85: 40,85 BAD (HHHHHH) -Size 86: 40,86 BAD (HHHHHH) -Size 87: 41,87 BAD (HHHHHH) -Size 88: 41,88 BAD (HHHHHH) -Size 89: 42,89 BAD (HHHHHH) -Size 90: 42,90 BAD (HHHHHH) -Size 91: 43,91 BAD (HHHHHH) -Size 92: 43,92 BAD (HHHHHH) -Size 93: 44,93 BAD (HHHHHH) -Size 94: 44,94 BAD (HHHHHH) -Size 95: 45,95 BAD (HHHHHH) -Size 96: 45,96 BAD (HHHHHH) -Size 97: 46,97 BAD (HHHHHH) -Size 98: 46,98 BAD (HHHHHH) -Size 99: 46,99 BAD (HHHHHH) -Size 100: 47,100 BAD (HHHHHH) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,3 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 1,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 2,5 BAD (HHHHHH) -Size 6: 3,6 BAD (HHHHHH) -Size 7: 3,6 BAD (HHHHHH) -Size 8: 4,8 BAD (HHHHHH) -Size 9: 4,9 BAD (HHHHHH) -Size 10: 5,10 BAD (HHHHHH) -Size 11: 5,11 BAD (HHHHHH) -Size 12: 6,12 BAD (HHHHHH) -Size 13: 6,13 BAD (HHHHHH) -Size 14: 7,14 BAD (HHHHHH) -Size 15: 7,15 BAD (HHHHHH) -Size 16: 8,16 BAD (HHHHHH) -Size 17: 8,17 BAD (HHHHHH) -Size 18: 8,18 BAD (HHHHHH) -Size 19: 9,19 BAD (HHHHHH) -Size 20: 9,20 BAD (HHHHHH) -Size 21: 10,22 BAD (HHHHHH) -Size 22: 10,22 BAD (HHHHHH) -Size 23: 11,23 BAD (HHHHHH) -Size 24: 11,24 BAD (HHHHHH) -Size 25: 12,25 BAD (HHHHHH) -Size 26: 12,26 BAD (HHHHHH) -Size 27: 13,27 BAD (HHHHHH) -Size 28: 13,28 BAD (HHHHHH) -Size 29: 14,29 BAD (HHHHHH) -Size 30: 14,30 BAD (HHHHHH) -Size 31: 15,31 BAD (HHHHHH) -Size 32: 15,32 BAD (HHHHHH) -Size 33: 15,33 BAD (HHHHHH) -Size 34: 16,34 BAD (HHHHHH) -Size 35: 16,36 BAD (HHHHHH) -Size 36: 17,36 BAD (HHHHHH) -Size 37: 17,37 BAD (HHHHHH) -Size 38: 18,38 BAD (HHHHHH) -Size 39: 18,39 BAD (HHHHHH) -Size 40: 19,40 BAD (HHHHHH) -Size 41: 19,41 BAD (HHHHHH) -Size 42: 20,42 BAD (HHHHHH) -Size 43: 20,43 BAD (HHHHHH) -Size 44: 21,44 BAD (HHHHHH) -Size 45: 21,45 BAD (HHHHHH) -Size 46: 22,46 BAD (HHHHHH) -Size 47: 22,47 BAD (HHHHHH) -Size 48: 23,48 BAD (HHHHHH) -Size 49: 23,49 BAD (HHHHHH) -Size 50: 23,50 BAD (HHHHHH) -Size 51: 24,51 BAD (HHHHHH) -Size 52: 24,52 BAD (HHHHHH) -Size 53: 25,53 BAD (HHHHHH) -Size 54: 25,54 BAD (HHHHHH) -Size 55: 26,55 BAD (HHHHHH) -Size 56: 26,56 BAD (HHHHHH) -Size 57: 27,57 BAD (HHHHHH) -Size 58: 27,58 BAD (HHHHHH) -Size 59: 28,59 BAD (HHHHHH) -Size 60: 28,60 BAD (HHHHHH) -Size 61: 29,61 BAD (HHHHHH) -Size 62: 29,62 BAD (HHHHHH) -Size 63: 30,64 BAD (HHHHHH) -Size 64: 30,64 BAD (HHHHHH) -Size 65: 31,65 BAD (HHHHHH) -Size 66: 31,66 BAD (HHHHHH) -Size 67: 31,67 BAD (HHHHHH) -Size 68: 32,68 BAD (HHHHHH) -Size 69: 32,69 BAD (HHHHHH) -Size 70: 33,70 BAD (HHHHHH) -Size 71: 33,71 BAD (HHHHHH) -Size 72: 34,72 BAD (HHHHHH) -Size 73: 34,73 BAD (HHHHHH) -Size 74: 35,74 BAD (HHHHHH) -Size 75: 35,75 BAD (HHHHHH) -Size 76: 36,76 BAD (HHHHHH) -Size 77: 36,77 BAD (HHHHHH) -Size 78: 37,78 BAD (HHHHHH) -Size 79: 37,79 BAD (HHHHHH) -Size 80: 38,80 BAD (HHHHHH) -Size 81: 38,81 BAD (HHHHHH) -Size 82: 39,82 BAD (HHHHHH) -Size 83: 39,83 BAD (HHHHHH) -Size 84: 39,84 BAD (HHHHHH) -Size 85: 40,85 BAD (HHHHHH) -Size 86: 40,86 BAD (HHHHHH) -Size 87: 41,87 BAD (HHHHHH) -Size 88: 41,88 BAD (HHHHHH) -Size 89: 42,89 BAD (HHHHHH) -Size 90: 42,90 BAD (HHHHHH) -Size 91: 43,91 BAD (HHHHHH) -Size 92: 43,92 BAD (HHHHHH) -Size 93: 44,93 BAD (HHHHHH) -Size 94: 44,94 BAD (HHHHHH) -Size 95: 45,95 BAD (HHHHHH) -Size 96: 45,96 BAD (HHHHHH) -Size 97: 46,97 BAD (HHHHHH) -Size 98: 46,98 BAD (HHHHHH) -Size 99: 46,99 BAD (HHHHHH) -Size 100: 47,100 BAD (HHHHHH) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 1,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 2,5 BAD (HHHHHH) -Size 6: 3,6 BAD (HHHHHH) -Size 7: 3,7 BAD (HHHHHH) -Size 8: 4,8 BAD (HHHHHH) -Size 9: 4,9 BAD (HHHHHH) -Size 10: 5,10 BAD (HHHHHH) -Size 11: 5,11 BAD (HHHHHH) -Size 12: 6,12 BAD (HHHHHH) -Size 13: 6,13 BAD (HHHHHH) -Size 14: 7,14 BAD (HHHHHH) -Size 15: 7,15 BAD (HHHHHH) -Size 16: 8,16 BAD (HHHHHH) -Size 17: 8,17 BAD (HHHHHH) -Size 18: 8,18 BAD (HHHHHH) -Size 19: 9,19 BAD (HHHHHH) -Size 20: 9,20 BAD (HHHHHH) -Size 21: 10,21 BAD (HHHHHH) -Size 22: 10,22 BAD (HHHHHH) -Size 23: 11,23 BAD (HHHHHH) -Size 24: 11,24 BAD (HHHHHH) -Size 25: 12,25 BAD (HHHHHH) -Size 26: 12,26 BAD (HHHHHH) -Size 27: 13,27 BAD (HHHHHH) -Size 28: 13,28 BAD (HHHHHH) -Size 29: 14,29 BAD (HHHHHH) -Size 30: 14,30 BAD (HHHHHH) -Size 31: 15,31 BAD (HHHHHH) -Size 32: 15,32 BAD (HHHHHH) -Size 33: 15,33 BAD (HHHHHH) -Size 34: 16,34 BAD (HHHHHH) -Size 35: 16,35 BAD (HHHHHH) -Size 36: 17,36 BAD (HHHHHH) -Size 37: 17,37 BAD (HHHHHH) -Size 38: 18,38 BAD (HHHHHH) -Size 39: 18,39 BAD (HHHHHH) -Size 40: 19,40 BAD (HHHHHH) -Size 41: 19,41 BAD (HHHHHH) -Size 42: 20,42 BAD (HHHHHH) -Size 43: 20,43 BAD (HHHHHH) -Size 44: 21,44 BAD (HHHHHH) -Size 45: 21,45 BAD (HHHHHH) -Size 46: 22,46 BAD (HHHHHH) -Size 47: 22,47 BAD (HHHHHH) -Size 48: 23,48 BAD (HHHHHH) -Size 49: 23,49 BAD (HHHHHH) -Size 50: 23,50 BAD (HHHHHH) -Size 51: 24,51 BAD (HHHHHH) -Size 52: 24,52 BAD (HHHHHH) -Size 53: 25,53 BAD (HHHHHH) -Size 54: 25,54 BAD (HHHHHH) -Size 55: 26,55 BAD (HHHHHH) -Size 56: 26,56 BAD (HHHHHH) -Size 57: 27,57 BAD (HHHHHH) -Size 58: 27,58 BAD (HHHHHH) -Size 59: 28,59 BAD (HHHHHH) -Size 60: 28,60 BAD (HHHHHH) -Size 61: 29,61 BAD (HHHHHH) -Size 62: 29,62 BAD (HHHHHH) -Size 63: 30,63 BAD (HHHHHH) -Size 64: 30,64 BAD (HHHHHH) -Size 65: 31,65 BAD (HHHHHH) -Size 66: 31,66 BAD (HHHHHH) -Size 67: 31,67 BAD (HHHHHH) -Size 68: 32,68 BAD (HHHHHH) -Size 69: 32,69 BAD (HHHHHH) -Size 70: 33,70 BAD (HHHHHH) -Size 71: 33,71 BAD (HHHHHH) -Size 72: 34,72 BAD (HHHHHH) -Size 73: 34,73 BAD (HHHHHH) -Size 74: 35,74 BAD (HHHHHH) -Size 75: 35,75 BAD (HHHHHH) -Size 76: 36,76 BAD (HHHHHH) -Size 77: 36,77 BAD (HHHHHH) -Size 78: 37,78 BAD (HHHHHH) -Size 79: 37,79 BAD (HHHHHH) -Size 80: 38,80 BAD (HHHHHH) -Size 81: 38,81 BAD (HHHHHH) -Size 82: 39,82 BAD (HHHHHH) -Size 83: 39,83 BAD (HHHHHH) -Size 84: 39,84 BAD (HHHHHH) -Size 85: 40,85 BAD (HHHHHH) -Size 86: 40,86 BAD (HHHHHH) -Size 87: 41,87 BAD (HHHHHH) -Size 88: 41,88 BAD (HHHHHH) -Size 89: 42,89 BAD (HHHHHH) -Size 90: 42,90 BAD (HHHHHH) -Size 91: 43,91 BAD (HHHHHH) -Size 92: 43,92 BAD (HHHHHH) -Size 93: 44,93 BAD (HHHHHH) -Size 94: 44,94 BAD (HHHHHH) -Size 95: 45,95 BAD (HHHHHH) -Size 96: 45,96 BAD (HHHHHH) -Size 97: 46,97 BAD (HHHHHH) -Size 98: 46,98 BAD (HHHHHH) -Size 99: 46,99 BAD (HHHHHH) -Size 100: 47,100 BAD (HHHHHH) diff --git a/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt b/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt deleted file mode 100644 index 0eed93ad9..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt +++ /dev/null @@ -1,633 +0,0 @@ -================================== -Code Page 437, Lucida Console font -================================== - -Options: -face "Lucida Console" -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -FontSurvey "-face \"Lucida Console\" -family 0x36" - -Vista ------ - -Size 1: 1,2 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,65 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) - - -Windows 7 ---------- - -Size 1: 1,2 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,65 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) - -Windows 8 ---------- - -Size 1: 1,2 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,65 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) - -Windows 8.1 ------------ - -Size 1: 1,2 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,65 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,2 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,65 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 BAD (HHHHHH) -Size 2: 1,2 BAD (HHHHHH) -Size 3: 2,3 BAD (HHHHHH) -Size 4: 2,4 BAD (HHHHHH) -Size 5: 3,5 BAD (HHHHHH) -Size 6: 4,6 BAD (HHHHHH) -Size 7: 4,7 BAD (HHHHHH) -Size 8: 5,8 BAD (HHHHHH) -Size 9: 5,9 BAD (HHHHHH) -Size 10: 6,10 BAD (HHHHHH) -Size 11: 7,11 BAD (HHHHHH) -Size 12: 7,12 BAD (HHHHHH) -Size 13: 8,13 BAD (HHHHHH) -Size 14: 8,14 BAD (HHHHHH) -Size 15: 9,15 BAD (HHHHHH) -Size 16: 10,16 BAD (HHHHHH) -Size 17: 10,17 BAD (HHHHHH) -Size 18: 11,18 BAD (HHHHHH) -Size 19: 11,19 BAD (HHHHHH) -Size 20: 12,20 BAD (HHHHHH) -Size 21: 13,21 BAD (HHHHHH) -Size 22: 13,22 BAD (HHHHHH) -Size 23: 14,23 BAD (HHHHHH) -Size 24: 14,24 BAD (HHHHHH) -Size 25: 15,25 BAD (HHHHHH) -Size 26: 16,26 BAD (HHHHHH) -Size 27: 16,27 BAD (HHHHHH) -Size 28: 17,28 BAD (HHHHHH) -Size 29: 17,29 BAD (HHHHHH) -Size 30: 18,30 BAD (HHHHHH) -Size 31: 19,31 BAD (HHHHHH) -Size 32: 19,32 BAD (HHHHHH) -Size 33: 20,33 BAD (HHHHHH) -Size 34: 20,34 BAD (HHHHHH) -Size 35: 21,35 BAD (HHHHHH) -Size 36: 22,36 BAD (HHHHHH) -Size 37: 22,37 BAD (HHHHHH) -Size 38: 23,38 BAD (HHHHHH) -Size 39: 23,39 BAD (HHHHHH) -Size 40: 24,40 BAD (HHHHHH) -Size 41: 25,41 BAD (HHHHHH) -Size 42: 25,42 BAD (HHHHHH) -Size 43: 26,43 BAD (HHHHHH) -Size 44: 27,44 BAD (HHHHHH) -Size 45: 27,45 BAD (HHHHHH) -Size 46: 28,46 BAD (HHHHHH) -Size 47: 28,47 BAD (HHHHHH) -Size 48: 29,48 BAD (HHHHHH) -Size 49: 30,49 BAD (HHHHHH) -Size 50: 30,50 BAD (HHHHHH) -Size 51: 31,51 BAD (HHHHHH) -Size 52: 31,52 BAD (HHHHHH) -Size 53: 32,53 BAD (HHHHHH) -Size 54: 33,54 BAD (HHHHHH) -Size 55: 33,55 BAD (HHHHHH) -Size 56: 34,56 BAD (HHHHHH) -Size 57: 34,57 BAD (HHHHHH) -Size 58: 35,58 BAD (HHHHHH) -Size 59: 36,59 BAD (HHHHHH) -Size 60: 36,60 BAD (HHHHHH) -Size 61: 37,61 BAD (HHHHHH) -Size 62: 37,62 BAD (HHHHHH) -Size 63: 38,63 BAD (HHHHHH) -Size 64: 39,64 BAD (HHHHHH) -Size 65: 39,65 BAD (HHHHHH) -Size 66: 40,66 BAD (HHHHHH) -Size 67: 40,67 BAD (HHHHHH) -Size 68: 41,68 BAD (HHHHHH) -Size 69: 42,69 BAD (HHHHHH) -Size 70: 42,70 BAD (HHHHHH) -Size 71: 43,71 BAD (HHHHHH) -Size 72: 43,72 BAD (HHHHHH) -Size 73: 44,73 BAD (HHHHHH) -Size 74: 45,74 BAD (HHHHHH) -Size 75: 45,75 BAD (HHHHHH) -Size 76: 46,76 BAD (HHHHHH) -Size 77: 46,77 BAD (HHHHHH) -Size 78: 47,78 BAD (HHHHHH) -Size 79: 48,79 BAD (HHHHHH) -Size 80: 48,80 BAD (HHHHHH) -Size 81: 49,81 BAD (HHHHHH) -Size 82: 49,82 BAD (HHHHHH) -Size 83: 50,83 BAD (HHHHHH) -Size 84: 51,84 BAD (HHHHHH) -Size 85: 51,85 BAD (HHHHHH) -Size 86: 52,86 BAD (HHHHHH) -Size 87: 52,87 BAD (HHHHHH) -Size 88: 53,88 BAD (HHHHHH) -Size 89: 54,89 BAD (HHHHHH) -Size 90: 54,90 BAD (HHHHHH) -Size 91: 55,91 BAD (HHHHHH) -Size 92: 55,92 BAD (HHHHHH) -Size 93: 56,93 BAD (HHHHHH) -Size 94: 57,94 BAD (HHHHHH) -Size 95: 57,95 BAD (HHHHHH) -Size 96: 58,96 BAD (HHHHHH) -Size 97: 58,97 BAD (HHHHHH) -Size 98: 59,98 BAD (HHHHHH) -Size 99: 60,99 BAD (HHHHHH) -Size 100: 60,100 BAD (HHHHHH) diff --git a/deps/winpty/misc/Font-Report-June2016/CP932.txt b/deps/winpty/misc/Font-Report-June2016/CP932.txt deleted file mode 100644 index ed3637eac..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP932.txt +++ /dev/null @@ -1,630 +0,0 @@ -======================================= -Code Page 932, Japanese, MS Gothic font -======================================= - -Options: -face-gothic -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -Vista ------ - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,4 OK (HHHFFF) -Size 5: 3,5 OK (HHHFFF) -Size 6: 3,6 OK (HHHFFF) -Size 7: 4,7 OK (HHHFFF) -Size 8: 4,8 OK (HHHFFF) -Size 9: 5,9 OK (HHHFFF) -Size 10: 5,10 OK (HHHFFF) -Size 11: 6,11 OK (HHHFFF) -Size 12: 6,12 OK (HHHFFF) -Size 13: 7,13 OK (HHHFFF) -Size 14: 7,14 BAD (HHHFHH) -Size 15: 8,15 OK (HHHFFF) -Size 16: 8,16 BAD (HHHFHH) -Size 17: 9,17 OK (HHHFFF) -Size 18: 9,18 BAD (HHHFHH) -Size 19: 10,19 OK (HHHFFF) -Size 20: 10,20 BAD (HHHFHH) -Size 21: 11,21 OK (HHHFFF) -Size 22: 11,22 BAD (HHHFHH) -Size 23: 12,23 BAD (HHHFHH) -Size 24: 12,24 BAD (HHHFHH) -Size 25: 13,25 BAD (HHHFHH) -Size 26: 13,26 BAD (HHHFHH) -Size 27: 14,27 BAD (HHHFHH) -Size 28: 14,28 BAD (HHHFHH) -Size 29: 15,29 BAD (HHHFHH) -Size 30: 15,30 BAD (HHHFHH) -Size 31: 16,31 BAD (HHHFHH) -Size 32: 16,33 BAD (HHHFHH) -Size 33: 17,33 BAD (HHHFHH) -Size 34: 17,34 BAD (HHHFHH) -Size 35: 18,35 BAD (HHHFHH) -Size 36: 18,36 BAD (HHHFHH) -Size 37: 19,37 BAD (HHHFHH) -Size 38: 19,38 BAD (HHHFHH) -Size 39: 20,39 BAD (HHHFHH) -Size 40: 20,40 BAD (HHHFHH) -Size 41: 21,41 BAD (HHHFHH) -Size 42: 21,42 BAD (HHHFHH) -Size 43: 22,43 BAD (HHHFHH) -Size 44: 22,44 BAD (HHHFHH) -Size 45: 23,45 BAD (HHHFHH) -Size 46: 23,46 BAD (HHHFHH) -Size 47: 24,47 BAD (HHHFHH) -Size 48: 24,48 BAD (HHHFHH) -Size 49: 25,49 BAD (HHHFHH) -Size 50: 25,50 BAD (HHHFHH) -Size 51: 26,51 BAD (HHHFHH) -Size 52: 26,52 BAD (HHHFHH) -Size 53: 27,53 BAD (HHHFHH) -Size 54: 27,54 BAD (HHHFHH) -Size 55: 28,55 BAD (HHHFHH) -Size 56: 28,56 BAD (HHHFHH) -Size 57: 29,57 BAD (HHHFHH) -Size 58: 29,58 BAD (HHHFHH) -Size 59: 30,59 BAD (HHHFHH) -Size 60: 30,60 BAD (HHHFHH) -Size 61: 31,61 BAD (HHHFHH) -Size 62: 31,62 BAD (HHHFHH) -Size 63: 32,63 BAD (HHHFHH) -Size 64: 32,64 BAD (HHHFHH) -Size 65: 33,65 BAD (HHHFHH) -Size 66: 33,66 BAD (HHHFHH) -Size 67: 34,67 BAD (HHHFHH) -Size 68: 34,68 BAD (HHHFHH) -Size 69: 35,69 BAD (HHHFHH) -Size 70: 35,70 BAD (HHHFHH) -Size 71: 36,71 BAD (HHHFHH) -Size 72: 36,72 BAD (HHHFHH) -Size 73: 37,73 BAD (HHHFHH) -Size 74: 37,74 BAD (HHHFHH) -Size 75: 38,75 BAD (HHHFHH) -Size 76: 38,76 BAD (HHHFHH) -Size 77: 39,77 BAD (HHHFHH) -Size 78: 39,78 BAD (HHHFHH) -Size 79: 40,79 BAD (HHHFHH) -Size 80: 40,80 BAD (HHHFHH) -Size 81: 41,81 BAD (HHHFHH) -Size 82: 41,82 BAD (HHHFHH) -Size 83: 42,83 BAD (HHHFHH) -Size 84: 42,84 BAD (HHHFHH) -Size 85: 43,85 BAD (HHHFHH) -Size 86: 43,86 BAD (HHHFHH) -Size 87: 44,87 BAD (HHHFHH) -Size 88: 44,88 BAD (HHHFHH) -Size 89: 45,89 BAD (HHHFHH) -Size 90: 45,90 BAD (HHHFHH) -Size 91: 46,91 BAD (HHHFHH) -Size 92: 46,92 BAD (HHHFHH) -Size 93: 47,93 BAD (HHHFHH) -Size 94: 47,94 BAD (HHHFHH) -Size 95: 48,95 BAD (HHHFHH) -Size 96: 48,97 BAD (HHHFHH) -Size 97: 49,97 BAD (HHHFHH) -Size 98: 49,98 BAD (HHHFHH) -Size 99: 50,99 BAD (HHHFHH) -Size 100: 50,100 BAD (HHHFHH) - -Windows 7 ---------- - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,4 OK (HHHFFF) -Size 5: 3,5 OK (HHHFFF) -Size 6: 3,6 OK (HHHFFF) -Size 7: 4,7 OK (HHHFFF) -Size 8: 4,8 OK (HHHFFF) -Size 9: 5,9 OK (HHHFFF) -Size 10: 5,10 OK (HHHFFF) -Size 11: 6,11 OK (HHHFFF) -Size 12: 6,12 OK (HHHFFF) -Size 13: 7,13 OK (HHHFFF) -Size 14: 7,14 BAD (FFFFFF) -Size 15: 8,15 OK (HHHFFF) -Size 16: 8,16 BAD (FFFFFF) -Size 17: 9,17 OK (HHHFFF) -Size 18: 9,18 BAD (FFFFFF) -Size 19: 10,19 OK (HHHFFF) -Size 20: 10,20 BAD (FFFFFF) -Size 21: 11,21 OK (HHHFFF) -Size 22: 11,22 BAD (FFFFFF) -Size 23: 12,23 BAD (FFFFFF) -Size 24: 12,24 BAD (FFFFFF) -Size 25: 13,25 BAD (FFFFFF) -Size 26: 13,26 BAD (FFFFFF) -Size 27: 14,27 BAD (FFFFFF) -Size 28: 14,28 BAD (FFFFFF) -Size 29: 15,29 BAD (FFFFFF) -Size 30: 15,30 BAD (FFFFFF) -Size 31: 16,31 BAD (FFFFFF) -Size 32: 16,33 BAD (FFFFFF) -Size 33: 17,33 BAD (FFFFFF) -Size 34: 17,34 BAD (FFFFFF) -Size 35: 18,35 BAD (FFFFFF) -Size 36: 18,36 BAD (FFFFFF) -Size 37: 19,37 BAD (FFFFFF) -Size 38: 19,38 BAD (FFFFFF) -Size 39: 20,39 BAD (FFFFFF) -Size 40: 20,40 BAD (FFFFFF) -Size 41: 21,41 BAD (FFFFFF) -Size 42: 21,42 BAD (FFFFFF) -Size 43: 22,43 BAD (FFFFFF) -Size 44: 22,44 BAD (FFFFFF) -Size 45: 23,45 BAD (FFFFFF) -Size 46: 23,46 BAD (FFFFFF) -Size 47: 24,47 BAD (FFFFFF) -Size 48: 24,48 BAD (FFFFFF) -Size 49: 25,49 BAD (FFFFFF) -Size 50: 25,50 BAD (FFFFFF) -Size 51: 26,51 BAD (FFFFFF) -Size 52: 26,52 BAD (FFFFFF) -Size 53: 27,53 BAD (FFFFFF) -Size 54: 27,54 BAD (FFFFFF) -Size 55: 28,55 BAD (FFFFFF) -Size 56: 28,56 BAD (FFFFFF) -Size 57: 29,57 BAD (FFFFFF) -Size 58: 29,58 BAD (FFFFFF) -Size 59: 30,59 BAD (FFFFFF) -Size 60: 30,60 BAD (FFFFFF) -Size 61: 31,61 BAD (FFFFFF) -Size 62: 31,62 BAD (FFFFFF) -Size 63: 32,63 BAD (FFFFFF) -Size 64: 32,64 BAD (FFFFFF) -Size 65: 33,65 BAD (FFFFFF) -Size 66: 33,66 BAD (FFFFFF) -Size 67: 34,67 BAD (FFFFFF) -Size 68: 34,68 BAD (FFFFFF) -Size 69: 35,69 BAD (FFFFFF) -Size 70: 35,70 BAD (FFFFFF) -Size 71: 36,71 BAD (FFFFFF) -Size 72: 36,72 BAD (FFFFFF) -Size 73: 37,73 BAD (FFFFFF) -Size 74: 37,74 BAD (FFFFFF) -Size 75: 38,75 BAD (FFFFFF) -Size 76: 38,76 BAD (FFFFFF) -Size 77: 39,77 BAD (FFFFFF) -Size 78: 39,78 BAD (FFFFFF) -Size 79: 40,79 BAD (FFFFFF) -Size 80: 40,80 BAD (FFFFFF) -Size 81: 41,81 BAD (FFFFFF) -Size 82: 41,82 BAD (FFFFFF) -Size 83: 42,83 BAD (FFFFFF) -Size 84: 42,84 BAD (FFFFFF) -Size 85: 43,85 BAD (FFFFFF) -Size 86: 43,86 BAD (FFFFFF) -Size 87: 44,87 BAD (FFFFFF) -Size 88: 44,88 BAD (FFFFFF) -Size 89: 45,89 BAD (FFFFFF) -Size 90: 45,90 BAD (FFFFFF) -Size 91: 46,91 BAD (FFFFFF) -Size 92: 46,92 BAD (FFFFFF) -Size 93: 47,93 BAD (FFFFFF) -Size 94: 47,94 BAD (FFFFFF) -Size 95: 48,95 BAD (FFFFFF) -Size 96: 48,97 BAD (FFFFFF) -Size 97: 49,97 BAD (FFFFFF) -Size 98: 49,98 BAD (FFFFFF) -Size 99: 50,99 BAD (FFFFFF) -Size 100: 50,100 BAD (FFFFFF) - -Windows 8 ---------- - -Size 1: 1,2 BAD (FFFFHH) -Size 2: 1,2 BAD (FFFFHH) -Size 3: 2,3 BAD (FFFFFF) -Size 4: 2,4 BAD (FFFFHH) -Size 5: 3,5 BAD (FFFFFF) -Size 6: 3,6 BAD (FFFFHH) -Size 7: 4,7 BAD (FFFFFF) -Size 8: 4,8 BAD (FFFFHH) -Size 9: 5,9 BAD (FFFFFF) -Size 10: 5,10 BAD (FFFFHH) -Size 11: 6,11 BAD (FFFFFF) -Size 12: 6,12 BAD (FFFFHH) -Size 13: 7,13 BAD (FFFFFF) -Size 14: 7,14 BAD (FFFFHH) -Size 15: 8,15 BAD (FFFFFF) -Size 16: 8,16 BAD (FFFFHH) -Size 17: 9,17 BAD (FFFFFF) -Size 18: 9,18 BAD (FFFFHH) -Size 19: 10,19 BAD (FFFFFF) -Size 20: 10,20 BAD (FFFFFF) -Size 21: 11,21 BAD (FFFFFF) -Size 22: 11,22 BAD (FFFFFF) -Size 23: 12,23 BAD (FFFFFF) -Size 24: 12,24 BAD (FFFFFF) -Size 25: 13,25 BAD (FFFFFF) -Size 26: 13,26 BAD (FFFFFF) -Size 27: 14,27 BAD (FFFFFF) -Size 28: 14,28 BAD (FFFFFF) -Size 29: 15,29 BAD (FFFFFF) -Size 30: 15,30 BAD (FFFFFF) -Size 31: 16,31 BAD (FFFFFF) -Size 32: 16,33 BAD (FFFFFF) -Size 33: 17,33 BAD (FFFFFF) -Size 34: 17,34 BAD (FFFFFF) -Size 35: 18,35 BAD (FFFFFF) -Size 36: 18,36 BAD (FFFFFF) -Size 37: 19,37 BAD (FFFFFF) -Size 38: 19,38 BAD (FFFFFF) -Size 39: 20,39 BAD (FFFFFF) -Size 40: 20,40 BAD (FFFFFF) -Size 41: 21,41 BAD (FFFFFF) -Size 42: 21,42 BAD (FFFFFF) -Size 43: 22,43 BAD (FFFFFF) -Size 44: 22,44 BAD (FFFFFF) -Size 45: 23,45 BAD (FFFFFF) -Size 46: 23,46 BAD (FFFFFF) -Size 47: 24,47 BAD (FFFFFF) -Size 48: 24,48 BAD (FFFFFF) -Size 49: 25,49 BAD (FFFFFF) -Size 50: 25,50 BAD (FFFFFF) -Size 51: 26,51 BAD (FFFFFF) -Size 52: 26,52 BAD (FFFFFF) -Size 53: 27,53 BAD (FFFFFF) -Size 54: 27,54 BAD (FFFFFF) -Size 55: 28,55 BAD (FFFFFF) -Size 56: 28,56 BAD (FFFFFF) -Size 57: 29,57 BAD (FFFFFF) -Size 58: 29,58 BAD (FFFFFF) -Size 59: 30,59 BAD (FFFFFF) -Size 60: 30,60 BAD (FFFFFF) -Size 61: 31,61 BAD (FFFFFF) -Size 62: 31,62 BAD (FFFFFF) -Size 63: 32,63 BAD (FFFFFF) -Size 64: 32,64 BAD (FFFFFF) -Size 65: 33,65 BAD (FFFFFF) -Size 66: 33,66 BAD (FFFFFF) -Size 67: 34,67 BAD (FFFFFF) -Size 68: 34,68 BAD (FFFFFF) -Size 69: 35,69 BAD (FFFFFF) -Size 70: 35,70 BAD (FFFFFF) -Size 71: 36,71 BAD (FFFFFF) -Size 72: 36,72 BAD (FFFFFF) -Size 73: 37,73 BAD (FFFFFF) -Size 74: 37,74 BAD (FFFFFF) -Size 75: 38,75 BAD (FFFFFF) -Size 76: 38,76 BAD (FFFFFF) -Size 77: 39,77 BAD (FFFFFF) -Size 78: 39,78 BAD (FFFFFF) -Size 79: 40,79 BAD (FFFFFF) -Size 80: 40,80 BAD (FFFFFF) -Size 81: 41,81 BAD (FFFFFF) -Size 82: 41,82 BAD (FFFFFF) -Size 83: 42,83 BAD (FFFFFF) -Size 84: 42,84 BAD (FFFFFF) -Size 85: 43,85 BAD (FFFFFF) -Size 86: 43,86 BAD (FFFFFF) -Size 87: 44,87 BAD (FFFFFF) -Size 88: 44,88 BAD (FFFFFF) -Size 89: 45,89 BAD (FFFFFF) -Size 90: 45,90 BAD (FFFFFF) -Size 91: 46,91 BAD (FFFFFF) -Size 92: 46,92 BAD (FFFFFF) -Size 93: 47,93 BAD (FFFFFF) -Size 94: 47,94 BAD (FFFFFF) -Size 95: 48,95 BAD (FFFFFF) -Size 96: 48,97 BAD (FFFFFF) -Size 97: 49,97 BAD (FFFFFF) -Size 98: 49,98 BAD (FFFFFF) -Size 99: 50,99 BAD (FFFFFF) -Size 100: 50,100 BAD (FFFFFF) - -Windows 8.1 ------------ - -Size 1: 1,2 BAD (FFFFHH) -Size 2: 1,2 BAD (FFFFHH) -Size 3: 2,3 BAD (FFFFFF) -Size 4: 2,4 BAD (FFFFHH) -Size 5: 3,5 BAD (FFFFFF) -Size 6: 3,6 BAD (FFFFHH) -Size 7: 4,7 BAD (FFFFFF) -Size 8: 4,8 BAD (FFFFHH) -Size 9: 5,9 BAD (FFFFFF) -Size 10: 5,10 BAD (FFFFHH) -Size 11: 6,11 BAD (FFFFFF) -Size 12: 6,12 BAD (FFFFHH) -Size 13: 7,13 BAD (FFFFFF) -Size 14: 7,14 BAD (FFFFHH) -Size 15: 8,15 BAD (FFFFFF) -Size 16: 8,16 BAD (FFFFHH) -Size 17: 9,17 BAD (FFFFFF) -Size 18: 9,18 BAD (FFFFHH) -Size 19: 10,19 BAD (FFFFFF) -Size 20: 10,20 BAD (FFFFFF) -Size 21: 11,21 BAD (FFFFFF) -Size 22: 11,22 BAD (FFFFFF) -Size 23: 12,23 BAD (FFFFFF) -Size 24: 12,24 BAD (FFFFFF) -Size 25: 13,25 BAD (FFFFFF) -Size 26: 13,26 BAD (FFFFFF) -Size 27: 14,27 BAD (FFFFFF) -Size 28: 14,28 BAD (FFFFFF) -Size 29: 15,29 BAD (FFFFFF) -Size 30: 15,30 BAD (FFFFFF) -Size 31: 16,31 BAD (FFFFFF) -Size 32: 16,33 BAD (FFFFFF) -Size 33: 17,33 BAD (FFFFFF) -Size 34: 17,34 BAD (FFFFFF) -Size 35: 18,35 BAD (FFFFFF) -Size 36: 18,36 BAD (FFFFFF) -Size 37: 19,37 BAD (FFFFFF) -Size 38: 19,38 BAD (FFFFFF) -Size 39: 20,39 BAD (FFFFFF) -Size 40: 20,40 BAD (FFFFFF) -Size 41: 21,41 BAD (FFFFFF) -Size 42: 21,42 BAD (FFFFFF) -Size 43: 22,43 BAD (FFFFFF) -Size 44: 22,44 BAD (FFFFFF) -Size 45: 23,45 BAD (FFFFFF) -Size 46: 23,46 BAD (FFFFFF) -Size 47: 24,47 BAD (FFFFFF) -Size 48: 24,48 BAD (FFFFFF) -Size 49: 25,49 BAD (FFFFFF) -Size 50: 25,50 BAD (FFFFFF) -Size 51: 26,51 BAD (FFFFFF) -Size 52: 26,52 BAD (FFFFFF) -Size 53: 27,53 BAD (FFFFFF) -Size 54: 27,54 BAD (FFFFFF) -Size 55: 28,55 BAD (FFFFFF) -Size 56: 28,56 BAD (FFFFFF) -Size 57: 29,57 BAD (FFFFFF) -Size 58: 29,58 BAD (FFFFFF) -Size 59: 30,59 BAD (FFFFFF) -Size 60: 30,60 BAD (FFFFFF) -Size 61: 31,61 BAD (FFFFFF) -Size 62: 31,62 BAD (FFFFFF) -Size 63: 32,63 BAD (FFFFFF) -Size 64: 32,64 BAD (FFFFFF) -Size 65: 33,65 BAD (FFFFFF) -Size 66: 33,66 BAD (FFFFFF) -Size 67: 34,67 BAD (FFFFFF) -Size 68: 34,68 BAD (FFFFFF) -Size 69: 35,69 BAD (FFFFFF) -Size 70: 35,70 BAD (FFFFFF) -Size 71: 36,71 BAD (FFFFFF) -Size 72: 36,72 BAD (FFFFFF) -Size 73: 37,73 BAD (FFFFFF) -Size 74: 37,74 BAD (FFFFFF) -Size 75: 38,75 BAD (FFFFFF) -Size 76: 38,76 BAD (FFFFFF) -Size 77: 39,77 BAD (FFFFFF) -Size 78: 39,78 BAD (FFFFFF) -Size 79: 40,79 BAD (FFFFFF) -Size 80: 40,80 BAD (FFFFFF) -Size 81: 41,81 BAD (FFFFFF) -Size 82: 41,82 BAD (FFFFFF) -Size 83: 42,83 BAD (FFFFFF) -Size 84: 42,84 BAD (FFFFFF) -Size 85: 43,85 BAD (FFFFFF) -Size 86: 43,86 BAD (FFFFFF) -Size 87: 44,87 BAD (FFFFFF) -Size 88: 44,88 BAD (FFFFFF) -Size 89: 45,89 BAD (FFFFFF) -Size 90: 45,90 BAD (FFFFFF) -Size 91: 46,91 BAD (FFFFFF) -Size 92: 46,92 BAD (FFFFFF) -Size 93: 47,93 BAD (FFFFFF) -Size 94: 47,94 BAD (FFFFFF) -Size 95: 48,95 BAD (FFFFFF) -Size 96: 48,97 BAD (FFFFFF) -Size 97: 49,97 BAD (FFFFFF) -Size 98: 49,98 BAD (FFFFFF) -Size 99: 50,99 BAD (FFFFFF) -Size 100: 50,100 BAD (FFFFFF) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,2 BAD (FFFFHH) -Size 2: 1,2 BAD (FFFFHH) -Size 3: 2,3 BAD (FFFFFF) -Size 4: 2,4 BAD (FFFFHH) -Size 5: 3,5 BAD (FFFFFF) -Size 6: 3,6 BAD (FFFFHH) -Size 7: 4,7 BAD (FFFFFF) -Size 8: 4,8 BAD (FFFFHH) -Size 9: 5,9 BAD (FFFFFF) -Size 10: 5,10 BAD (FFFFHH) -Size 11: 6,11 BAD (FFFFFF) -Size 12: 6,12 BAD (FFFFHH) -Size 13: 7,13 BAD (FFFFFF) -Size 14: 7,14 BAD (FFFFHH) -Size 15: 8,15 BAD (FFFFFF) -Size 16: 8,16 BAD (FFFFHH) -Size 17: 9,17 BAD (FFFFFF) -Size 18: 9,18 BAD (FFFFHH) -Size 19: 10,19 BAD (FFFFFF) -Size 20: 10,20 BAD (FFFFFF) -Size 21: 11,21 BAD (FFFFFF) -Size 22: 11,22 BAD (FFFFFF) -Size 23: 12,23 BAD (FFFFFF) -Size 24: 12,24 BAD (FFFFFF) -Size 25: 13,25 BAD (FFFFFF) -Size 26: 13,26 BAD (FFFFFF) -Size 27: 14,27 BAD (FFFFFF) -Size 28: 14,28 BAD (FFFFFF) -Size 29: 15,29 BAD (FFFFFF) -Size 30: 15,30 BAD (FFFFFF) -Size 31: 16,31 BAD (FFFFFF) -Size 32: 16,33 BAD (FFFFFF) -Size 33: 17,33 BAD (FFFFFF) -Size 34: 17,34 BAD (FFFFFF) -Size 35: 18,35 BAD (FFFFFF) -Size 36: 18,36 BAD (FFFFFF) -Size 37: 19,37 BAD (FFFFFF) -Size 38: 19,38 BAD (FFFFFF) -Size 39: 20,39 BAD (FFFFFF) -Size 40: 20,40 BAD (FFFFFF) -Size 41: 21,41 BAD (FFFFFF) -Size 42: 21,42 BAD (FFFFFF) -Size 43: 22,43 BAD (FFFFFF) -Size 44: 22,44 BAD (FFFFFF) -Size 45: 23,45 BAD (FFFFFF) -Size 46: 23,46 BAD (FFFFFF) -Size 47: 24,47 BAD (FFFFFF) -Size 48: 24,48 BAD (FFFFFF) -Size 49: 25,49 BAD (FFFFFF) -Size 50: 25,50 BAD (FFFFFF) -Size 51: 26,51 BAD (FFFFFF) -Size 52: 26,52 BAD (FFFFFF) -Size 53: 27,53 BAD (FFFFFF) -Size 54: 27,54 BAD (FFFFFF) -Size 55: 28,55 BAD (FFFFFF) -Size 56: 28,56 BAD (FFFFFF) -Size 57: 29,57 BAD (FFFFFF) -Size 58: 29,58 BAD (FFFFFF) -Size 59: 30,59 BAD (FFFFFF) -Size 60: 30,60 BAD (FFFFFF) -Size 61: 31,61 BAD (FFFFFF) -Size 62: 31,62 BAD (FFFFFF) -Size 63: 32,63 BAD (FFFFFF) -Size 64: 32,64 BAD (FFFFFF) -Size 65: 33,65 BAD (FFFFFF) -Size 66: 33,66 BAD (FFFFFF) -Size 67: 34,67 BAD (FFFFFF) -Size 68: 34,68 BAD (FFFFFF) -Size 69: 35,69 BAD (FFFFFF) -Size 70: 35,70 BAD (FFFFFF) -Size 71: 36,71 BAD (FFFFFF) -Size 72: 36,72 BAD (FFFFFF) -Size 73: 37,73 BAD (FFFFFF) -Size 74: 37,74 BAD (FFFFFF) -Size 75: 38,75 BAD (FFFFFF) -Size 76: 38,76 BAD (FFFFFF) -Size 77: 39,77 BAD (FFFFFF) -Size 78: 39,78 BAD (FFFFFF) -Size 79: 40,79 BAD (FFFFFF) -Size 80: 40,80 BAD (FFFFFF) -Size 81: 41,81 BAD (FFFFFF) -Size 82: 41,82 BAD (FFFFFF) -Size 83: 42,83 BAD (FFFFFF) -Size 84: 42,84 BAD (FFFFFF) -Size 85: 43,85 BAD (FFFFFF) -Size 86: 43,86 BAD (FFFFFF) -Size 87: 44,87 BAD (FFFFFF) -Size 88: 44,88 BAD (FFFFFF) -Size 89: 45,89 BAD (FFFFFF) -Size 90: 45,90 BAD (FFFFFF) -Size 91: 46,91 BAD (FFFFFF) -Size 92: 46,92 BAD (FFFFFF) -Size 93: 47,93 BAD (FFFFFF) -Size 94: 47,94 BAD (FFFFFF) -Size 95: 48,95 BAD (FFFFFF) -Size 96: 48,97 BAD (FFFFFF) -Size 97: 49,97 BAD (FFFFFF) -Size 98: 49,98 BAD (FFFFFF) -Size 99: 50,99 BAD (FFFFFF) -Size 100: 50,100 BAD (FFFFFF) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 OK (HHHFFF) -Size 4: 2,4 OK (HHHFFF) -Size 5: 3,5 OK (HHHFFF) -Size 6: 3,6 OK (HHHFFF) -Size 7: 4,7 OK (HHHFFF) -Size 8: 4,8 OK (HHHFFF) -Size 9: 5,9 OK (HHHFFF) -Size 10: 5,10 OK (HHHFFF) -Size 11: 6,11 OK (HHHFFF) -Size 12: 6,12 OK (HHHFFF) -Size 13: 7,13 OK (HHHFFF) -Size 14: 7,14 OK (HHHFFF) -Size 15: 8,15 OK (HHHFFF) -Size 16: 8,16 OK (HHHFFF) -Size 17: 9,17 OK (HHHFFF) -Size 18: 9,18 OK (HHHFFF) -Size 19: 10,19 OK (HHHFFF) -Size 20: 10,20 OK (HHHFFF) -Size 21: 11,21 OK (HHHFFF) -Size 22: 11,22 OK (HHHFFF) -Size 23: 12,23 OK (HHHFFF) -Size 24: 12,24 OK (HHHFFF) -Size 25: 13,25 OK (HHHFFF) -Size 26: 13,26 OK (HHHFFF) -Size 27: 14,27 OK (HHHFFF) -Size 28: 14,28 OK (HHHFFF) -Size 29: 15,29 OK (HHHFFF) -Size 30: 15,30 OK (HHHFFF) -Size 31: 16,31 OK (HHHFFF) -Size 32: 16,32 OK (HHHFFF) -Size 33: 17,33 OK (HHHFFF) -Size 34: 17,34 OK (HHHFFF) -Size 35: 18,35 OK (HHHFFF) -Size 36: 18,36 OK (HHHFFF) -Size 37: 19,37 OK (HHHFFF) -Size 38: 19,38 OK (HHHFFF) -Size 39: 20,39 OK (HHHFFF) -Size 40: 20,40 OK (HHHFFF) -Size 41: 21,41 OK (HHHFFF) -Size 42: 21,42 OK (HHHFFF) -Size 43: 22,43 OK (HHHFFF) -Size 44: 22,44 OK (HHHFFF) -Size 45: 23,45 OK (HHHFFF) -Size 46: 23,46 OK (HHHFFF) -Size 47: 24,47 OK (HHHFFF) -Size 48: 24,48 OK (HHHFFF) -Size 49: 25,49 OK (HHHFFF) -Size 50: 25,50 OK (HHHFFF) -Size 51: 26,51 OK (HHHFFF) -Size 52: 26,52 OK (HHHFFF) -Size 53: 27,53 OK (HHHFFF) -Size 54: 27,54 OK (HHHFFF) -Size 55: 28,55 OK (HHHFFF) -Size 56: 28,56 OK (HHHFFF) -Size 57: 29,57 OK (HHHFFF) -Size 58: 29,58 OK (HHHFFF) -Size 59: 30,59 OK (HHHFFF) -Size 60: 30,60 OK (HHHFFF) -Size 61: 31,61 OK (HHHFFF) -Size 62: 31,62 OK (HHHFFF) -Size 63: 32,63 OK (HHHFFF) -Size 64: 32,64 OK (HHHFFF) -Size 65: 33,65 OK (HHHFFF) -Size 66: 33,66 OK (HHHFFF) -Size 67: 34,67 OK (HHHFFF) -Size 68: 34,68 OK (HHHFFF) -Size 69: 35,69 OK (HHHFFF) -Size 70: 35,70 OK (HHHFFF) -Size 71: 36,71 OK (HHHFFF) -Size 72: 36,72 OK (HHHFFF) -Size 73: 37,73 OK (HHHFFF) -Size 74: 37,74 OK (HHHFFF) -Size 75: 38,75 OK (HHHFFF) -Size 76: 38,76 OK (HHHFFF) -Size 77: 39,77 OK (HHHFFF) -Size 78: 39,78 OK (HHHFFF) -Size 79: 40,79 OK (HHHFFF) -Size 80: 40,80 OK (HHHFFF) -Size 81: 41,81 OK (HHHFFF) -Size 82: 41,82 OK (HHHFFF) -Size 83: 42,83 OK (HHHFFF) -Size 84: 42,84 OK (HHHFFF) -Size 85: 43,85 OK (HHHFFF) -Size 86: 43,86 OK (HHHFFF) -Size 87: 44,87 OK (HHHFFF) -Size 88: 44,88 OK (HHHFFF) -Size 89: 45,89 OK (HHHFFF) -Size 90: 45,90 OK (HHHFFF) -Size 91: 46,91 OK (HHHFFF) -Size 92: 46,92 OK (HHHFFF) -Size 93: 47,93 OK (HHHFFF) -Size 94: 47,94 OK (HHHFFF) -Size 95: 48,95 OK (HHHFFF) -Size 96: 48,96 OK (HHHFFF) -Size 97: 49,97 OK (HHHFFF) -Size 98: 49,98 OK (HHHFFF) -Size 99: 50,99 OK (HHHFFF) -Size 100: 50,100 OK (HHHFFF) diff --git a/deps/winpty/misc/Font-Report-June2016/CP936.txt b/deps/winpty/misc/Font-Report-June2016/CP936.txt deleted file mode 100644 index 43210dac5..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP936.txt +++ /dev/null @@ -1,630 +0,0 @@ -========================================================== -Code Page 936, Chinese Simplified (China/PRC), SimSun font -========================================================== - -Options: -face-simsun -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -Vista ------ - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (HHHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (HHHFHH) -Size 8: 4,9 GOOD (HHFFFF) -Size 9: 5,10 BAD (HHHFHH) -Size 10: 5,11 GOOD (HHFFFF) -Size 11: 6,13 BAD (HHHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,15 BAD (HHHFHH) -Size 14: 7,16 GOOD (HHFFFF) -Size 15: 8,17 BAD (HHHFHH) -Size 16: 8,18 GOOD (HHFFFF) -Size 17: 9,19 BAD (HHHFHH) -Size 18: 9,21 GOOD (HHFFFF) -Size 19: 10,22 BAD (HHHFHH) -Size 20: 10,23 GOOD (HHFFFF) -Size 21: 11,24 BAD (HHHFHH) -Size 22: 11,25 GOOD (HHFFFF) -Size 23: 12,26 BAD (HHHFHH) -Size 24: 12,27 GOOD (HHFFFF) -Size 25: 13,29 BAD (HHHFHH) -Size 26: 13,30 GOOD (HHFFFF) -Size 27: 14,31 BAD (HHHFHH) -Size 28: 14,32 GOOD (HHFFFF) -Size 29: 15,33 BAD (HHHFHH) -Size 30: 15,34 GOOD (HHFFFF) -Size 31: 16,35 BAD (HHHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,38 BAD (HHHFHH) -Size 34: 17,39 GOOD (HHFFFF) -Size 35: 18,40 BAD (HHHFHH) -Size 36: 18,41 GOOD (HHFFFF) -Size 37: 19,42 BAD (HHHFHH) -Size 38: 19,43 GOOD (HHFFFF) -Size 39: 20,44 BAD (HHHFHH) -Size 40: 20,46 GOOD (HHFFFF) -Size 41: 21,47 BAD (HHHFHH) -Size 42: 21,48 GOOD (HHFFFF) -Size 43: 22,49 BAD (HHHFHH) -Size 44: 22,50 GOOD (HHFFFF) -Size 45: 23,51 BAD (HHHFHH) -Size 46: 23,52 GOOD (HHFFFF) -Size 47: 24,54 BAD (HHHFHH) -Size 48: 24,55 GOOD (HHFFFF) -Size 49: 25,56 BAD (HHHFHH) -Size 50: 25,57 GOOD (HHFFFF) -Size 51: 26,58 BAD (HHHFHH) -Size 52: 26,59 GOOD (HHFFFF) -Size 53: 27,60 BAD (HHHFHH) -Size 54: 27,62 GOOD (HHFFFF) -Size 55: 28,63 BAD (HHHFHH) -Size 56: 28,64 GOOD (HHFFFF) -Size 57: 29,65 BAD (HHHFHH) -Size 58: 29,66 GOOD (HHFFFF) -Size 59: 30,67 BAD (HHHFHH) -Size 60: 30,68 GOOD (HHFFFF) -Size 61: 31,70 BAD (HHHFHH) -Size 62: 31,71 GOOD (HHFFFF) -Size 63: 32,72 BAD (HHHFHH) -Size 64: 32,73 GOOD (HHFFFF) -Size 65: 33,74 GOOD (HHFFFF) -Size 66: 33,75 GOOD (HHFFFF) -Size 67: 34,76 GOOD (HHFFFF) -Size 68: 34,78 GOOD (HHFFFF) -Size 69: 35,79 GOOD (HHFFFF) -Size 70: 35,80 GOOD (HHFFFF) -Size 71: 36,81 GOOD (HHFFFF) -Size 72: 36,82 GOOD (HHFFFF) -Size 73: 37,83 GOOD (HHFFFF) -Size 74: 37,84 GOOD (HHFFFF) -Size 75: 38,86 GOOD (HHFFFF) -Size 76: 38,87 GOOD (HHFFFF) -Size 77: 39,88 GOOD (HHFFFF) -Size 78: 39,89 GOOD (HHFFFF) -Size 79: 40,90 GOOD (HHFFFF) -Size 80: 40,91 GOOD (HHFFFF) -Size 81: 41,92 GOOD (HHFFFF) -Size 82: 41,94 GOOD (HHFFFF) -Size 83: 42,95 GOOD (HHFFFF) -Size 84: 42,96 GOOD (HHFFFF) -Size 85: 43,97 GOOD (HHFFFF) -Size 86: 43,98 GOOD (HHFFFF) -Size 87: 44,99 GOOD (HHFFFF) -Size 88: 44,100 GOOD (HHFFFF) -Size 89: 45,102 GOOD (HHFFFF) -Size 90: 45,103 GOOD (HHFFFF) -Size 91: 46,104 GOOD (HHFFFF) -Size 92: 46,105 GOOD (HHFFFF) -Size 93: 47,106 GOOD (HHFFFF) -Size 94: 47,107 GOOD (HHFFFF) -Size 95: 48,108 GOOD (HHFFFF) -Size 96: 48,111 GOOD (HHFFFF) -Size 97: 49,111 GOOD (HHFFFF) -Size 98: 49,112 GOOD (HHFFFF) -Size 99: 50,113 GOOD (HHFFFF) -Size 100: 50,114 GOOD (HHFFFF) - -Windows 7 ---------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,9 GOOD (HHFFFF) -Size 9: 5,10 BAD (FFHFHH) -Size 10: 5,11 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,15 BAD (FFHFHH) -Size 14: 7,16 GOOD (HHFFFF) -Size 15: 8,17 BAD (FFHFHH) -Size 16: 8,18 GOOD (HHFFFF) -Size 17: 9,19 BAD (FFHFHH) -Size 18: 9,21 GOOD (HHFFFF) -Size 19: 10,22 BAD (FFHFHH) -Size 20: 10,23 GOOD (HHFFFF) -Size 21: 11,24 BAD (FFHFHH) -Size 22: 11,25 GOOD (HHFFFF) -Size 23: 12,26 BAD (FFHFHH) -Size 24: 12,27 GOOD (HHFFFF) -Size 25: 13,29 BAD (FFHFHH) -Size 26: 13,30 GOOD (HHFFFF) -Size 27: 14,31 BAD (FFHFHH) -Size 28: 14,32 GOOD (HHFFFF) -Size 29: 15,33 BAD (FFHFHH) -Size 30: 15,34 GOOD (HHFFFF) -Size 31: 16,35 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,38 BAD (FFHFHH) -Size 34: 17,39 GOOD (HHFFFF) -Size 35: 18,40 BAD (FFHFHH) -Size 36: 18,41 GOOD (HHFFFF) -Size 37: 19,42 BAD (FFHFHH) -Size 38: 19,43 GOOD (HHFFFF) -Size 39: 20,44 BAD (FFHFHH) -Size 40: 20,46 GOOD (HHFFFF) -Size 41: 21,47 BAD (FFHFHH) -Size 42: 21,48 GOOD (HHFFFF) -Size 43: 22,49 BAD (FFHFHH) -Size 44: 22,50 GOOD (HHFFFF) -Size 45: 23,51 BAD (FFHFHH) -Size 46: 23,52 GOOD (HHFFFF) -Size 47: 24,54 BAD (FFHFHH) -Size 48: 24,55 GOOD (HHFFFF) -Size 49: 25,56 BAD (FFHFHH) -Size 50: 25,57 GOOD (HHFFFF) -Size 51: 26,58 BAD (FFHFHH) -Size 52: 26,59 GOOD (HHFFFF) -Size 53: 27,60 BAD (FFHFHH) -Size 54: 27,62 GOOD (HHFFFF) -Size 55: 28,63 BAD (FFHFHH) -Size 56: 28,64 GOOD (HHFFFF) -Size 57: 29,65 BAD (FFHFHH) -Size 58: 29,66 GOOD (HHFFFF) -Size 59: 30,67 BAD (FFHFHH) -Size 60: 30,68 GOOD (HHFFFF) -Size 61: 31,70 BAD (FFHFHH) -Size 62: 31,71 GOOD (HHFFFF) -Size 63: 32,72 BAD (FFHFHH) -Size 64: 32,73 GOOD (HHFFFF) -Size 65: 33,74 GOOD (HHFFFF) -Size 66: 33,75 GOOD (HHFFFF) -Size 67: 34,76 GOOD (HHFFFF) -Size 68: 34,78 GOOD (HHFFFF) -Size 69: 35,79 GOOD (HHFFFF) -Size 70: 35,80 GOOD (HHFFFF) -Size 71: 36,81 GOOD (HHFFFF) -Size 72: 36,82 GOOD (HHFFFF) -Size 73: 37,83 GOOD (HHFFFF) -Size 74: 37,84 GOOD (HHFFFF) -Size 75: 38,86 GOOD (HHFFFF) -Size 76: 38,87 GOOD (HHFFFF) -Size 77: 39,88 GOOD (HHFFFF) -Size 78: 39,89 GOOD (HHFFFF) -Size 79: 40,90 GOOD (HHFFFF) -Size 80: 40,91 GOOD (HHFFFF) -Size 81: 41,92 GOOD (HHFFFF) -Size 82: 41,94 GOOD (HHFFFF) -Size 83: 42,95 GOOD (HHFFFF) -Size 84: 42,96 GOOD (HHFFFF) -Size 85: 43,97 GOOD (HHFFFF) -Size 86: 43,98 GOOD (HHFFFF) -Size 87: 44,99 GOOD (HHFFFF) -Size 88: 44,100 GOOD (HHFFFF) -Size 89: 45,102 GOOD (HHFFFF) -Size 90: 45,103 GOOD (HHFFFF) -Size 91: 46,104 GOOD (HHFFFF) -Size 92: 46,105 GOOD (HHFFFF) -Size 93: 47,106 GOOD (HHFFFF) -Size 94: 47,107 GOOD (HHFFFF) -Size 95: 48,108 GOOD (HHFFFF) -Size 96: 48,111 GOOD (HHFFFF) -Size 97: 49,111 GOOD (HHFFFF) -Size 98: 49,112 GOOD (HHFFFF) -Size 99: 50,113 GOOD (HHFFFF) -Size 100: 50,114 GOOD (HHFFFF) - -Windows 8 ---------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,9 GOOD (HHFFFF) -Size 9: 5,10 BAD (FFHFHH) -Size 10: 5,11 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,15 BAD (FFHFHH) -Size 14: 7,16 GOOD (HHFFFF) -Size 15: 8,17 BAD (FFHFHH) -Size 16: 8,18 GOOD (HHFFFF) -Size 17: 9,19 BAD (FFHFHH) -Size 18: 9,21 GOOD (HHFFFF) -Size 19: 10,22 BAD (FFHFHH) -Size 20: 10,23 GOOD (HHFFFF) -Size 21: 11,24 BAD (FFHFHH) -Size 22: 11,25 GOOD (HHFFFF) -Size 23: 12,26 BAD (FFHFHH) -Size 24: 12,27 GOOD (HHFFFF) -Size 25: 13,29 BAD (FFHFHH) -Size 26: 13,30 GOOD (HHFFFF) -Size 27: 14,31 BAD (FFHFHH) -Size 28: 14,32 GOOD (HHFFFF) -Size 29: 15,33 BAD (FFHFHH) -Size 30: 15,34 GOOD (HHFFFF) -Size 31: 16,35 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,38 BAD (FFHFHH) -Size 34: 17,39 GOOD (HHFFFF) -Size 35: 18,40 BAD (FFHFHH) -Size 36: 18,41 GOOD (HHFFFF) -Size 37: 19,42 BAD (FFHFHH) -Size 38: 19,43 GOOD (HHFFFF) -Size 39: 20,44 BAD (FFHFHH) -Size 40: 20,46 GOOD (HHFFFF) -Size 41: 21,47 BAD (FFHFHH) -Size 42: 21,48 GOOD (HHFFFF) -Size 43: 22,49 BAD (FFHFHH) -Size 44: 22,50 GOOD (HHFFFF) -Size 45: 23,51 BAD (FFHFHH) -Size 46: 23,52 GOOD (HHFFFF) -Size 47: 24,54 BAD (FFHFHH) -Size 48: 24,55 GOOD (HHFFFF) -Size 49: 25,56 BAD (FFHFHH) -Size 50: 25,57 GOOD (HHFFFF) -Size 51: 26,58 BAD (FFHFHH) -Size 52: 26,59 GOOD (HHFFFF) -Size 53: 27,60 BAD (FFHFHH) -Size 54: 27,62 GOOD (HHFFFF) -Size 55: 28,63 BAD (FFHFHH) -Size 56: 28,64 GOOD (HHFFFF) -Size 57: 29,65 BAD (FFHFHH) -Size 58: 29,66 GOOD (HHFFFF) -Size 59: 30,67 BAD (FFHFHH) -Size 60: 30,68 GOOD (HHFFFF) -Size 61: 31,70 BAD (FFHFHH) -Size 62: 31,71 GOOD (HHFFFF) -Size 63: 32,72 BAD (FFHFHH) -Size 64: 32,73 GOOD (HHFFFF) -Size 65: 33,74 GOOD (HHFFFF) -Size 66: 33,75 GOOD (HHFFFF) -Size 67: 34,76 GOOD (HHFFFF) -Size 68: 34,78 GOOD (HHFFFF) -Size 69: 35,79 GOOD (HHFFFF) -Size 70: 35,80 GOOD (HHFFFF) -Size 71: 36,81 GOOD (HHFFFF) -Size 72: 36,82 GOOD (HHFFFF) -Size 73: 37,83 GOOD (HHFFFF) -Size 74: 37,84 GOOD (HHFFFF) -Size 75: 38,86 GOOD (HHFFFF) -Size 76: 38,87 GOOD (HHFFFF) -Size 77: 39,88 GOOD (HHFFFF) -Size 78: 39,89 GOOD (HHFFFF) -Size 79: 40,90 GOOD (HHFFFF) -Size 80: 40,91 GOOD (HHFFFF) -Size 81: 41,92 GOOD (HHFFFF) -Size 82: 41,94 GOOD (HHFFFF) -Size 83: 42,95 GOOD (HHFFFF) -Size 84: 42,96 GOOD (HHFFFF) -Size 85: 43,97 GOOD (HHFFFF) -Size 86: 43,98 GOOD (HHFFFF) -Size 87: 44,99 GOOD (HHFFFF) -Size 88: 44,100 GOOD (HHFFFF) -Size 89: 45,102 GOOD (HHFFFF) -Size 90: 45,103 GOOD (HHFFFF) -Size 91: 46,104 GOOD (HHFFFF) -Size 92: 46,105 GOOD (HHFFFF) -Size 93: 47,106 GOOD (HHFFFF) -Size 94: 47,107 GOOD (HHFFFF) -Size 95: 48,108 GOOD (HHFFFF) -Size 96: 48,111 GOOD (HHFFFF) -Size 97: 49,111 GOOD (HHFFFF) -Size 98: 49,112 GOOD (HHFFFF) -Size 99: 50,113 GOOD (HHFFFF) -Size 100: 50,114 GOOD (HHFFFF) - -Windows 8.1 ------------ - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,9 GOOD (HHFFFF) -Size 9: 5,10 BAD (FFHFHH) -Size 10: 5,11 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,15 BAD (FFHFHH) -Size 14: 7,16 GOOD (HHFFFF) -Size 15: 8,17 BAD (FFHFHH) -Size 16: 8,18 GOOD (HHFFFF) -Size 17: 9,19 BAD (FFHFHH) -Size 18: 9,21 GOOD (HHFFFF) -Size 19: 10,22 BAD (FFHFHH) -Size 20: 10,23 GOOD (HHFFFF) -Size 21: 11,24 BAD (FFHFHH) -Size 22: 11,25 GOOD (HHFFFF) -Size 23: 12,26 BAD (FFHFHH) -Size 24: 12,27 GOOD (HHFFFF) -Size 25: 13,29 BAD (FFHFHH) -Size 26: 13,30 GOOD (HHFFFF) -Size 27: 14,31 BAD (FFHFHH) -Size 28: 14,32 GOOD (HHFFFF) -Size 29: 15,33 BAD (FFHFHH) -Size 30: 15,34 GOOD (HHFFFF) -Size 31: 16,35 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,38 BAD (FFHFHH) -Size 34: 17,39 GOOD (HHFFFF) -Size 35: 18,40 BAD (FFHFHH) -Size 36: 18,41 GOOD (HHFFFF) -Size 37: 19,42 BAD (FFHFHH) -Size 38: 19,43 GOOD (HHFFFF) -Size 39: 20,44 BAD (FFHFHH) -Size 40: 20,46 GOOD (HHFFFF) -Size 41: 21,47 BAD (FFHFHH) -Size 42: 21,48 GOOD (HHFFFF) -Size 43: 22,49 BAD (FFHFHH) -Size 44: 22,50 GOOD (HHFFFF) -Size 45: 23,51 BAD (FFHFHH) -Size 46: 23,52 GOOD (HHFFFF) -Size 47: 24,54 BAD (FFHFHH) -Size 48: 24,55 GOOD (HHFFFF) -Size 49: 25,56 BAD (FFHFHH) -Size 50: 25,57 GOOD (HHFFFF) -Size 51: 26,58 BAD (FFHFHH) -Size 52: 26,59 GOOD (HHFFFF) -Size 53: 27,60 BAD (FFHFHH) -Size 54: 27,62 GOOD (HHFFFF) -Size 55: 28,63 BAD (FFHFHH) -Size 56: 28,64 GOOD (HHFFFF) -Size 57: 29,65 BAD (FFHFHH) -Size 58: 29,66 GOOD (HHFFFF) -Size 59: 30,67 BAD (FFHFHH) -Size 60: 30,68 GOOD (HHFFFF) -Size 61: 31,70 BAD (FFHFHH) -Size 62: 31,71 GOOD (HHFFFF) -Size 63: 32,72 BAD (FFHFHH) -Size 64: 32,73 GOOD (HHFFFF) -Size 65: 33,74 GOOD (HHFFFF) -Size 66: 33,75 GOOD (HHFFFF) -Size 67: 34,76 GOOD (HHFFFF) -Size 68: 34,78 GOOD (HHFFFF) -Size 69: 35,79 GOOD (HHFFFF) -Size 70: 35,80 GOOD (HHFFFF) -Size 71: 36,81 GOOD (HHFFFF) -Size 72: 36,82 GOOD (HHFFFF) -Size 73: 37,83 GOOD (HHFFFF) -Size 74: 37,84 GOOD (HHFFFF) -Size 75: 38,86 GOOD (HHFFFF) -Size 76: 38,87 GOOD (HHFFFF) -Size 77: 39,88 GOOD (HHFFFF) -Size 78: 39,89 GOOD (HHFFFF) -Size 79: 40,90 GOOD (HHFFFF) -Size 80: 40,91 GOOD (HHFFFF) -Size 81: 41,92 GOOD (HHFFFF) -Size 82: 41,94 GOOD (HHFFFF) -Size 83: 42,95 GOOD (HHFFFF) -Size 84: 42,96 GOOD (HHFFFF) -Size 85: 43,97 GOOD (HHFFFF) -Size 86: 43,98 GOOD (HHFFFF) -Size 87: 44,99 GOOD (HHFFFF) -Size 88: 44,100 GOOD (HHFFFF) -Size 89: 45,102 GOOD (HHFFFF) -Size 90: 45,103 GOOD (HHFFFF) -Size 91: 46,104 GOOD (HHFFFF) -Size 92: 46,105 GOOD (HHFFFF) -Size 93: 47,106 GOOD (HHFFFF) -Size 94: 47,107 GOOD (HHFFFF) -Size 95: 48,108 GOOD (HHFFFF) -Size 96: 48,111 GOOD (HHFFFF) -Size 97: 49,111 GOOD (HHFFFF) -Size 98: 49,112 GOOD (HHFFFF) -Size 99: 50,113 GOOD (HHFFFF) -Size 100: 50,114 GOOD (HHFFFF) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,9 GOOD (HHFFFF) -Size 9: 5,10 BAD (FFHFHH) -Size 10: 5,11 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,15 BAD (FFHFHH) -Size 14: 7,16 GOOD (HHFFFF) -Size 15: 8,17 BAD (FFHFHH) -Size 16: 8,18 GOOD (HHFFFF) -Size 17: 9,19 BAD (FFHFHH) -Size 18: 9,21 GOOD (HHFFFF) -Size 19: 10,22 BAD (FFHFHH) -Size 20: 10,23 GOOD (HHFFFF) -Size 21: 11,24 BAD (FFHFHH) -Size 22: 11,25 GOOD (HHFFFF) -Size 23: 12,26 BAD (FFHFHH) -Size 24: 12,27 GOOD (HHFFFF) -Size 25: 13,29 BAD (FFHFHH) -Size 26: 13,30 GOOD (HHFFFF) -Size 27: 14,31 BAD (FFHFHH) -Size 28: 14,32 GOOD (HHFFFF) -Size 29: 15,33 BAD (FFHFHH) -Size 30: 15,34 GOOD (HHFFFF) -Size 31: 16,35 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,38 BAD (FFHFHH) -Size 34: 17,39 GOOD (HHFFFF) -Size 35: 18,40 BAD (FFHFHH) -Size 36: 18,41 GOOD (HHFFFF) -Size 37: 19,42 BAD (FFHFHH) -Size 38: 19,43 GOOD (HHFFFF) -Size 39: 20,44 BAD (FFHFHH) -Size 40: 20,46 GOOD (HHFFFF) -Size 41: 21,47 BAD (FFHFHH) -Size 42: 21,48 GOOD (HHFFFF) -Size 43: 22,49 BAD (FFHFHH) -Size 44: 22,50 GOOD (HHFFFF) -Size 45: 23,51 BAD (FFHFHH) -Size 46: 23,52 GOOD (HHFFFF) -Size 47: 24,54 BAD (FFHFHH) -Size 48: 24,55 GOOD (HHFFFF) -Size 49: 25,56 BAD (FFHFHH) -Size 50: 25,57 GOOD (HHFFFF) -Size 51: 26,58 BAD (FFHFHH) -Size 52: 26,59 GOOD (HHFFFF) -Size 53: 27,60 BAD (FFHFHH) -Size 54: 27,62 GOOD (HHFFFF) -Size 55: 28,63 BAD (FFHFHH) -Size 56: 28,64 GOOD (HHFFFF) -Size 57: 29,65 BAD (FFHFHH) -Size 58: 29,66 GOOD (HHFFFF) -Size 59: 30,67 BAD (FFHFHH) -Size 60: 30,68 GOOD (HHFFFF) -Size 61: 31,70 BAD (FFHFHH) -Size 62: 31,71 GOOD (HHFFFF) -Size 63: 32,72 BAD (FFHFHH) -Size 64: 32,73 GOOD (HHFFFF) -Size 65: 33,74 GOOD (HHFFFF) -Size 66: 33,75 GOOD (HHFFFF) -Size 67: 34,76 GOOD (HHFFFF) -Size 68: 34,78 GOOD (HHFFFF) -Size 69: 35,79 GOOD (HHFFFF) -Size 70: 35,80 GOOD (HHFFFF) -Size 71: 36,81 GOOD (HHFFFF) -Size 72: 36,82 GOOD (HHFFFF) -Size 73: 37,83 GOOD (HHFFFF) -Size 74: 37,84 GOOD (HHFFFF) -Size 75: 38,86 GOOD (HHFFFF) -Size 76: 38,87 GOOD (HHFFFF) -Size 77: 39,88 GOOD (HHFFFF) -Size 78: 39,89 GOOD (HHFFFF) -Size 79: 40,90 GOOD (HHFFFF) -Size 80: 40,91 GOOD (HHFFFF) -Size 81: 41,92 GOOD (HHFFFF) -Size 82: 41,94 GOOD (HHFFFF) -Size 83: 42,95 GOOD (HHFFFF) -Size 84: 42,96 GOOD (HHFFFF) -Size 85: 43,97 GOOD (HHFFFF) -Size 86: 43,98 GOOD (HHFFFF) -Size 87: 44,99 GOOD (HHFFFF) -Size 88: 44,100 GOOD (HHFFFF) -Size 89: 45,102 GOOD (HHFFFF) -Size 90: 45,103 GOOD (HHFFFF) -Size 91: 46,104 GOOD (HHFFFF) -Size 92: 46,105 GOOD (HHFFFF) -Size 93: 47,106 GOOD (HHFFFF) -Size 94: 47,107 GOOD (HHFFFF) -Size 95: 48,108 GOOD (HHFFFF) -Size 96: 48,111 GOOD (HHFFFF) -Size 97: 49,111 GOOD (HHFFFF) -Size 98: 49,112 GOOD (HHFFFF) -Size 99: 50,113 GOOD (HHFFFF) -Size 100: 50,114 GOOD (HHFFFF) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 GOOD (HHFFFF) -Size 4: 2,4 GOOD (HHFFFF) -Size 5: 3,5 GOOD (HHFFFF) -Size 6: 3,6 GOOD (HHFFFF) -Size 7: 4,7 GOOD (HHFFFF) -Size 8: 4,8 GOOD (HHFFFF) -Size 9: 5,9 GOOD (HHFFFF) -Size 10: 5,10 GOOD (HHFFFF) -Size 11: 6,11 GOOD (HHFFFF) -Size 12: 6,12 GOOD (HHFFFF) -Size 13: 7,13 GOOD (HHFFFF) -Size 14: 7,14 GOOD (HHFFFF) -Size 15: 8,15 GOOD (HHFFFF) -Size 16: 8,16 GOOD (HHFFFF) -Size 17: 9,17 GOOD (HHFFFF) -Size 18: 9,18 GOOD (HHFFFF) -Size 19: 10,19 GOOD (HHFFFF) -Size 20: 10,20 GOOD (HHFFFF) -Size 21: 11,21 GOOD (HHFFFF) -Size 22: 11,22 GOOD (HHFFFF) -Size 23: 12,23 GOOD (HHFFFF) -Size 24: 12,24 GOOD (HHFFFF) -Size 25: 13,25 GOOD (HHFFFF) -Size 26: 13,26 GOOD (HHFFFF) -Size 27: 14,27 GOOD (HHFFFF) -Size 28: 14,28 GOOD (HHFFFF) -Size 29: 15,29 GOOD (HHFFFF) -Size 30: 15,30 GOOD (HHFFFF) -Size 31: 16,31 GOOD (HHFFFF) -Size 32: 16,32 GOOD (HHFFFF) -Size 33: 17,33 GOOD (HHFFFF) -Size 34: 17,34 GOOD (HHFFFF) -Size 35: 18,35 GOOD (HHFFFF) -Size 36: 18,36 GOOD (HHFFFF) -Size 37: 19,37 GOOD (HHFFFF) -Size 38: 19,38 GOOD (HHFFFF) -Size 39: 20,39 GOOD (HHFFFF) -Size 40: 20,40 GOOD (HHFFFF) -Size 41: 21,41 GOOD (HHFFFF) -Size 42: 21,42 GOOD (HHFFFF) -Size 43: 22,43 GOOD (HHFFFF) -Size 44: 22,44 GOOD (HHFFFF) -Size 45: 23,45 GOOD (HHFFFF) -Size 46: 23,46 GOOD (HHFFFF) -Size 47: 24,47 GOOD (HHFFFF) -Size 48: 24,48 GOOD (HHFFFF) -Size 49: 25,49 GOOD (HHFFFF) -Size 50: 25,50 GOOD (HHFFFF) -Size 51: 26,51 GOOD (HHFFFF) -Size 52: 26,52 GOOD (HHFFFF) -Size 53: 27,53 GOOD (HHFFFF) -Size 54: 27,54 GOOD (HHFFFF) -Size 55: 28,55 GOOD (HHFFFF) -Size 56: 28,56 GOOD (HHFFFF) -Size 57: 29,57 GOOD (HHFFFF) -Size 58: 29,58 GOOD (HHFFFF) -Size 59: 30,59 GOOD (HHFFFF) -Size 60: 30,60 GOOD (HHFFFF) -Size 61: 31,61 GOOD (HHFFFF) -Size 62: 31,62 GOOD (HHFFFF) -Size 63: 32,63 GOOD (HHFFFF) -Size 64: 32,64 GOOD (HHFFFF) -Size 65: 33,65 GOOD (HHFFFF) -Size 66: 33,66 GOOD (HHFFFF) -Size 67: 34,67 GOOD (HHFFFF) -Size 68: 34,68 GOOD (HHFFFF) -Size 69: 35,69 GOOD (HHFFFF) -Size 70: 35,70 GOOD (HHFFFF) -Size 71: 36,71 GOOD (HHFFFF) -Size 72: 36,72 GOOD (HHFFFF) -Size 73: 37,73 GOOD (HHFFFF) -Size 74: 37,74 GOOD (HHFFFF) -Size 75: 38,75 GOOD (HHFFFF) -Size 76: 38,76 GOOD (HHFFFF) -Size 77: 39,77 GOOD (HHFFFF) -Size 78: 39,78 GOOD (HHFFFF) -Size 79: 40,79 GOOD (HHFFFF) -Size 80: 40,80 GOOD (HHFFFF) -Size 81: 41,81 GOOD (HHFFFF) -Size 82: 41,82 GOOD (HHFFFF) -Size 83: 42,83 GOOD (HHFFFF) -Size 84: 42,84 GOOD (HHFFFF) -Size 85: 43,85 GOOD (HHFFFF) -Size 86: 43,86 GOOD (HHFFFF) -Size 87: 44,87 GOOD (HHFFFF) -Size 88: 44,88 GOOD (HHFFFF) -Size 89: 45,89 GOOD (HHFFFF) -Size 90: 45,90 GOOD (HHFFFF) -Size 91: 46,91 GOOD (HHFFFF) -Size 92: 46,92 GOOD (HHFFFF) -Size 93: 47,93 GOOD (HHFFFF) -Size 94: 47,94 GOOD (HHFFFF) -Size 95: 48,95 GOOD (HHFFFF) -Size 96: 48,96 GOOD (HHFFFF) -Size 97: 49,97 GOOD (HHFFFF) -Size 98: 49,98 GOOD (HHFFFF) -Size 99: 50,99 GOOD (HHFFFF) -Size 100: 50,100 GOOD (HHFFFF) diff --git a/deps/winpty/misc/Font-Report-June2016/CP949.txt b/deps/winpty/misc/Font-Report-June2016/CP949.txt deleted file mode 100644 index 2f0ea1e7c..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP949.txt +++ /dev/null @@ -1,630 +0,0 @@ -===================================== -Code Page 949, Korean, GulimChe font -===================================== - -Options: -face-gulimche -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -Vista ------ - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,5 OK (HHHFFF) -Size 5: 3,6 BAD (HHHFHH) -Size 6: 3,7 OK (HHHFFF) -Size 7: 4,8 BAD (HHHFHH) -Size 8: 4,9 OK (HHHFFF) -Size 9: 5,10 BAD (HHHFHH) -Size 10: 5,11 OK (HHHFFF) -Size 11: 6,13 BAD (HHHFHH) -Size 12: 6,14 OK (HHHFFF) -Size 13: 7,15 BAD (HHHFHH) -Size 14: 7,16 OK (HHHFFF) -Size 15: 8,17 BAD (HHHFHH) -Size 16: 8,18 OK (HHHFFF) -Size 17: 9,20 BAD (HHHFHH) -Size 18: 9,21 OK (HHHFFF) -Size 19: 10,22 BAD (HHHFHH) -Size 20: 10,23 OK (HHHFFF) -Size 21: 11,24 BAD (HHHFHH) -Size 22: 11,25 OK (HHHFFF) -Size 23: 12,26 BAD (HHHFHH) -Size 24: 12,28 OK (HHHFFF) -Size 25: 13,29 BAD (HHHFHH) -Size 26: 13,30 OK (HHHFFF) -Size 27: 14,31 BAD (HHHFHH) -Size 28: 14,32 OK (HHHFFF) -Size 29: 15,33 BAD (HHHFHH) -Size 30: 15,34 OK (HHHFFF) -Size 31: 16,36 BAD (HHHFHH) -Size 32: 16,37 OK (HHHFFF) -Size 33: 17,38 BAD (HHHFHH) -Size 34: 17,39 OK (HHHFFF) -Size 35: 18,40 BAD (HHHFHH) -Size 36: 18,41 OK (HHHFFF) -Size 37: 19,42 BAD (HHHFHH) -Size 38: 19,44 OK (HHHFFF) -Size 39: 20,45 BAD (HHHFHH) -Size 40: 20,46 OK (HHHFFF) -Size 41: 21,47 BAD (HHHFHH) -Size 42: 21,48 OK (HHHFFF) -Size 43: 22,49 BAD (HHHFHH) -Size 44: 22,51 OK (HHHFFF) -Size 45: 23,52 BAD (HHHFHH) -Size 46: 23,53 OK (HHHFFF) -Size 47: 24,54 BAD (HHHFHH) -Size 48: 24,55 OK (HHHFFF) -Size 49: 25,56 BAD (HHHFHH) -Size 50: 25,57 OK (HHHFFF) -Size 51: 26,59 BAD (HHHFHH) -Size 52: 26,60 OK (HHHFFF) -Size 53: 27,61 BAD (HHHFHH) -Size 54: 27,62 OK (HHHFFF) -Size 55: 28,63 BAD (HHHFHH) -Size 56: 28,64 OK (HHHFFF) -Size 57: 29,65 BAD (HHHFHH) -Size 58: 29,67 OK (HHHFFF) -Size 59: 30,68 BAD (HHHFHH) -Size 60: 30,69 OK (HHHFFF) -Size 61: 31,70 BAD (HHHFHH) -Size 62: 31,71 OK (HHHFFF) -Size 63: 32,72 BAD (HHHFHH) -Size 64: 32,74 OK (HHHFFF) -Size 65: 33,75 BAD (HHHFHH) -Size 66: 33,76 OK (HHHFFF) -Size 67: 34,77 BAD (HHHFHH) -Size 68: 34,78 OK (HHHFFF) -Size 69: 35,79 BAD (HHHFHH) -Size 70: 35,80 OK (HHHFFF) -Size 71: 36,82 BAD (HHHFHH) -Size 72: 36,83 OK (HHHFFF) -Size 73: 37,84 BAD (HHHFHH) -Size 74: 37,85 OK (HHHFFF) -Size 75: 38,86 BAD (HHHFHH) -Size 76: 38,87 OK (HHHFFF) -Size 77: 39,88 BAD (HHHFHH) -Size 78: 39,90 OK (HHHFFF) -Size 79: 40,91 BAD (HHHFHH) -Size 80: 40,92 OK (HHHFFF) -Size 81: 41,93 BAD (HHHFHH) -Size 82: 41,94 OK (HHHFFF) -Size 83: 42,95 BAD (HHHFHH) -Size 84: 42,96 OK (HHHFFF) -Size 85: 43,98 BAD (HHHFHH) -Size 86: 43,99 OK (HHHFFF) -Size 87: 44,100 BAD (HHHFHH) -Size 88: 44,101 OK (HHHFFF) -Size 89: 45,102 BAD (HHHFHH) -Size 90: 45,103 OK (HHHFFF) -Size 91: 46,105 BAD (HHHFHH) -Size 92: 46,106 OK (HHHFFF) -Size 93: 47,107 BAD (HHHFHH) -Size 94: 47,108 OK (HHHFFF) -Size 95: 48,109 BAD (HHHFHH) -Size 96: 48,110 OK (HHHFFF) -Size 97: 49,111 BAD (HHHFHH) -Size 98: 49,113 OK (HHHFFF) -Size 99: 50,114 BAD (HHHFHH) -Size 100: 50,115 OK (HHHFFF) - -Windows 7 ---------- - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,5 OK (HHHFFF) -Size 5: 3,6 BAD (FFFFHH) -Size 6: 3,7 OK (HHHFFF) -Size 7: 4,8 BAD (FFFFHH) -Size 8: 4,9 OK (HHHFFF) -Size 9: 5,10 BAD (FFFFHH) -Size 10: 5,11 OK (HHHFFF) -Size 11: 6,13 BAD (FFFFHH) -Size 12: 6,14 OK (HHHFFF) -Size 13: 7,15 BAD (FFFFHH) -Size 14: 7,16 OK (HHHFFF) -Size 15: 8,17 BAD (FFFFHH) -Size 16: 8,18 OK (HHHFFF) -Size 17: 9,20 BAD (FFFFHH) -Size 18: 9,21 OK (HHHFFF) -Size 19: 10,22 BAD (FFFFHH) -Size 20: 10,23 OK (HHHFFF) -Size 21: 11,24 BAD (FFFFHH) -Size 22: 11,25 OK (HHHFFF) -Size 23: 12,26 BAD (FFFFHH) -Size 24: 12,28 OK (HHHFFF) -Size 25: 13,29 BAD (FFFFHH) -Size 26: 13,30 OK (HHHFFF) -Size 27: 14,31 BAD (FFFFHH) -Size 28: 14,32 OK (HHHFFF) -Size 29: 15,33 BAD (FFFFHH) -Size 30: 15,34 OK (HHHFFF) -Size 31: 16,36 BAD (FFFFHH) -Size 32: 16,37 OK (HHHFFF) -Size 33: 17,38 BAD (FFFFHH) -Size 34: 17,39 OK (HHHFFF) -Size 35: 18,40 BAD (FFFFHH) -Size 36: 18,41 OK (HHHFFF) -Size 37: 19,42 BAD (FFFFHH) -Size 38: 19,44 OK (HHHFFF) -Size 39: 20,45 BAD (FFFFHH) -Size 40: 20,46 OK (HHHFFF) -Size 41: 21,47 BAD (FFFFHH) -Size 42: 21,48 OK (HHHFFF) -Size 43: 22,49 BAD (FFFFHH) -Size 44: 22,51 OK (HHHFFF) -Size 45: 23,52 BAD (FFFFHH) -Size 46: 23,53 OK (HHHFFF) -Size 47: 24,54 BAD (FFFFHH) -Size 48: 24,55 OK (HHHFFF) -Size 49: 25,56 BAD (FFFFHH) -Size 50: 25,57 OK (HHHFFF) -Size 51: 26,59 BAD (FFFFHH) -Size 52: 26,60 OK (HHHFFF) -Size 53: 27,61 BAD (FFFFHH) -Size 54: 27,62 OK (HHHFFF) -Size 55: 28,63 BAD (FFFFHH) -Size 56: 28,64 OK (HHHFFF) -Size 57: 29,65 BAD (FFFFHH) -Size 58: 29,67 OK (HHHFFF) -Size 59: 30,68 BAD (FFFFHH) -Size 60: 30,69 OK (HHHFFF) -Size 61: 31,70 BAD (FFFFHH) -Size 62: 31,71 OK (HHHFFF) -Size 63: 32,72 BAD (FFFFHH) -Size 64: 32,74 OK (HHHFFF) -Size 65: 33,75 BAD (FFFFHH) -Size 66: 33,76 OK (HHHFFF) -Size 67: 34,77 BAD (FFFFHH) -Size 68: 34,78 OK (HHHFFF) -Size 69: 35,79 BAD (FFFFHH) -Size 70: 35,80 OK (HHHFFF) -Size 71: 36,82 BAD (FFFFHH) -Size 72: 36,83 OK (HHHFFF) -Size 73: 37,84 BAD (FFFFHH) -Size 74: 37,85 OK (HHHFFF) -Size 75: 38,86 BAD (FFFFHH) -Size 76: 38,87 OK (HHHFFF) -Size 77: 39,88 BAD (FFFFHH) -Size 78: 39,90 OK (HHHFFF) -Size 79: 40,91 BAD (FFFFHH) -Size 80: 40,92 OK (HHHFFF) -Size 81: 41,93 BAD (FFFFHH) -Size 82: 41,94 OK (HHHFFF) -Size 83: 42,95 BAD (FFFFHH) -Size 84: 42,96 OK (HHHFFF) -Size 85: 43,98 BAD (FFFFHH) -Size 86: 43,99 OK (HHHFFF) -Size 87: 44,100 BAD (FFFFHH) -Size 88: 44,101 OK (HHHFFF) -Size 89: 45,102 BAD (FFFFHH) -Size 90: 45,103 OK (HHHFFF) -Size 91: 46,105 BAD (FFFFHH) -Size 92: 46,106 OK (HHHFFF) -Size 93: 47,107 BAD (FFFFHH) -Size 94: 47,108 OK (HHHFFF) -Size 95: 48,109 BAD (FFFFHH) -Size 96: 48,110 OK (HHHFFF) -Size 97: 49,111 BAD (FFFFHH) -Size 98: 49,113 OK (HHHFFF) -Size 99: 50,114 BAD (FFFFHH) -Size 100: 50,115 OK (HHHFFF) - -Windows 8 ---------- - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,5 OK (HHHFFF) -Size 5: 3,6 BAD (FFFFHH) -Size 6: 3,7 OK (HHHFFF) -Size 7: 4,8 BAD (FFFFHH) -Size 8: 4,9 OK (HHHFFF) -Size 9: 5,10 BAD (FFFFHH) -Size 10: 5,11 OK (HHHFFF) -Size 11: 6,13 BAD (FFFFHH) -Size 12: 6,14 OK (HHHFFF) -Size 13: 7,15 BAD (FFFFHH) -Size 14: 7,16 OK (HHHFFF) -Size 15: 8,17 BAD (FFFFHH) -Size 16: 8,18 OK (HHHFFF) -Size 17: 9,20 BAD (FFFFHH) -Size 18: 9,21 OK (HHHFFF) -Size 19: 10,22 BAD (FFFFHH) -Size 20: 10,23 OK (HHHFFF) -Size 21: 11,24 BAD (FFFFHH) -Size 22: 11,25 OK (HHHFFF) -Size 23: 12,26 BAD (FFFFHH) -Size 24: 12,28 OK (HHHFFF) -Size 25: 13,29 BAD (FFFFHH) -Size 26: 13,30 OK (HHHFFF) -Size 27: 14,31 BAD (FFFFHH) -Size 28: 14,32 OK (HHHFFF) -Size 29: 15,33 BAD (FFFFHH) -Size 30: 15,34 OK (HHHFFF) -Size 31: 16,36 BAD (FFFFHH) -Size 32: 16,37 OK (HHHFFF) -Size 33: 17,38 BAD (FFFFHH) -Size 34: 17,39 OK (HHHFFF) -Size 35: 18,40 BAD (FFFFHH) -Size 36: 18,41 OK (HHHFFF) -Size 37: 19,42 BAD (FFFFHH) -Size 38: 19,44 OK (HHHFFF) -Size 39: 20,45 BAD (FFFFHH) -Size 40: 20,46 OK (HHHFFF) -Size 41: 21,47 BAD (FFFFHH) -Size 42: 21,48 OK (HHHFFF) -Size 43: 22,49 BAD (FFFFHH) -Size 44: 22,51 OK (HHHFFF) -Size 45: 23,52 BAD (FFFFHH) -Size 46: 23,53 OK (HHHFFF) -Size 47: 24,54 BAD (FFFFHH) -Size 48: 24,55 OK (HHHFFF) -Size 49: 25,56 BAD (FFFFHH) -Size 50: 25,57 OK (HHHFFF) -Size 51: 26,59 BAD (FFFFHH) -Size 52: 26,60 OK (HHHFFF) -Size 53: 27,61 BAD (FFFFHH) -Size 54: 27,62 OK (HHHFFF) -Size 55: 28,63 BAD (FFFFHH) -Size 56: 28,64 OK (HHHFFF) -Size 57: 29,65 BAD (FFFFHH) -Size 58: 29,67 OK (HHHFFF) -Size 59: 30,68 BAD (FFFFHH) -Size 60: 30,69 OK (HHHFFF) -Size 61: 31,70 BAD (FFFFHH) -Size 62: 31,71 OK (HHHFFF) -Size 63: 32,72 BAD (FFFFHH) -Size 64: 32,74 OK (HHHFFF) -Size 65: 33,75 BAD (FFFFHH) -Size 66: 33,76 OK (HHHFFF) -Size 67: 34,77 BAD (FFFFHH) -Size 68: 34,78 OK (HHHFFF) -Size 69: 35,79 BAD (FFFFHH) -Size 70: 35,80 OK (HHHFFF) -Size 71: 36,82 BAD (FFFFHH) -Size 72: 36,83 OK (HHHFFF) -Size 73: 37,84 BAD (FFFFHH) -Size 74: 37,85 OK (HHHFFF) -Size 75: 38,86 BAD (FFFFHH) -Size 76: 38,87 OK (HHHFFF) -Size 77: 39,88 BAD (FFFFHH) -Size 78: 39,90 OK (HHHFFF) -Size 79: 40,91 BAD (FFFFHH) -Size 80: 40,92 OK (HHHFFF) -Size 81: 41,93 BAD (FFFFHH) -Size 82: 41,94 OK (HHHFFF) -Size 83: 42,95 BAD (FFFFHH) -Size 84: 42,96 OK (HHHFFF) -Size 85: 43,98 BAD (FFFFHH) -Size 86: 43,99 OK (HHHFFF) -Size 87: 44,100 BAD (FFFFHH) -Size 88: 44,101 OK (HHHFFF) -Size 89: 45,102 BAD (FFFFHH) -Size 90: 45,103 OK (HHHFFF) -Size 91: 46,105 BAD (FFFFHH) -Size 92: 46,106 OK (HHHFFF) -Size 93: 47,107 BAD (FFFFHH) -Size 94: 47,108 OK (HHHFFF) -Size 95: 48,109 BAD (FFFFHH) -Size 96: 48,110 OK (HHHFFF) -Size 97: 49,111 BAD (FFFFHH) -Size 98: 49,113 OK (HHHFFF) -Size 99: 50,114 BAD (FFFFHH) -Size 100: 50,115 OK (HHHFFF) - -Windows 8.1 ------------ - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,5 OK (HHHFFF) -Size 5: 3,6 BAD (FFFFHH) -Size 6: 3,7 OK (HHHFFF) -Size 7: 4,8 BAD (FFFFHH) -Size 8: 4,9 OK (HHHFFF) -Size 9: 5,10 BAD (FFFFHH) -Size 10: 5,11 OK (HHHFFF) -Size 11: 6,13 BAD (FFFFHH) -Size 12: 6,14 OK (HHHFFF) -Size 13: 7,15 BAD (FFFFHH) -Size 14: 7,16 OK (HHHFFF) -Size 15: 8,17 BAD (FFFFHH) -Size 16: 8,18 OK (HHHFFF) -Size 17: 9,20 BAD (FFFFHH) -Size 18: 9,21 OK (HHHFFF) -Size 19: 10,22 BAD (FFFFHH) -Size 20: 10,23 OK (HHHFFF) -Size 21: 11,24 BAD (FFFFHH) -Size 22: 11,25 OK (HHHFFF) -Size 23: 12,26 BAD (FFFFHH) -Size 24: 12,28 OK (HHHFFF) -Size 25: 13,29 BAD (FFFFHH) -Size 26: 13,30 OK (HHHFFF) -Size 27: 14,31 BAD (FFFFHH) -Size 28: 14,32 OK (HHHFFF) -Size 29: 15,33 BAD (FFFFHH) -Size 30: 15,34 OK (HHHFFF) -Size 31: 16,36 BAD (FFFFHH) -Size 32: 16,37 OK (HHHFFF) -Size 33: 17,38 BAD (FFFFHH) -Size 34: 17,39 OK (HHHFFF) -Size 35: 18,40 BAD (FFFFHH) -Size 36: 18,41 OK (HHHFFF) -Size 37: 19,42 BAD (FFFFHH) -Size 38: 19,44 OK (HHHFFF) -Size 39: 20,45 BAD (FFFFHH) -Size 40: 20,46 OK (HHHFFF) -Size 41: 21,47 BAD (FFFFHH) -Size 42: 21,48 OK (HHHFFF) -Size 43: 22,49 BAD (FFFFHH) -Size 44: 22,51 OK (HHHFFF) -Size 45: 23,52 BAD (FFFFHH) -Size 46: 23,53 OK (HHHFFF) -Size 47: 24,54 BAD (FFFFHH) -Size 48: 24,55 OK (HHHFFF) -Size 49: 25,56 BAD (FFFFHH) -Size 50: 25,57 OK (HHHFFF) -Size 51: 26,59 BAD (FFFFHH) -Size 52: 26,60 OK (HHHFFF) -Size 53: 27,61 BAD (FFFFHH) -Size 54: 27,62 OK (HHHFFF) -Size 55: 28,63 BAD (FFFFHH) -Size 56: 28,64 OK (HHHFFF) -Size 57: 29,65 BAD (FFFFHH) -Size 58: 29,67 OK (HHHFFF) -Size 59: 30,68 BAD (FFFFHH) -Size 60: 30,69 OK (HHHFFF) -Size 61: 31,70 BAD (FFFFHH) -Size 62: 31,71 OK (HHHFFF) -Size 63: 32,72 BAD (FFFFHH) -Size 64: 32,74 OK (HHHFFF) -Size 65: 33,75 BAD (FFFFHH) -Size 66: 33,76 OK (HHHFFF) -Size 67: 34,77 BAD (FFFFHH) -Size 68: 34,78 OK (HHHFFF) -Size 69: 35,79 BAD (FFFFHH) -Size 70: 35,80 OK (HHHFFF) -Size 71: 36,82 BAD (FFFFHH) -Size 72: 36,83 OK (HHHFFF) -Size 73: 37,84 BAD (FFFFHH) -Size 74: 37,85 OK (HHHFFF) -Size 75: 38,86 BAD (FFFFHH) -Size 76: 38,87 OK (HHHFFF) -Size 77: 39,88 BAD (FFFFHH) -Size 78: 39,90 OK (HHHFFF) -Size 79: 40,91 BAD (FFFFHH) -Size 80: 40,92 OK (HHHFFF) -Size 81: 41,93 BAD (FFFFHH) -Size 82: 41,94 OK (HHHFFF) -Size 83: 42,95 BAD (FFFFHH) -Size 84: 42,96 OK (HHHFFF) -Size 85: 43,98 BAD (FFFFHH) -Size 86: 43,99 OK (HHHFFF) -Size 87: 44,100 BAD (FFFFHH) -Size 88: 44,101 OK (HHHFFF) -Size 89: 45,102 BAD (FFFFHH) -Size 90: 45,103 OK (HHHFFF) -Size 91: 46,105 BAD (FFFFHH) -Size 92: 46,106 OK (HHHFFF) -Size 93: 47,107 BAD (FFFFHH) -Size 94: 47,108 OK (HHHFFF) -Size 95: 48,109 BAD (FFFFHH) -Size 96: 48,110 OK (HHHFFF) -Size 97: 49,111 BAD (FFFFHH) -Size 98: 49,113 OK (HHHFFF) -Size 99: 50,114 BAD (FFFFHH) -Size 100: 50,115 OK (HHHFFF) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,2 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 BAD (FFFFHH) -Size 4: 2,5 OK (HHHFFF) -Size 5: 3,6 BAD (FFFFHH) -Size 6: 3,7 OK (HHHFFF) -Size 7: 4,8 BAD (FFFFHH) -Size 8: 4,9 OK (HHHFFF) -Size 9: 5,10 BAD (FFFFHH) -Size 10: 5,11 OK (HHHFFF) -Size 11: 6,13 BAD (FFFFHH) -Size 12: 6,14 OK (HHHFFF) -Size 13: 7,15 BAD (FFFFHH) -Size 14: 7,16 OK (HHHFFF) -Size 15: 8,17 BAD (FFFFHH) -Size 16: 8,18 OK (HHHFFF) -Size 17: 9,20 BAD (FFFFHH) -Size 18: 9,21 OK (HHHFFF) -Size 19: 10,22 BAD (FFFFHH) -Size 20: 10,23 OK (HHHFFF) -Size 21: 11,24 BAD (FFFFHH) -Size 22: 11,25 OK (HHHFFF) -Size 23: 12,26 BAD (FFFFHH) -Size 24: 12,28 OK (HHHFFF) -Size 25: 13,29 BAD (FFFFHH) -Size 26: 13,30 OK (HHHFFF) -Size 27: 14,31 BAD (FFFFHH) -Size 28: 14,32 OK (HHHFFF) -Size 29: 15,33 BAD (FFFFHH) -Size 30: 15,34 OK (HHHFFF) -Size 31: 16,36 BAD (FFFFHH) -Size 32: 16,37 OK (HHHFFF) -Size 33: 17,38 BAD (FFFFHH) -Size 34: 17,39 OK (HHHFFF) -Size 35: 18,40 BAD (FFFFHH) -Size 36: 18,41 OK (HHHFFF) -Size 37: 19,42 BAD (FFFFHH) -Size 38: 19,44 OK (HHHFFF) -Size 39: 20,45 BAD (FFFFHH) -Size 40: 20,46 OK (HHHFFF) -Size 41: 21,47 BAD (FFFFHH) -Size 42: 21,48 OK (HHHFFF) -Size 43: 22,49 BAD (FFFFHH) -Size 44: 22,51 OK (HHHFFF) -Size 45: 23,52 BAD (FFFFHH) -Size 46: 23,53 OK (HHHFFF) -Size 47: 24,54 BAD (FFFFHH) -Size 48: 24,55 OK (HHHFFF) -Size 49: 25,56 BAD (FFFFHH) -Size 50: 25,57 OK (HHHFFF) -Size 51: 26,59 BAD (FFFFHH) -Size 52: 26,60 OK (HHHFFF) -Size 53: 27,61 BAD (FFFFHH) -Size 54: 27,62 OK (HHHFFF) -Size 55: 28,63 BAD (FFFFHH) -Size 56: 28,64 OK (HHHFFF) -Size 57: 29,65 BAD (FFFFHH) -Size 58: 29,67 OK (HHHFFF) -Size 59: 30,68 BAD (FFFFHH) -Size 60: 30,69 OK (HHHFFF) -Size 61: 31,70 BAD (FFFFHH) -Size 62: 31,71 OK (HHHFFF) -Size 63: 32,72 BAD (FFFFHH) -Size 64: 32,74 OK (HHHFFF) -Size 65: 33,75 BAD (FFFFHH) -Size 66: 33,76 OK (HHHFFF) -Size 67: 34,77 BAD (FFFFHH) -Size 68: 34,78 OK (HHHFFF) -Size 69: 35,79 BAD (FFFFHH) -Size 70: 35,80 OK (HHHFFF) -Size 71: 36,82 BAD (FFFFHH) -Size 72: 36,83 OK (HHHFFF) -Size 73: 37,84 BAD (FFFFHH) -Size 74: 37,85 OK (HHHFFF) -Size 75: 38,86 BAD (FFFFHH) -Size 76: 38,87 OK (HHHFFF) -Size 77: 39,88 BAD (FFFFHH) -Size 78: 39,90 OK (HHHFFF) -Size 79: 40,91 BAD (FFFFHH) -Size 80: 40,92 OK (HHHFFF) -Size 81: 41,93 BAD (FFFFHH) -Size 82: 41,94 OK (HHHFFF) -Size 83: 42,95 BAD (FFFFHH) -Size 84: 42,96 OK (HHHFFF) -Size 85: 43,98 BAD (FFFFHH) -Size 86: 43,99 OK (HHHFFF) -Size 87: 44,100 BAD (FFFFHH) -Size 88: 44,101 OK (HHHFFF) -Size 89: 45,102 BAD (FFFFHH) -Size 90: 45,103 OK (HHHFFF) -Size 91: 46,105 BAD (FFFFHH) -Size 92: 46,106 OK (HHHFFF) -Size 93: 47,107 BAD (FFFFHH) -Size 94: 47,108 OK (HHHFFF) -Size 95: 48,109 BAD (FFFFHH) -Size 96: 48,110 OK (HHHFFF) -Size 97: 49,111 BAD (FFFFHH) -Size 98: 49,113 OK (HHHFFF) -Size 99: 50,114 BAD (FFFFHH) -Size 100: 50,115 OK (HHHFFF) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 OK (HHHFFF) -Size 2: 1,2 OK (HHHFFF) -Size 3: 2,3 OK (HHHFFF) -Size 4: 2,4 OK (HHHFFF) -Size 5: 3,5 OK (HHHFFF) -Size 6: 3,6 OK (HHHFFF) -Size 7: 4,7 OK (HHHFFF) -Size 8: 4,8 OK (HHHFFF) -Size 9: 5,9 OK (HHHFFF) -Size 10: 5,10 OK (HHHFFF) -Size 11: 6,11 OK (HHHFFF) -Size 12: 6,12 OK (HHHFFF) -Size 13: 7,13 OK (HHHFFF) -Size 14: 7,14 OK (HHHFFF) -Size 15: 8,15 OK (HHHFFF) -Size 16: 8,16 OK (HHHFFF) -Size 17: 9,17 OK (HHHFFF) -Size 18: 9,18 OK (HHHFFF) -Size 19: 10,19 OK (HHHFFF) -Size 20: 10,20 OK (HHHFFF) -Size 21: 11,21 OK (HHHFFF) -Size 22: 11,22 OK (HHHFFF) -Size 23: 12,23 OK (HHHFFF) -Size 24: 12,24 OK (HHHFFF) -Size 25: 13,25 OK (HHHFFF) -Size 26: 13,26 OK (HHHFFF) -Size 27: 14,27 OK (HHHFFF) -Size 28: 14,28 OK (HHHFFF) -Size 29: 15,29 OK (HHHFFF) -Size 30: 15,30 OK (HHHFFF) -Size 31: 16,31 OK (HHHFFF) -Size 32: 16,32 OK (HHHFFF) -Size 33: 17,33 OK (HHHFFF) -Size 34: 17,34 OK (HHHFFF) -Size 35: 18,35 OK (HHHFFF) -Size 36: 18,36 OK (HHHFFF) -Size 37: 19,37 OK (HHHFFF) -Size 38: 19,38 OK (HHHFFF) -Size 39: 20,39 OK (HHHFFF) -Size 40: 20,40 OK (HHHFFF) -Size 41: 21,41 OK (HHHFFF) -Size 42: 21,42 OK (HHHFFF) -Size 43: 22,43 OK (HHHFFF) -Size 44: 22,44 OK (HHHFFF) -Size 45: 23,45 OK (HHHFFF) -Size 46: 23,46 OK (HHHFFF) -Size 47: 24,47 OK (HHHFFF) -Size 48: 24,48 OK (HHHFFF) -Size 49: 25,49 OK (HHHFFF) -Size 50: 25,50 OK (HHHFFF) -Size 51: 26,51 OK (HHHFFF) -Size 52: 26,52 OK (HHHFFF) -Size 53: 27,53 OK (HHHFFF) -Size 54: 27,54 OK (HHHFFF) -Size 55: 28,55 OK (HHHFFF) -Size 56: 28,56 OK (HHHFFF) -Size 57: 29,57 OK (HHHFFF) -Size 58: 29,58 OK (HHHFFF) -Size 59: 30,59 OK (HHHFFF) -Size 60: 30,60 OK (HHHFFF) -Size 61: 31,61 OK (HHHFFF) -Size 62: 31,62 OK (HHHFFF) -Size 63: 32,63 OK (HHHFFF) -Size 64: 32,64 OK (HHHFFF) -Size 65: 33,65 OK (HHHFFF) -Size 66: 33,66 OK (HHHFFF) -Size 67: 34,67 OK (HHHFFF) -Size 68: 34,68 OK (HHHFFF) -Size 69: 35,69 OK (HHHFFF) -Size 70: 35,70 OK (HHHFFF) -Size 71: 36,71 OK (HHHFFF) -Size 72: 36,72 OK (HHHFFF) -Size 73: 37,73 OK (HHHFFF) -Size 74: 37,74 OK (HHHFFF) -Size 75: 38,75 OK (HHHFFF) -Size 76: 38,76 OK (HHHFFF) -Size 77: 39,77 OK (HHHFFF) -Size 78: 39,78 OK (HHHFFF) -Size 79: 40,79 OK (HHHFFF) -Size 80: 40,80 OK (HHHFFF) -Size 81: 41,81 OK (HHHFFF) -Size 82: 41,82 OK (HHHFFF) -Size 83: 42,83 OK (HHHFFF) -Size 84: 42,84 OK (HHHFFF) -Size 85: 43,85 OK (HHHFFF) -Size 86: 43,86 OK (HHHFFF) -Size 87: 44,87 OK (HHHFFF) -Size 88: 44,88 OK (HHHFFF) -Size 89: 45,89 OK (HHHFFF) -Size 90: 45,90 OK (HHHFFF) -Size 91: 46,91 OK (HHHFFF) -Size 92: 46,92 OK (HHHFFF) -Size 93: 47,93 OK (HHHFFF) -Size 94: 47,94 OK (HHHFFF) -Size 95: 48,95 OK (HHHFFF) -Size 96: 48,96 OK (HHHFFF) -Size 97: 49,97 OK (HHHFFF) -Size 98: 49,98 OK (HHHFFF) -Size 99: 50,99 OK (HHHFFF) -Size 100: 50,100 OK (HHHFFF) diff --git a/deps/winpty/misc/Font-Report-June2016/CP950.txt b/deps/winpty/misc/Font-Report-June2016/CP950.txt deleted file mode 100644 index 0dbade504..000000000 --- a/deps/winpty/misc/Font-Report-June2016/CP950.txt +++ /dev/null @@ -1,630 +0,0 @@ -=========================================================== -Code Page 950, Chinese Traditional (Taiwan), MingLight font -=========================================================== - -Options: -face-minglight -family 0x36 -Chars: A2 A3 2014 3044 30FC 4000 - -Vista ------ - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,4 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (HHHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (HHHFHH) -Size 8: 4,10 GOOD (HHFFFF) -Size 9: 5,11 BAD (HHHFHH) -Size 10: 5,12 GOOD (HHFFFF) -Size 11: 6,13 BAD (HHHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,16 BAD (HHHFHH) -Size 14: 7,17 GOOD (HHFFFF) -Size 15: 8,18 BAD (HHHFHH) -Size 16: 8,19 GOOD (HHFFFF) -Size 17: 9,20 BAD (HHHFHH) -Size 18: 9,22 GOOD (HHFFFF) -Size 19: 10,23 BAD (HHHFHH) -Size 20: 10,24 GOOD (HHFFFF) -Size 21: 11,25 BAD (HHHFHH) -Size 22: 11,26 GOOD (HHFFFF) -Size 23: 12,28 BAD (HHHFHH) -Size 24: 12,29 GOOD (HHFFFF) -Size 25: 13,30 BAD (HHHFHH) -Size 26: 13,31 GOOD (HHFFFF) -Size 27: 14,32 BAD (HHHFHH) -Size 28: 14,34 GOOD (HHFFFF) -Size 29: 15,35 BAD (HHHFHH) -Size 30: 15,36 GOOD (HHFFFF) -Size 31: 16,37 BAD (HHHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,40 BAD (HHHFHH) -Size 34: 17,41 GOOD (HHFFFF) -Size 35: 18,42 BAD (HHHFHH) -Size 36: 18,43 GOOD (HHFFFF) -Size 37: 19,44 BAD (HHHFHH) -Size 38: 19,46 GOOD (HHFFFF) -Size 39: 20,47 BAD (HHHFHH) -Size 40: 20,48 GOOD (HHFFFF) -Size 41: 21,49 BAD (HHHFHH) -Size 42: 21,50 GOOD (HHFFFF) -Size 43: 22,52 BAD (HHHFHH) -Size 44: 22,53 GOOD (HHFFFF) -Size 45: 23,54 BAD (HHHFHH) -Size 46: 23,55 GOOD (HHFFFF) -Size 47: 24,56 BAD (HHHFHH) -Size 48: 24,58 GOOD (HHFFFF) -Size 49: 25,59 BAD (HHHFHH) -Size 50: 25,60 GOOD (HHFFFF) -Size 51: 26,61 BAD (HHHFHH) -Size 52: 26,62 GOOD (HHFFFF) -Size 53: 27,64 BAD (HHHFHH) -Size 54: 27,65 GOOD (HHFFFF) -Size 55: 28,66 BAD (HHHFHH) -Size 56: 28,67 GOOD (HHFFFF) -Size 57: 29,68 BAD (HHHFHH) -Size 58: 29,70 GOOD (HHFFFF) -Size 59: 30,71 BAD (HHHFHH) -Size 60: 30,72 GOOD (HHFFFF) -Size 61: 31,73 BAD (HHHFHH) -Size 62: 31,74 GOOD (HHFFFF) -Size 63: 32,76 BAD (HHHFHH) -Size 64: 32,77 GOOD (HHFFFF) -Size 65: 33,78 BAD (HHHFHH) -Size 66: 33,79 GOOD (HHFFFF) -Size 67: 34,80 BAD (HHHFHH) -Size 68: 34,82 GOOD (HHFFFF) -Size 69: 35,83 BAD (HHHFHH) -Size 70: 35,84 GOOD (HHFFFF) -Size 71: 36,85 BAD (HHHFHH) -Size 72: 36,86 GOOD (HHFFFF) -Size 73: 37,88 BAD (HHHFHH) -Size 74: 37,89 GOOD (HHFFFF) -Size 75: 38,90 BAD (HHHFHH) -Size 76: 38,91 GOOD (HHFFFF) -Size 77: 39,92 BAD (HHHFHH) -Size 78: 39,94 GOOD (HHFFFF) -Size 79: 40,95 BAD (HHHFHH) -Size 80: 40,96 GOOD (HHFFFF) -Size 81: 41,97 BAD (HHHFHH) -Size 82: 41,98 GOOD (HHFFFF) -Size 83: 42,100 BAD (HHHFHH) -Size 84: 42,101 GOOD (HHFFFF) -Size 85: 43,102 BAD (HHHFHH) -Size 86: 43,103 GOOD (HHFFFF) -Size 87: 44,104 BAD (HHHFHH) -Size 88: 44,106 GOOD (HHFFFF) -Size 89: 45,107 BAD (HHHFHH) -Size 90: 45,108 GOOD (HHFFFF) -Size 91: 46,109 BAD (HHHFHH) -Size 92: 46,110 GOOD (HHFFFF) -Size 93: 47,112 BAD (HHHFHH) -Size 94: 47,113 GOOD (HHFFFF) -Size 95: 48,114 BAD (HHHFHH) -Size 96: 48,115 GOOD (HHFFFF) -Size 97: 49,116 BAD (HHHFHH) -Size 98: 49,118 GOOD (HHFFFF) -Size 99: 50,119 BAD (HHHFHH) -Size 100: 50,120 GOOD (HHFFFF) - -Windows 7 ---------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,4 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,10 GOOD (HHFFFF) -Size 9: 5,11 BAD (FFHFHH) -Size 10: 5,12 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,16 BAD (FFHFHH) -Size 14: 7,17 GOOD (HHFFFF) -Size 15: 8,18 BAD (FFHFHH) -Size 16: 8,19 GOOD (HHFFFF) -Size 17: 9,20 BAD (FFHFHH) -Size 18: 9,22 GOOD (HHFFFF) -Size 19: 10,23 BAD (FFHFHH) -Size 20: 10,24 GOOD (HHFFFF) -Size 21: 11,25 BAD (FFHFHH) -Size 22: 11,26 GOOD (HHFFFF) -Size 23: 12,28 BAD (FFHFHH) -Size 24: 12,29 GOOD (HHFFFF) -Size 25: 13,30 BAD (FFHFHH) -Size 26: 13,31 GOOD (HHFFFF) -Size 27: 14,32 BAD (FFHFHH) -Size 28: 14,34 GOOD (HHFFFF) -Size 29: 15,35 BAD (FFHFHH) -Size 30: 15,36 GOOD (HHFFFF) -Size 31: 16,37 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,40 BAD (FFHFHH) -Size 34: 17,41 GOOD (HHFFFF) -Size 35: 18,42 BAD (FFHFHH) -Size 36: 18,43 GOOD (HHFFFF) -Size 37: 19,44 BAD (FFHFHH) -Size 38: 19,46 GOOD (HHFFFF) -Size 39: 20,47 BAD (FFHFHH) -Size 40: 20,48 GOOD (HHFFFF) -Size 41: 21,49 BAD (FFHFHH) -Size 42: 21,50 GOOD (HHFFFF) -Size 43: 22,52 BAD (FFHFHH) -Size 44: 22,53 GOOD (HHFFFF) -Size 45: 23,54 BAD (FFHFHH) -Size 46: 23,55 GOOD (HHFFFF) -Size 47: 24,56 BAD (FFHFHH) -Size 48: 24,58 GOOD (HHFFFF) -Size 49: 25,59 BAD (FFHFHH) -Size 50: 25,60 GOOD (HHFFFF) -Size 51: 26,61 BAD (FFHFHH) -Size 52: 26,62 GOOD (HHFFFF) -Size 53: 27,64 BAD (FFHFHH) -Size 54: 27,65 GOOD (HHFFFF) -Size 55: 28,66 BAD (FFHFHH) -Size 56: 28,67 GOOD (HHFFFF) -Size 57: 29,68 BAD (FFHFHH) -Size 58: 29,70 GOOD (HHFFFF) -Size 59: 30,71 BAD (FFHFHH) -Size 60: 30,72 GOOD (HHFFFF) -Size 61: 31,73 BAD (FFHFHH) -Size 62: 31,74 GOOD (HHFFFF) -Size 63: 32,76 BAD (FFHFHH) -Size 64: 32,77 GOOD (HHFFFF) -Size 65: 33,78 BAD (FFHFHH) -Size 66: 33,79 GOOD (HHFFFF) -Size 67: 34,80 BAD (FFHFHH) -Size 68: 34,82 GOOD (HHFFFF) -Size 69: 35,83 BAD (FFHFHH) -Size 70: 35,84 GOOD (HHFFFF) -Size 71: 36,85 BAD (FFHFHH) -Size 72: 36,86 GOOD (HHFFFF) -Size 73: 37,88 BAD (FFHFHH) -Size 74: 37,89 GOOD (HHFFFF) -Size 75: 38,90 BAD (FFHFHH) -Size 76: 38,91 GOOD (HHFFFF) -Size 77: 39,92 BAD (FFHFHH) -Size 78: 39,94 GOOD (HHFFFF) -Size 79: 40,95 BAD (FFHFHH) -Size 80: 40,96 GOOD (HHFFFF) -Size 81: 41,97 BAD (FFHFHH) -Size 82: 41,98 GOOD (HHFFFF) -Size 83: 42,100 BAD (FFHFHH) -Size 84: 42,101 GOOD (HHFFFF) -Size 85: 43,102 BAD (FFHFHH) -Size 86: 43,103 GOOD (HHFFFF) -Size 87: 44,104 BAD (FFHFHH) -Size 88: 44,106 GOOD (HHFFFF) -Size 89: 45,107 BAD (FFHFHH) -Size 90: 45,108 GOOD (HHFFFF) -Size 91: 46,109 BAD (FFHFHH) -Size 92: 46,110 GOOD (HHFFFF) -Size 93: 47,112 BAD (FFHFHH) -Size 94: 47,113 GOOD (HHFFFF) -Size 95: 48,114 BAD (FFHFHH) -Size 96: 48,115 GOOD (HHFFFF) -Size 97: 49,116 BAD (FFHFHH) -Size 98: 49,118 GOOD (HHFFFF) -Size 99: 50,119 BAD (FFHFHH) -Size 100: 50,120 GOOD (HHFFFF) - -Windows 8 ---------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,4 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,10 GOOD (HHFFFF) -Size 9: 5,11 BAD (FFHFHH) -Size 10: 5,12 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,16 BAD (FFHFHH) -Size 14: 7,17 GOOD (HHFFFF) -Size 15: 8,18 BAD (FFHFHH) -Size 16: 8,19 GOOD (HHFFFF) -Size 17: 9,20 BAD (FFHFHH) -Size 18: 9,22 GOOD (HHFFFF) -Size 19: 10,23 BAD (FFHFHH) -Size 20: 10,24 GOOD (HHFFFF) -Size 21: 11,25 BAD (FFHFHH) -Size 22: 11,26 GOOD (HHFFFF) -Size 23: 12,28 BAD (FFHFHH) -Size 24: 12,29 GOOD (HHFFFF) -Size 25: 13,30 BAD (FFHFHH) -Size 26: 13,31 GOOD (HHFFFF) -Size 27: 14,32 BAD (FFHFHH) -Size 28: 14,34 GOOD (HHFFFF) -Size 29: 15,35 BAD (FFHFHH) -Size 30: 15,36 GOOD (HHFFFF) -Size 31: 16,37 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,40 BAD (FFHFHH) -Size 34: 17,41 GOOD (HHFFFF) -Size 35: 18,42 BAD (FFHFHH) -Size 36: 18,43 GOOD (HHFFFF) -Size 37: 19,44 BAD (FFHFHH) -Size 38: 19,46 GOOD (HHFFFF) -Size 39: 20,47 BAD (FFHFHH) -Size 40: 20,48 GOOD (HHFFFF) -Size 41: 21,49 BAD (FFHFHH) -Size 42: 21,50 GOOD (HHFFFF) -Size 43: 22,52 BAD (FFHFHH) -Size 44: 22,53 GOOD (HHFFFF) -Size 45: 23,54 BAD (FFHFHH) -Size 46: 23,55 GOOD (HHFFFF) -Size 47: 24,56 BAD (FFHFHH) -Size 48: 24,58 GOOD (HHFFFF) -Size 49: 25,59 BAD (FFHFHH) -Size 50: 25,60 GOOD (HHFFFF) -Size 51: 26,61 BAD (FFHFHH) -Size 52: 26,62 GOOD (HHFFFF) -Size 53: 27,64 BAD (FFHFHH) -Size 54: 27,65 GOOD (HHFFFF) -Size 55: 28,66 BAD (FFHFHH) -Size 56: 28,67 GOOD (HHFFFF) -Size 57: 29,68 BAD (FFHFHH) -Size 58: 29,70 GOOD (HHFFFF) -Size 59: 30,71 BAD (FFHFHH) -Size 60: 30,72 GOOD (HHFFFF) -Size 61: 31,73 BAD (FFHFHH) -Size 62: 31,74 GOOD (HHFFFF) -Size 63: 32,76 BAD (FFHFHH) -Size 64: 32,77 GOOD (HHFFFF) -Size 65: 33,78 BAD (FFHFHH) -Size 66: 33,79 GOOD (HHFFFF) -Size 67: 34,80 BAD (FFHFHH) -Size 68: 34,82 GOOD (HHFFFF) -Size 69: 35,83 BAD (FFHFHH) -Size 70: 35,84 GOOD (HHFFFF) -Size 71: 36,85 BAD (FFHFHH) -Size 72: 36,86 GOOD (HHFFFF) -Size 73: 37,88 BAD (FFHFHH) -Size 74: 37,89 GOOD (HHFFFF) -Size 75: 38,90 BAD (FFHFHH) -Size 76: 38,91 GOOD (HHFFFF) -Size 77: 39,92 BAD (FFHFHH) -Size 78: 39,94 GOOD (HHFFFF) -Size 79: 40,95 BAD (FFHFHH) -Size 80: 40,96 GOOD (HHFFFF) -Size 81: 41,97 BAD (FFHFHH) -Size 82: 41,98 GOOD (HHFFFF) -Size 83: 42,100 BAD (FFHFHH) -Size 84: 42,101 GOOD (HHFFFF) -Size 85: 43,102 BAD (FFHFHH) -Size 86: 43,103 GOOD (HHFFFF) -Size 87: 44,104 BAD (FFHFHH) -Size 88: 44,106 GOOD (HHFFFF) -Size 89: 45,107 BAD (FFHFHH) -Size 90: 45,108 GOOD (HHFFFF) -Size 91: 46,109 BAD (FFHFHH) -Size 92: 46,110 GOOD (HHFFFF) -Size 93: 47,112 BAD (FFHFHH) -Size 94: 47,113 GOOD (HHFFFF) -Size 95: 48,114 BAD (FFHFHH) -Size 96: 48,115 GOOD (HHFFFF) -Size 97: 49,116 BAD (FFHFHH) -Size 98: 49,118 GOOD (HHFFFF) -Size 99: 50,119 BAD (FFHFHH) -Size 100: 50,120 GOOD (HHFFFF) - -Windows 8.1 ------------ - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,4 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,10 GOOD (HHFFFF) -Size 9: 5,11 BAD (FFHFHH) -Size 10: 5,12 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,16 BAD (FFHFHH) -Size 14: 7,17 GOOD (HHFFFF) -Size 15: 8,18 BAD (FFHFHH) -Size 16: 8,19 GOOD (HHFFFF) -Size 17: 9,20 BAD (FFHFHH) -Size 18: 9,22 GOOD (HHFFFF) -Size 19: 10,23 BAD (FFHFHH) -Size 20: 10,24 GOOD (HHFFFF) -Size 21: 11,25 BAD (FFHFHH) -Size 22: 11,26 GOOD (HHFFFF) -Size 23: 12,28 BAD (FFHFHH) -Size 24: 12,29 GOOD (HHFFFF) -Size 25: 13,30 BAD (FFHFHH) -Size 26: 13,31 GOOD (HHFFFF) -Size 27: 14,32 BAD (FFHFHH) -Size 28: 14,34 GOOD (HHFFFF) -Size 29: 15,35 BAD (FFHFHH) -Size 30: 15,36 GOOD (HHFFFF) -Size 31: 16,37 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,40 BAD (FFHFHH) -Size 34: 17,41 GOOD (HHFFFF) -Size 35: 18,42 BAD (FFHFHH) -Size 36: 18,43 GOOD (HHFFFF) -Size 37: 19,44 BAD (FFHFHH) -Size 38: 19,46 GOOD (HHFFFF) -Size 39: 20,47 BAD (FFHFHH) -Size 40: 20,48 GOOD (HHFFFF) -Size 41: 21,49 BAD (FFHFHH) -Size 42: 21,50 GOOD (HHFFFF) -Size 43: 22,52 BAD (FFHFHH) -Size 44: 22,53 GOOD (HHFFFF) -Size 45: 23,54 BAD (FFHFHH) -Size 46: 23,55 GOOD (HHFFFF) -Size 47: 24,56 BAD (FFHFHH) -Size 48: 24,58 GOOD (HHFFFF) -Size 49: 25,59 BAD (FFHFHH) -Size 50: 25,60 GOOD (HHFFFF) -Size 51: 26,61 BAD (FFHFHH) -Size 52: 26,62 GOOD (HHFFFF) -Size 53: 27,64 BAD (FFHFHH) -Size 54: 27,65 GOOD (HHFFFF) -Size 55: 28,66 BAD (FFHFHH) -Size 56: 28,67 GOOD (HHFFFF) -Size 57: 29,68 BAD (FFHFHH) -Size 58: 29,70 GOOD (HHFFFF) -Size 59: 30,71 BAD (FFHFHH) -Size 60: 30,72 GOOD (HHFFFF) -Size 61: 31,73 BAD (FFHFHH) -Size 62: 31,74 GOOD (HHFFFF) -Size 63: 32,76 BAD (FFHFHH) -Size 64: 32,77 GOOD (HHFFFF) -Size 65: 33,78 BAD (FFHFHH) -Size 66: 33,79 GOOD (HHFFFF) -Size 67: 34,80 BAD (FFHFHH) -Size 68: 34,82 GOOD (HHFFFF) -Size 69: 35,83 BAD (FFHFHH) -Size 70: 35,84 GOOD (HHFFFF) -Size 71: 36,85 BAD (FFHFHH) -Size 72: 36,86 GOOD (HHFFFF) -Size 73: 37,88 BAD (FFHFHH) -Size 74: 37,89 GOOD (HHFFFF) -Size 75: 38,90 BAD (FFHFHH) -Size 76: 38,91 GOOD (HHFFFF) -Size 77: 39,92 BAD (FFHFHH) -Size 78: 39,94 GOOD (HHFFFF) -Size 79: 40,95 BAD (FFHFHH) -Size 80: 40,96 GOOD (HHFFFF) -Size 81: 41,97 BAD (FFHFHH) -Size 82: 41,98 GOOD (HHFFFF) -Size 83: 42,100 BAD (FFHFHH) -Size 84: 42,101 GOOD (HHFFFF) -Size 85: 43,102 BAD (FFHFHH) -Size 86: 43,103 GOOD (HHFFFF) -Size 87: 44,104 BAD (FFHFHH) -Size 88: 44,106 GOOD (HHFFFF) -Size 89: 45,107 BAD (FFHFHH) -Size 90: 45,108 GOOD (HHFFFF) -Size 91: 46,109 BAD (FFHFHH) -Size 92: 46,110 GOOD (HHFFFF) -Size 93: 47,112 BAD (FFHFHH) -Size 94: 47,113 GOOD (HHFFFF) -Size 95: 48,114 BAD (FFHFHH) -Size 96: 48,115 GOOD (HHFFFF) -Size 97: 49,116 BAD (FFHFHH) -Size 98: 49,118 GOOD (HHFFFF) -Size 99: 50,119 BAD (FFHFHH) -Size 100: 50,120 GOOD (HHFFFF) - -Windows 10 14342 Old Console ----------------------------- - -Size 1: 1,2 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,4 BAD (FFHFHH) -Size 4: 2,5 GOOD (HHFFFF) -Size 5: 3,6 BAD (FFHFHH) -Size 6: 3,7 GOOD (HHFFFF) -Size 7: 4,8 BAD (FFHFHH) -Size 8: 4,10 GOOD (HHFFFF) -Size 9: 5,11 BAD (FFHFHH) -Size 10: 5,12 GOOD (HHFFFF) -Size 11: 6,13 BAD (FFHFHH) -Size 12: 6,14 GOOD (HHFFFF) -Size 13: 7,16 BAD (FFHFHH) -Size 14: 7,17 GOOD (HHFFFF) -Size 15: 8,18 BAD (FFHFHH) -Size 16: 8,19 GOOD (HHFFFF) -Size 17: 9,20 BAD (FFHFHH) -Size 18: 9,22 GOOD (HHFFFF) -Size 19: 10,23 BAD (FFHFHH) -Size 20: 10,24 GOOD (HHFFFF) -Size 21: 11,25 BAD (FFHFHH) -Size 22: 11,26 GOOD (HHFFFF) -Size 23: 12,28 BAD (FFHFHH) -Size 24: 12,29 GOOD (HHFFFF) -Size 25: 13,30 BAD (FFHFHH) -Size 26: 13,31 GOOD (HHFFFF) -Size 27: 14,32 BAD (FFHFHH) -Size 28: 14,34 GOOD (HHFFFF) -Size 29: 15,35 BAD (FFHFHH) -Size 30: 15,36 GOOD (HHFFFF) -Size 31: 16,37 BAD (FFHFHH) -Size 32: 16,38 GOOD (HHFFFF) -Size 33: 17,40 BAD (FFHFHH) -Size 34: 17,41 GOOD (HHFFFF) -Size 35: 18,42 BAD (FFHFHH) -Size 36: 18,43 GOOD (HHFFFF) -Size 37: 19,44 BAD (FFHFHH) -Size 38: 19,46 GOOD (HHFFFF) -Size 39: 20,47 BAD (FFHFHH) -Size 40: 20,48 GOOD (HHFFFF) -Size 41: 21,49 BAD (FFHFHH) -Size 42: 21,50 GOOD (HHFFFF) -Size 43: 22,52 BAD (FFHFHH) -Size 44: 22,53 GOOD (HHFFFF) -Size 45: 23,54 BAD (FFHFHH) -Size 46: 23,55 GOOD (HHFFFF) -Size 47: 24,56 BAD (FFHFHH) -Size 48: 24,58 GOOD (HHFFFF) -Size 49: 25,59 BAD (FFHFHH) -Size 50: 25,60 GOOD (HHFFFF) -Size 51: 26,61 BAD (FFHFHH) -Size 52: 26,62 GOOD (HHFFFF) -Size 53: 27,64 BAD (FFHFHH) -Size 54: 27,65 GOOD (HHFFFF) -Size 55: 28,66 BAD (FFHFHH) -Size 56: 28,67 GOOD (HHFFFF) -Size 57: 29,68 BAD (FFHFHH) -Size 58: 29,70 GOOD (HHFFFF) -Size 59: 30,71 BAD (FFHFHH) -Size 60: 30,72 GOOD (HHFFFF) -Size 61: 31,73 BAD (FFHFHH) -Size 62: 31,74 GOOD (HHFFFF) -Size 63: 32,76 BAD (FFHFHH) -Size 64: 32,77 GOOD (HHFFFF) -Size 65: 33,78 BAD (FFHFHH) -Size 66: 33,79 GOOD (HHFFFF) -Size 67: 34,80 BAD (FFHFHH) -Size 68: 34,82 GOOD (HHFFFF) -Size 69: 35,83 BAD (FFHFHH) -Size 70: 35,84 GOOD (HHFFFF) -Size 71: 36,85 BAD (FFHFHH) -Size 72: 36,86 GOOD (HHFFFF) -Size 73: 37,88 BAD (FFHFHH) -Size 74: 37,89 GOOD (HHFFFF) -Size 75: 38,90 BAD (FFHFHH) -Size 76: 38,91 GOOD (HHFFFF) -Size 77: 39,92 BAD (FFHFHH) -Size 78: 39,94 GOOD (HHFFFF) -Size 79: 40,95 BAD (FFHFHH) -Size 80: 40,96 GOOD (HHFFFF) -Size 81: 41,97 BAD (FFHFHH) -Size 82: 41,98 GOOD (HHFFFF) -Size 83: 42,100 BAD (FFHFHH) -Size 84: 42,101 GOOD (HHFFFF) -Size 85: 43,102 BAD (FFHFHH) -Size 86: 43,103 GOOD (HHFFFF) -Size 87: 44,104 BAD (FFHFHH) -Size 88: 44,106 GOOD (HHFFFF) -Size 89: 45,107 BAD (FFHFHH) -Size 90: 45,108 GOOD (HHFFFF) -Size 91: 46,109 BAD (FFHFHH) -Size 92: 46,110 GOOD (HHFFFF) -Size 93: 47,112 BAD (FFHFHH) -Size 94: 47,113 GOOD (HHFFFF) -Size 95: 48,114 BAD (FFHFHH) -Size 96: 48,115 GOOD (HHFFFF) -Size 97: 49,116 BAD (FFHFHH) -Size 98: 49,118 GOOD (HHFFFF) -Size 99: 50,119 BAD (FFHFHH) -Size 100: 50,120 GOOD (HHFFFF) - -Windows 10 14342 New Console ----------------------------- - -Size 1: 1,1 GOOD (HHFFFF) -Size 2: 1,2 GOOD (HHFFFF) -Size 3: 2,3 GOOD (HHFFFF) -Size 4: 2,4 GOOD (HHFFFF) -Size 5: 3,5 GOOD (HHFFFF) -Size 6: 3,6 GOOD (HHFFFF) -Size 7: 4,7 GOOD (HHFFFF) -Size 8: 4,8 GOOD (HHFFFF) -Size 9: 5,9 GOOD (HHFFFF) -Size 10: 5,10 GOOD (HHFFFF) -Size 11: 6,11 GOOD (HHFFFF) -Size 12: 6,12 GOOD (HHFFFF) -Size 13: 7,13 GOOD (HHFFFF) -Size 14: 7,14 GOOD (HHFFFF) -Size 15: 8,15 GOOD (HHFFFF) -Size 16: 8,16 GOOD (HHFFFF) -Size 17: 9,17 GOOD (HHFFFF) -Size 18: 9,18 GOOD (HHFFFF) -Size 19: 10,19 GOOD (HHFFFF) -Size 20: 10,20 GOOD (HHFFFF) -Size 21: 11,21 GOOD (HHFFFF) -Size 22: 11,22 GOOD (HHFFFF) -Size 23: 12,23 GOOD (HHFFFF) -Size 24: 12,24 GOOD (HHFFFF) -Size 25: 13,25 GOOD (HHFFFF) -Size 26: 13,26 GOOD (HHFFFF) -Size 27: 14,27 GOOD (HHFFFF) -Size 28: 14,28 GOOD (HHFFFF) -Size 29: 15,29 GOOD (HHFFFF) -Size 30: 15,30 GOOD (HHFFFF) -Size 31: 16,31 GOOD (HHFFFF) -Size 32: 16,32 GOOD (HHFFFF) -Size 33: 17,33 GOOD (HHFFFF) -Size 34: 17,34 GOOD (HHFFFF) -Size 35: 18,35 GOOD (HHFFFF) -Size 36: 18,36 GOOD (HHFFFF) -Size 37: 19,37 GOOD (HHFFFF) -Size 38: 19,38 GOOD (HHFFFF) -Size 39: 20,39 GOOD (HHFFFF) -Size 40: 20,40 GOOD (HHFFFF) -Size 41: 21,41 GOOD (HHFFFF) -Size 42: 21,42 GOOD (HHFFFF) -Size 43: 22,43 GOOD (HHFFFF) -Size 44: 22,44 GOOD (HHFFFF) -Size 45: 23,45 GOOD (HHFFFF) -Size 46: 23,46 GOOD (HHFFFF) -Size 47: 24,47 GOOD (HHFFFF) -Size 48: 24,48 GOOD (HHFFFF) -Size 49: 25,49 GOOD (HHFFFF) -Size 50: 25,50 GOOD (HHFFFF) -Size 51: 26,51 GOOD (HHFFFF) -Size 52: 26,52 GOOD (HHFFFF) -Size 53: 27,53 GOOD (HHFFFF) -Size 54: 27,54 GOOD (HHFFFF) -Size 55: 28,55 GOOD (HHFFFF) -Size 56: 28,56 GOOD (HHFFFF) -Size 57: 29,57 GOOD (HHFFFF) -Size 58: 29,58 GOOD (HHFFFF) -Size 59: 30,59 GOOD (HHFFFF) -Size 60: 30,60 GOOD (HHFFFF) -Size 61: 31,61 GOOD (HHFFFF) -Size 62: 31,62 GOOD (HHFFFF) -Size 63: 32,63 GOOD (HHFFFF) -Size 64: 32,64 GOOD (HHFFFF) -Size 65: 33,65 GOOD (HHFFFF) -Size 66: 33,66 GOOD (HHFFFF) -Size 67: 34,67 GOOD (HHFFFF) -Size 68: 34,68 GOOD (HHFFFF) -Size 69: 35,69 GOOD (HHFFFF) -Size 70: 35,70 GOOD (HHFFFF) -Size 71: 36,71 GOOD (HHFFFF) -Size 72: 36,72 GOOD (HHFFFF) -Size 73: 37,73 GOOD (HHFFFF) -Size 74: 37,74 GOOD (HHFFFF) -Size 75: 38,75 GOOD (HHFFFF) -Size 76: 38,76 GOOD (HHFFFF) -Size 77: 39,77 GOOD (HHFFFF) -Size 78: 39,78 GOOD (HHFFFF) -Size 79: 40,79 GOOD (HHFFFF) -Size 80: 40,80 GOOD (HHFFFF) -Size 81: 41,81 GOOD (HHFFFF) -Size 82: 41,82 GOOD (HHFFFF) -Size 83: 42,83 GOOD (HHFFFF) -Size 84: 42,84 GOOD (HHFFFF) -Size 85: 43,85 GOOD (HHFFFF) -Size 86: 43,86 GOOD (HHFFFF) -Size 87: 44,87 GOOD (HHFFFF) -Size 88: 44,88 GOOD (HHFFFF) -Size 89: 45,89 GOOD (HHFFFF) -Size 90: 45,90 GOOD (HHFFFF) -Size 91: 46,91 GOOD (HHFFFF) -Size 92: 46,92 GOOD (HHFFFF) -Size 93: 47,93 GOOD (HHFFFF) -Size 94: 47,94 GOOD (HHFFFF) -Size 95: 48,95 GOOD (HHFFFF) -Size 96: 48,96 GOOD (HHFFFF) -Size 97: 49,97 GOOD (HHFFFF) -Size 98: 49,98 GOOD (HHFFFF) -Size 99: 50,99 GOOD (HHFFFF) -Size 100: 50,100 GOOD (HHFFFF) diff --git a/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt b/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt deleted file mode 100644 index d5261d8db..000000000 --- a/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt +++ /dev/null @@ -1,16 +0,0 @@ -The narrowest allowed console window, in pixels, on a conventional (~96dpi) -monitor: - -(mode con: cols=40 lines=40) && SetFont.exe -face "Lucida Console" -h 1 && (ping -n 4 127.0.0.1 > NUL) && cls && GetConsolePos.exe && SetFont.exe -face "Lucida Console" -h 12 - -(mode con: cols=40 lines=40) && SetFont.exe -face "Lucida Console" -h 16 && (ping -n 4 127.0.0.1 > NUL) && cls && GetConsolePos.exe && SetFont.exe -face "Lucida Console" -h 12 - - sz1:px sz1:col sz16:px sz16:col -Vista: 124 104 137 10 -Windows 7: 132 112 147 11 -Windows 8: 140 120 147 11 -Windows 8.1: 140 120 147 11 -Windows 10 OLD: 136 116 147 11 -Windows 10 NEW: 136 103 136 10 - -I used build 14342 to test Windows 10. diff --git a/deps/winpty/misc/Font-Report-June2016/Results.txt b/deps/winpty/misc/Font-Report-June2016/Results.txt deleted file mode 100644 index 15a825cb5..000000000 --- a/deps/winpty/misc/Font-Report-June2016/Results.txt +++ /dev/null @@ -1,4 +0,0 @@ -As before, avoid odd sizes in favor of even sizes. - -It's curious that the Japanese font is handled so poorly, especially with -Windows 8 and later. diff --git a/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt b/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt deleted file mode 100644 index fef397a1e..000000000 --- a/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt +++ /dev/null @@ -1,144 +0,0 @@ -Issues: - - - Starting with the 14342 build, changing the font using - SetCurrentConsoleFontEx does not affect the window size. e.g. The content - itself will resize/redraw, but the window neither shrinks nor expands. - Presumably this is an oversight? It's almost a convenience; if a program - is going to resize the window anyway, then it's nice that the window size - contraints don't get in the way. Ordinarily, changing the font doesn't just - change the window size in pixels--it can also change the size as measured in - rows and columns. - - - (Aside: in the 14342 build, there is also a bug with wmic.exe. Open a console - with more than 300 lines of screen buffer, then fill those lines with, e.g., - dir /s. Then run wmic.exe. You won't be able to see the wmic.exe prompt. - If you query the screen buffer info somehow, you'll notice that the srWindow - is not contained within the dwSize. This breaks winpty's scraping, because - it's invalid.) - - - In build 14316, with the Japanese locale, with the 437 code page, attempting - to set the Consolas font instead sets the Terminal (raster) font. It seems - to pick an appropriate vertical size. - - - It seems necessary to specify "-family 0x36" for maximum reliability. - Setting the family to 0 almost always works, and specifying just -tt rarely - works. - -Win7 - English locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 932 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt unreliable - SetFont.exe -face Consolas -h 16 -family 0x36 works - -Win10 Build 10586 - New console - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - -Win10 Build 14316 - Old console - English locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 932 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selected very small Consolas font - SetFont.exe -face Consolas -h 16 -family 0x36 works - New console - English locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt works - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 932 code page: - SetFont.exe -face Consolas -h 16 selects gothic instead - SetFont.exe -face Consolas -h 16 -tt selects gothic instead - SetFont.exe -face Consolas -h 16 -family 0x36 selects gothic instead - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 selects Terminal font instead - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36(*) selects Terminal font instead - -Win10 Build 14342 - Old Console - English locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 932 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt selects Terminal font instead - SetFont.exe -face Consolas -h 16 -family 0x36 works - New console - English locale / 437 code page: - SetFont.exe -face Consolas -h 16 works - SetFont.exe -face Consolas -h 16 -tt works - SetFont.exe -face Consolas -h 16 -family 0x36 works - Japanese locale / 932 code page: - SetFont.exe -face Consolas -h 16 selects gothic instead - SetFont.exe -face Consolas -h 16 -tt selects gothic instead - SetFont.exe -face Consolas -h 16 -family 0x36 selects gothic instead - Japanese locale / 437 code page: - SetFont.exe -face Consolas -h 16 selects Terminal font instead - SetFont.exe -face Consolas -h 16 -tt works - SetFont.exe -face Consolas -h 16 -family 0x36 works - -(*) I was trying to figure out whether the inconsistency was at when I stumbled -onto this completely unexpected bug. Here's more detail: - - F:\>SetFont.exe -face Consolas -h 16 -family 0x36 -weight normal -w 8 - Setting to: nFont=0 dwFontSize=(8,16) FontFamily=0x36 FontWeight=400 FaceName="Consolas" - SetCurrentConsoleFontEx returned 1 - - F:\>GetFont.exe - largestConsoleWindowSize=(96,50) - maxWnd=0: nFont=0 dwFontSize=(12,16) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - maxWnd=1: nFont=0 dwFontSize=(96,25) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - 00-00: 12x16 - GetNumberOfConsoleFonts returned 0 - CP=437 OutputCP=437 - - F:\>SetFont.exe -face "Lucida Console" -h 16 -family 0x36 -weight normal - Setting to: nFont=0 dwFontSize=(0,16) FontFamily=0x36 FontWeight=400 FaceName="Lucida Console" - SetCurrentConsoleFontEx returned 1 - - F:\>GetFont.exe - largestConsoleWindowSize=(96,50) - maxWnd=0: nFont=0 dwFontSize=(12,16) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - maxWnd=1: nFont=0 dwFontSize=(96,25) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - 00-00: 12x16 - GetNumberOfConsoleFonts returned 0 - CP=437 OutputCP=437 - - F:\>SetFont.exe -face "Lucida Console" -h 12 -family 0x36 -weight normal - Setting to: nFont=0 dwFontSize=(0,12) FontFamily=0x36 FontWeight=400 FaceName="Lucida Console" - SetCurrentConsoleFontEx returned 1 - - F:\>GetFont.exe - largestConsoleWindowSize=(230,66) - maxWnd=0: nFont=0 dwFontSize=(5,12) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - maxWnd=1: nFont=0 dwFontSize=(116,36) FontFamily=0x30 FontWeight=400 FaceName=Terminal (54 65 72 6D 69 6E 61 6C) - 00-00: 5x12 - GetNumberOfConsoleFonts returned 0 - CP=437 OutputCP=437 - -Even attempting to set to a Lucida Console / Consolas font from the Console -properties dialog fails. diff --git a/deps/winpty/misc/FontSurvey.cc b/deps/winpty/misc/FontSurvey.cc deleted file mode 100644 index 254bcc81a..000000000 --- a/deps/winpty/misc/FontSurvey.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include -#include -#include - -#include - -#include "TestUtil.cc" - -#define COUNT_OF(array) (sizeof(array) / sizeof((array)[0])) - -// See https://en.wikipedia.org/wiki/List_of_CJK_fonts -const wchar_t kMSGothic[] = { 0xff2d, 0xff33, 0x0020, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 }; // Japanese -const wchar_t kNSimSun[] = { 0x65b0, 0x5b8b, 0x4f53, 0 }; // Simplified Chinese -const wchar_t kMingLight[] = { 0x7d30, 0x660e, 0x9ad4, 0 }; // Traditional Chinese -const wchar_t kGulimChe[] = { 0xad74, 0xb9bc, 0xccb4, 0 }; // Korean - -std::vector condense(const std::vector &buf) { - std::vector ret; - size_t i = 0; - while (i < buf.size()) { - if (buf[i].Char.UnicodeChar == L' ' && - ((buf[i].Attributes & 0x300) == 0)) { - // end of line - break; - } else if (i + 1 < buf.size() && - ((buf[i].Attributes & 0x300) == 0x100) && - ((buf[i + 1].Attributes & 0x300) == 0x200) && - buf[i].Char.UnicodeChar != L' ' && - buf[i].Char.UnicodeChar == buf[i + 1].Char.UnicodeChar) { - // double-width - ret.push_back(true); - i += 2; - } else if ((buf[i].Attributes & 0x300) == 0) { - // single-width - ret.push_back(false); - i++; - } else { - ASSERT(false && "unexpected output"); - } - } - return ret; -} - -int main(int argc, char *argv[]) { - if (argc != 2) { - printf("Usage: %s \"arguments for SetFont.exe\"\n", argv[0]); - return 1; - } - - const char *setFontArgs = argv[1]; - - const wchar_t testLine[] = { 0xA2, 0xA3, 0x2014, 0x3044, 0x30FC, 0x4000, 0 }; - const HANDLE conout = openConout(); - - char setFontCmd[1024]; - for (int h = 1; h <= 100; ++h) { - sprintf(setFontCmd, ".\\SetFont.exe %s -h %d && cls", setFontArgs, h); - system(setFontCmd); - - CONSOLE_FONT_INFOEX infoex = {}; - infoex.cbSize = sizeof(infoex); - BOOL success = GetCurrentConsoleFontEx(conout, FALSE, &infoex); - ASSERT(success && "GetCurrentConsoleFontEx failed"); - - DWORD actual = 0; - success = WriteConsoleW(conout, testLine, wcslen(testLine), &actual, nullptr); - ASSERT(success && actual == wcslen(testLine)); - - std::vector readBuf(14); - const SMALL_RECT readRegion = {0, 0, static_cast(readBuf.size() - 1), 0}; - SMALL_RECT readRegion2 = readRegion; - success = ReadConsoleOutputW( - conout, readBuf.data(), - {static_cast(readBuf.size()), 1}, - {0, 0}, - &readRegion2); - ASSERT(success && !memcmp(&readRegion, &readRegion2, sizeof(readRegion))); - - const auto widths = condense(readBuf); - std::string widthsStr; - for (bool width : widths) { - widthsStr.append(width ? "F" : "H"); - } - char size[16]; - sprintf(size, "%d,%d", infoex.dwFontSize.X, infoex.dwFontSize.Y); - const char *status = ""; - if (widthsStr == "HHFFFF") { - status = "GOOD"; - } else if (widthsStr == "HHHFFF") { - status = "OK"; - } else { - status = "BAD"; - } - trace("Size %3d: %-7s %-4s (%s)", h, size, status, widthsStr.c_str()); - } - sprintf(setFontCmd, ".\\SetFont.exe %s -h 14", setFontArgs); - system(setFontCmd); -} diff --git a/deps/winpty/misc/FormatChar.h b/deps/winpty/misc/FormatChar.h deleted file mode 100644 index aade488f9..000000000 --- a/deps/winpty/misc/FormatChar.h +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - -static inline void formatChar(char *str, char ch) -{ - // Print some common control codes. - switch (ch) { - case '\r': strcpy(str, "CR "); break; - case '\n': strcpy(str, "LF "); break; - case ' ': strcpy(str, "SP "); break; - case 27: strcpy(str, "^[ "); break; - case 3: strcpy(str, "^C "); break; - default: - if (isgraph(ch)) - sprintf(str, "%c ", ch); - else - sprintf(str, "%02x ", ch); - break; - } -} diff --git a/deps/winpty/misc/FreezePerfTest.cc b/deps/winpty/misc/FreezePerfTest.cc deleted file mode 100644 index 2c0b0086a..000000000 --- a/deps/winpty/misc/FreezePerfTest.cc +++ /dev/null @@ -1,62 +0,0 @@ -#include - -#include "TestUtil.cc" - -const int SC_CONSOLE_MARK = 0xFFF2; -const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - -int main(int argc, char *argv[0]) { - - if (argc != 2) { - printf("Usage: %s (mark|selectall|read)\n", argv[0]); - return 1; - } - - enum class Test { Mark, SelectAll, Read } test; - if (!strcmp(argv[1], "mark")) { - test = Test::Mark; - } else if (!strcmp(argv[1], "selectall")) { - test = Test::SelectAll; - } else if (!strcmp(argv[1], "read")) { - test = Test::Read; - } else { - printf("Invalid test: %s\n", argv[1]); - return 1; - } - - HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - TimeMeasurement tm; - HWND hwnd = GetConsoleWindow(); - - setWindowPos(0, 0, 1, 1); - setBufferSize(100, 3000); - system("cls"); - setWindowPos(0, 2975, 100, 25); - setCursorPos(0, 2999); - - ShowWindow(hwnd, SW_HIDE); - - for (int i = 0; i < 1000; ++i) { - // CONSOLE_SCREEN_BUFFER_INFO info = {}; - // GetConsoleScreenBufferInfo(conout, &info); - - if (test == Test::Mark) { - SendMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_MARK, 0); - SendMessage(hwnd, WM_CHAR, 27, 0x00010001); - } else if (test == Test::SelectAll) { - SendMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_SELECT_ALL, 0); - SendMessage(hwnd, WM_CHAR, 27, 0x00010001); - } else if (test == Test::Read) { - static CHAR_INFO buffer[100 * 3000]; - const SMALL_RECT readRegion = {0, 0, 99, 2999}; - SMALL_RECT tmp = readRegion; - BOOL ret = ReadConsoleOutput(conout, buffer, {100, 3000}, {0, 0}, &tmp); - ASSERT(ret && !memcmp(&tmp, &readRegion, sizeof(tmp))); - } - } - - ShowWindow(hwnd, SW_SHOW); - - printf("elapsed: %f\n", tm.elapsed()); - return 0; -} diff --git a/deps/winpty/misc/GetCh.cc b/deps/winpty/misc/GetCh.cc deleted file mode 100644 index cd6ed1943..000000000 --- a/deps/winpty/misc/GetCh.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include - -int main() { - printf("\nPress any keys -- Ctrl-D exits\n\n"); - - while (true) { - const int ch = getch(); - printf("0x%x", ch); - if (isgraph(ch)) { - printf(" '%c'", ch); - } - printf("\n"); - if (ch == 0x4) { // Ctrl-D - break; - } - } - return 0; -} diff --git a/deps/winpty/misc/GetConsolePos.cc b/deps/winpty/misc/GetConsolePos.cc deleted file mode 100644 index 1f3cc5316..000000000 --- a/deps/winpty/misc/GetConsolePos.cc +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include - -#include "TestUtil.cc" - -int main() { - const HANDLE conout = openConout(); - - CONSOLE_SCREEN_BUFFER_INFO info = {}; - BOOL ret = GetConsoleScreenBufferInfo(conout, &info); - ASSERT(ret && "GetConsoleScreenBufferInfo failed"); - - trace("cursor=%d,%d", info.dwCursorPosition.X, info.dwCursorPosition.Y); - printf("cursor=%d,%d\n", info.dwCursorPosition.X, info.dwCursorPosition.Y); - - trace("srWindow={L=%d,T=%d,R=%d,B=%d}", info.srWindow.Left, info.srWindow.Top, info.srWindow.Right, info.srWindow.Bottom); - printf("srWindow={L=%d,T=%d,R=%d,B=%d}\n", info.srWindow.Left, info.srWindow.Top, info.srWindow.Right, info.srWindow.Bottom); - - trace("dwSize=%d,%d", info.dwSize.X, info.dwSize.Y); - printf("dwSize=%d,%d\n", info.dwSize.X, info.dwSize.Y); - - const HWND hwnd = GetConsoleWindow(); - if (hwnd != NULL) { - RECT r = {}; - if (GetWindowRect(hwnd, &r)) { - const int w = r.right - r.left; - const int h = r.bottom - r.top; - trace("hwnd: pos=(%d,%d) size=(%d,%d)", r.left, r.top, w, h); - printf("hwnd: pos=(%d,%d) size=(%d,%d)\n", r.left, r.top, w, h); - } else { - trace("GetWindowRect failed"); - printf("GetWindowRect failed\n"); - } - } else { - trace("GetConsoleWindow returned NULL"); - printf("GetConsoleWindow returned NULL\n"); - } - - return 0; -} diff --git a/deps/winpty/misc/GetFont.cc b/deps/winpty/misc/GetFont.cc deleted file mode 100644 index 38625317a..000000000 --- a/deps/winpty/misc/GetFont.cc +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include - -#include "../src/shared/OsModule.h" -#include "../src/shared/StringUtil.h" - -#include "TestUtil.cc" -#include "../src/shared/StringUtil.cc" - -#define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) - -// Some of these types and functions are missing from the MinGW headers. -// Others are undocumented. - -struct AGENT_CONSOLE_FONT_INFO { - DWORD nFont; - COORD dwFontSize; -}; - -struct AGENT_CONSOLE_FONT_INFOEX { - ULONG cbSize; - DWORD nFont; - COORD dwFontSize; - UINT FontFamily; - UINT FontWeight; - WCHAR FaceName[LF_FACESIZE]; -}; - -// undocumented XP API -typedef BOOL WINAPI SetConsoleFont_t( - HANDLE hOutput, - DWORD dwFontIndex); - -// undocumented XP API -typedef DWORD WINAPI GetNumberOfConsoleFonts_t(); - -// XP and up -typedef BOOL WINAPI GetCurrentConsoleFont_t( - HANDLE hOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont); - -// XP and up -typedef COORD WINAPI GetConsoleFontSize_t( - HANDLE hConsoleOutput, - DWORD nFont); - -// Vista and up -typedef BOOL WINAPI GetCurrentConsoleFontEx_t( - HANDLE hConsoleOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); - -// Vista and up -typedef BOOL WINAPI SetCurrentConsoleFontEx_t( - HANDLE hConsoleOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); - -#define GET_MODULE_PROC(mod, funcName) \ - m_##funcName = reinterpret_cast((mod).proc(#funcName)); \ - -#define DEFINE_ACCESSOR(funcName) \ - funcName##_t &funcName() const { \ - ASSERT(valid()); \ - return *m_##funcName; \ - } - -class XPFontAPI { -public: - XPFontAPI() : m_kernel32(L"kernel32.dll") { - GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont); - GET_MODULE_PROC(m_kernel32, GetConsoleFontSize); - } - - bool valid() const { - return m_GetCurrentConsoleFont != NULL && - m_GetConsoleFontSize != NULL; - } - - DEFINE_ACCESSOR(GetCurrentConsoleFont) - DEFINE_ACCESSOR(GetConsoleFontSize) - -private: - OsModule m_kernel32; - GetCurrentConsoleFont_t *m_GetCurrentConsoleFont; - GetConsoleFontSize_t *m_GetConsoleFontSize; -}; - -class UndocumentedXPFontAPI : public XPFontAPI { -public: - UndocumentedXPFontAPI() : m_kernel32(L"kernel32.dll") { - GET_MODULE_PROC(m_kernel32, SetConsoleFont); - GET_MODULE_PROC(m_kernel32, GetNumberOfConsoleFonts); - } - - bool valid() const { - return this->XPFontAPI::valid() && - m_SetConsoleFont != NULL && - m_GetNumberOfConsoleFonts != NULL; - } - - DEFINE_ACCESSOR(SetConsoleFont) - DEFINE_ACCESSOR(GetNumberOfConsoleFonts) - -private: - OsModule m_kernel32; - SetConsoleFont_t *m_SetConsoleFont; - GetNumberOfConsoleFonts_t *m_GetNumberOfConsoleFonts; -}; - -class VistaFontAPI : public XPFontAPI { -public: - VistaFontAPI() : m_kernel32(L"kernel32.dll") { - GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx); - GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx); - } - - bool valid() const { - return this->XPFontAPI::valid() && - m_GetCurrentConsoleFontEx != NULL && - m_SetCurrentConsoleFontEx != NULL; - } - - DEFINE_ACCESSOR(GetCurrentConsoleFontEx) - DEFINE_ACCESSOR(SetCurrentConsoleFontEx) - -private: - OsModule m_kernel32; - GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx; - SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx; -}; - -static std::vector > readFontTable( - XPFontAPI &api, HANDLE conout, DWORD maxCount) { - std::vector > ret; - for (DWORD i = 0; i < maxCount; ++i) { - COORD size = api.GetConsoleFontSize()(conout, i); - if (size.X == 0 && size.Y == 0) { - break; - } - ret.push_back(std::make_pair(i, size)); - } - return ret; -} - -static void dumpFontTable(HANDLE conout) { - const int kMaxCount = 1000; - XPFontAPI api; - if (!api.valid()) { - printf("dumpFontTable: cannot dump font table -- missing APIs\n"); - return; - } - std::vector > table = - readFontTable(api, conout, kMaxCount); - std::string line; - char tmp[128]; - size_t first = 0; - while (first < table.size()) { - size_t last = std::min(table.size() - 1, first + 10 - 1); - winpty_snprintf(tmp, "%02u-%02u:", - static_cast(first), static_cast(last)); - line = tmp; - for (size_t i = first; i <= last; ++i) { - if (i % 10 == 5) { - line += " - "; - } - winpty_snprintf(tmp, " %2dx%-2d", - table[i].second.X, table[i].second.Y); - line += tmp; - } - printf("%s\n", line.c_str()); - first = last + 1; - } - if (table.size() == kMaxCount) { - printf("... stopped reading at %d fonts ...\n", kMaxCount); - } -} - -static std::string stringToCodePoints(const std::wstring &str) { - std::string ret = "("; - for (size_t i = 0; i < str.size(); ++i) { - char tmp[32]; - winpty_snprintf(tmp, "%X", str[i]); - if (ret.size() > 1) { - ret.push_back(' '); - } - ret += tmp; - } - ret.push_back(')'); - return ret; -} - -static void dumpFontInfoEx( - const AGENT_CONSOLE_FONT_INFOEX &infoex) { - std::wstring faceName(infoex.FaceName, - winpty_wcsnlen(infoex.FaceName, COUNT_OF(infoex.FaceName))); - cprintf(L"nFont=%u dwFontSize=(%d,%d) " - "FontFamily=0x%x FontWeight=%u FaceName=%ls %hs\n", - static_cast(infoex.nFont), - infoex.dwFontSize.X, infoex.dwFontSize.Y, - infoex.FontFamily, infoex.FontWeight, faceName.c_str(), - stringToCodePoints(faceName).c_str()); -} - -static void dumpVistaFont(VistaFontAPI &api, HANDLE conout, BOOL maxWindow) { - AGENT_CONSOLE_FONT_INFOEX infoex = {0}; - infoex.cbSize = sizeof(infoex); - if (!api.GetCurrentConsoleFontEx()(conout, maxWindow, &infoex)) { - printf("GetCurrentConsoleFontEx call failed\n"); - return; - } - dumpFontInfoEx(infoex); -} - -static void dumpXPFont(XPFontAPI &api, HANDLE conout, BOOL maxWindow) { - AGENT_CONSOLE_FONT_INFO info = {0}; - if (!api.GetCurrentConsoleFont()(conout, maxWindow, &info)) { - printf("GetCurrentConsoleFont call failed\n"); - return; - } - printf("nFont=%u dwFontSize=(%d,%d)\n", - static_cast(info.nFont), - info.dwFontSize.X, info.dwFontSize.Y); -} - -static void dumpFontAndTable(HANDLE conout) { - VistaFontAPI vista; - if (vista.valid()) { - printf("maxWnd=0: "); dumpVistaFont(vista, conout, FALSE); - printf("maxWnd=1: "); dumpVistaFont(vista, conout, TRUE); - dumpFontTable(conout); - return; - } - UndocumentedXPFontAPI xp; - if (xp.valid()) { - printf("maxWnd=0: "); dumpXPFont(xp, conout, FALSE); - printf("maxWnd=1: "); dumpXPFont(xp, conout, TRUE); - dumpFontTable(conout); - return; - } - printf("setSmallFont: neither Vista nor XP APIs detected -- giving up\n"); - dumpFontTable(conout); -} - -int main() { - const HANDLE conout = openConout(); - const COORD largest = GetLargestConsoleWindowSize(conout); - printf("largestConsoleWindowSize=(%d,%d)\n", largest.X, largest.Y); - dumpFontAndTable(conout); - UndocumentedXPFontAPI xp; - if (xp.valid()) { - printf("GetNumberOfConsoleFonts returned %u\n", xp.GetNumberOfConsoleFonts()()); - } else { - printf("The GetNumberOfConsoleFonts API was missing\n"); - } - printf("CP=%u OutputCP=%u\n", GetConsoleCP(), GetConsoleOutputCP()); - return 0; -} diff --git a/deps/winpty/misc/IdentifyConsoleWindow.ps1 b/deps/winpty/misc/IdentifyConsoleWindow.ps1 deleted file mode 100644 index 0c488597b..000000000 --- a/deps/winpty/misc/IdentifyConsoleWindow.ps1 +++ /dev/null @@ -1,51 +0,0 @@ -# -# Usage: powershell \IdentifyConsoleWindow.ps1 -# -# This script determines whether the process has a console attached, whether -# that console has a non-NULL window (e.g. HWND), and whether the window is on -# the current window station. -# - -$signature = @' -[DllImport("kernel32.dll", SetLastError=true)] -public static extern IntPtr GetConsoleWindow(); - -[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] -public static extern bool SetConsoleTitle(String title); - -[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)] -public static extern int GetWindowText(IntPtr hWnd, - System.Text.StringBuilder lpString, - int nMaxCount); -'@ - -$WinAPI = Add-Type -MemberDefinition $signature ` - -Name WinAPI -Namespace IdentifyConsoleWindow -PassThru - -if (!$WinAPI::SetConsoleTitle("ConsoleWindowScript")) { - echo "error: could not change console title -- is a console attached?" - exit 1 -} else { - echo "note: successfully set console title to ""ConsoleWindowScript""." -} - -$hwnd = $WinAPI::GetConsoleWindow() -if ($hwnd -eq 0) { - echo "note: GetConsoleWindow returned NULL." -} else { - echo "note: GetConsoleWindow returned 0x$($hwnd.ToString("X"))." - $sb = New-Object System.Text.StringBuilder -ArgumentList 4096 - if ($WinAPI::GetWindowText($hwnd, $sb, $sb.Capacity)) { - $title = $sb.ToString() - echo "note: GetWindowText returned ""${title}""." - if ($title -eq "ConsoleWindowScript") { - echo "success!" - } else { - echo "error: expected to see ""ConsoleWindowScript""." - echo " (Perhaps the console window is on a different window station?)" - } - } else { - echo "error: GetWindowText could not read the window title." - echo " (Perhaps the console window is on a different window station?)" - } -} diff --git a/deps/winpty/misc/IsNewConsole.cc b/deps/winpty/misc/IsNewConsole.cc deleted file mode 100644 index 2b554c72c..000000000 --- a/deps/winpty/misc/IsNewConsole.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Determines whether this is a new console by testing whether MARK moves the -// cursor. -// -// WARNING: This test program may behave erratically if run under winpty. -// - -#include - -#include -#include - -#include "TestUtil.cc" - -const int SC_CONSOLE_MARK = 0xFFF2; -const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - -static COORD getWindowPos(HANDLE conout) { - CONSOLE_SCREEN_BUFFER_INFO info = {}; - BOOL ret = GetConsoleScreenBufferInfo(conout, &info); - ASSERT(ret && "GetConsoleScreenBufferInfo failed"); - return { info.srWindow.Left, info.srWindow.Top }; -} - -static COORD getWindowSize(HANDLE conout) { - CONSOLE_SCREEN_BUFFER_INFO info = {}; - BOOL ret = GetConsoleScreenBufferInfo(conout, &info); - ASSERT(ret && "GetConsoleScreenBufferInfo failed"); - return { - static_cast(info.srWindow.Right - info.srWindow.Left + 1), - static_cast(info.srWindow.Bottom - info.srWindow.Top + 1) - }; -} - -static COORD getCursorPos(HANDLE conout) { - CONSOLE_SCREEN_BUFFER_INFO info = {}; - BOOL ret = GetConsoleScreenBufferInfo(conout, &info); - ASSERT(ret && "GetConsoleScreenBufferInfo failed"); - return info.dwCursorPosition; -} - -static void setCursorPos(HANDLE conout, COORD pos) { - BOOL ret = SetConsoleCursorPosition(conout, pos); - ASSERT(ret && "SetConsoleCursorPosition failed"); -} - -int main() { - const HANDLE conout = openConout(); - const HWND hwnd = GetConsoleWindow(); - ASSERT(hwnd != NULL && "GetConsoleWindow() returned NULL"); - - // With the legacy console, the Mark command moves the the cursor to the - // top-left cell of the visible console window. Determine whether this - // is the new console by seeing if the cursor moves. - - const auto windowSize = getWindowSize(conout); - if (windowSize.X <= 1) { - printf("Error: console window must be at least 2 columns wide\n"); - trace("Error: console window must be at least 2 columns wide"); - return 1; - } - - bool cursorMoved = false; - const auto initialPos = getCursorPos(conout); - - const auto windowPos = getWindowPos(conout); - setCursorPos(conout, { static_cast(windowPos.X + 1), windowPos.Y }); - - { - const auto posA = getCursorPos(conout); - SendMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_MARK, 0); - const auto posB = getCursorPos(conout); - cursorMoved = memcmp(&posA, &posB, sizeof(posA)) != 0; - SendMessage(hwnd, WM_CHAR, 27, 0x00010001); // Send ESCAPE - } - - setCursorPos(conout, initialPos); - - if (cursorMoved) { - printf("Legacy console (i.e. MARK moved cursor)\n"); - trace("Legacy console (i.e. MARK moved cursor)"); - } else { - printf("Windows 10 new console (i.e MARK did not move cursor)\n"); - trace("Windows 10 new console (i.e MARK did not move cursor)"); - } - - return 0; -} diff --git a/deps/winpty/misc/MouseInputNotes.txt b/deps/winpty/misc/MouseInputNotes.txt deleted file mode 100644 index 18460c686..000000000 --- a/deps/winpty/misc/MouseInputNotes.txt +++ /dev/null @@ -1,90 +0,0 @@ -Introduction -============ - -The only specification I could find describing mouse input escape sequences -was the /usr/share/doc/xterm/ctlseqs.txt.gz file installed on my Ubuntu -machine. - -Here are the relevant escape sequences: - - * [ON] CSI '?' M 'h' Enable mouse input mode M - * [OFF] CSI '?' M 'l' Disable mouse input mode M - * [EVT] CSI 'M' F X Y Mouse event (default or mode 1005) - * [EVT6] CSI '<' F ';' X ';' Y 'M' Mouse event with mode 1006 - * [EVT6] CSI '<' F ';' X ';' Y 'm' Mouse event with mode 1006 (up) - * [EVT15] CSI F ';' X ';' Y 'M' Mouse event with mode 1015 - -The first batch of modes affect what events are reported: - - * 9: Presses only (not as well-supported as the other modes) - * 1000: Presses and releases - * 1002: Presses, releases, and moves-while-pressed - * 1003: Presses, releases, and all moves - -The next batch of modes affect the encoding of the mouse events: - - * 1005: The X and Y coordinates are UTF-8 codepoints rather than bytes. - * 1006: Use the EVT6 sequences instead of EVT - * 1015: Use the EVT15 sequence instead of EVT (aka URVXT-mode) - -Support for modes in existing terminals -======================================= - - | 9 1000 1002 1003 | 1004 | overflow | defhi | 1005 1006 1015 ----------------------------------+---------------------+------+--------------+-------+---------------- -Eclipse TM Terminal (Neon) | _ _ _ _ | _ | n/a | n/a | _ _ _ -gnome-terminal 3.6.2 | X X X X | _ | suppressed*b | 0x07 | _ X X -iTerm2 2.1.4 | _ X X X | OI | wrap*z | n/a | X X X -jediterm/IntelliJ | _ X X X | _ | ch='?' | 0xff | X X X -Konsole 2.13.2 | _ X X *a | _ | suppressed | 0xff | X X X -mintty 2.2.2 | X X X X | OI | ch='\0' | 0xff | X X X -putty 0.66 | _ X X _ | _ | suppressed | 0xff | _ X X -rxvt 2.7.10 | X X _ _ | _ | wrap*z | n/a | _ _ _ -screen(under xterm) | X X X X | _ | suppressed | 0xff | _ _ _ -urxvt 9.21 | X X X X | _ | wrap*z | n/a | X _ X -xfce4-terminal 0.6.3 (GTK2 VTE) | X X X X | _ | wrap | n/a | _ _ _ -xterm | X X X X | OI | ch='\0' | 0xff | X X X - -*a: Mode 1003 is handled the same way as 1002. -*b: The coordinate wraps from 0xff to 0x00, then maxs out at 0x07. I'm - guessing this behavior is a bug? I'm using the Xubuntu 14.04 - gnome-terminal. -*z: These terminals have a bug where column 224 (and row 224, presumably) - yields a truncated escape sequence. 224 + 32 is 0, so it would normally - yield `CSI 'M' F '\0' Y`, but the '\0' is interpreted as a NUL-terminator. - -Problem 1: How do these flags work? -=================================== - -Terminals accept the OFF sequence with any of the input modes. This makes -little sense--there are two multi-value settings, not seven independent flags! - -All the terminals handle Granularity the same way. ON-Granularity sets -Granularity to the specified value, and OFF-Granularity sets Granularity to -OFF. - -Terminals vary in how they handle the Encoding modes. For example: - - * xterm. ON-Encoding sets Encoding. OFF-Encoding with a non-active Encoding - has no effect. OFF-Encoding otherwise resets Encoding to Default. - - * mintty (tested 2.2.2), iTerm2 2.1.4, and jediterm. ON-Encoding sets - Encoding. OFF-Encoding resets Encoding to Default. - - * Konsole (tested 2.13.2) seems to configure each encoding method - independently. The effective Encoding is the first enabled encoding in this - list: - - Mode 1006 - - Mode 1015 - - Mode 1005 - - Default - - * gnome-terminal (tested 3.6.2) also configures each encoding method - independently. The effective Encoding is the first enabled encoding in - this list: - - Mode 1006 - - Mode 1015 - - Default - Mode 1005 is not supported. - - * xfce4 terminal 0.6.3 (GTK2 VTE) always outputs the default encoding method. diff --git a/deps/winpty/misc/MoveConsoleWindow.cc b/deps/winpty/misc/MoveConsoleWindow.cc deleted file mode 100644 index 7d9684fe9..000000000 --- a/deps/winpty/misc/MoveConsoleWindow.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc != 3 && argc != 5) { - printf("Usage: %s x y\n", argv[0]); - printf("Usage: %s x y width height\n", argv[0]); - return 1; - } - - HWND hwnd = GetConsoleWindow(); - - const int x = atoi(argv[1]); - const int y = atoi(argv[2]); - - int w = 0, h = 0; - if (argc == 3) { - RECT r = {}; - BOOL ret = GetWindowRect(hwnd, &r); - ASSERT(ret && "GetWindowRect failed on console window"); - w = r.right - r.left; - h = r.bottom - r.top; - } else { - w = atoi(argv[3]); - h = atoi(argv[4]); - } - - BOOL ret = MoveWindow(hwnd, x, y, w, h, TRUE); - trace("MoveWindow: ret=%d", ret); - printf("MoveWindow: ret=%d\n", ret); - - return 0; -} diff --git a/deps/winpty/misc/Notes.txt b/deps/winpty/misc/Notes.txt deleted file mode 100644 index 410e18419..000000000 --- a/deps/winpty/misc/Notes.txt +++ /dev/null @@ -1,219 +0,0 @@ -Test programs -------------- - -Cygwin - emacs - vim - mc (Midnight Commander) - lynx - links - less - more - wget - -Capturing the console output ----------------------------- - -Initial idea: - -In the agent, keep track of the remote terminal state for N lines of -(window+history). Also keep track of the terminal size. Regularly poll for -changes to the console screen buffer, then use some number of edits to bring -the remote terminal into sync with the console. - -This idea seems to have trouble when a Unix terminal is resized. When the -server receives a resize notification, it can have a hard time figuring out -what the terminal did. Race conditions might also be a problem. - -The behavior of the terminal can be tricky: - - - When the window is expanded by one line, does the terminal add a blank line - to the bottom or move a line from the history into the top? - - - When the window is shrunk by one line, does the terminal delete the topmost - or the bottommost line? Can it delete the line with the cursor? - -Some popular behaviors for expanding: - - [all] If there are no history lines, then add a line at the bottom. - - [konsole] Always add a line at the bottom. - - [putty,xterm,rxvt] Pull in a history line from the top. - - [g-t] I can't tell. It seems to add a blank line, until the program writes - to stdout or until I click the scroll bar, then the output "snaps" back down, - pulling lines out of the history. I thought I saw different behavior - between Ubuntu 10.10 and 11.10, so maybe GNOME 3 changed something. Avoid - using "bash" to test this behavior because "bash" apparently always writes - the prompt after terminal resize. - -Some popular behaviors for shrinking: - - [konsole,putty,xterm,rxvt] If the line at the bottom is blank, then delete - it. Otherwise, move the topmost line into history. - - [g-t] If the line at the bottom has not been touched, then delete it. - Otherwise, move the topmost line into history. - -(TODO: I need to test my theories about the terminal behavior better still. -It's interesting to see how g-t handles clear differently than every other -terminal.) - -There is an ANSI escape sequence (DSR) that sends the current cursor location -to the terminal's input. One idea I had was to use this code to figure out how -the terminal had handled a resize. I currently think this idea won't work due -to race conditions. - -Newer idea: - -Keep track of the last N lines that have been sent to the remote terminal. -Poll for changes to console output. When the output changes, send just the -changed content to the terminal. In particular: - - Don't send a cursor position (CUP) code. Instead, if the line that's 3 - steps up from the latest line changes, send a relative cursor up (CUU) - code. It's OK to send an absolute column number code (CHA). - - At least in general, don't try to send complete screenshots of the current - console window. - -The idea is that sending just the changes should have good behavior for streams -of output, even when those streams modify the output (e.g. an archiver, or -maybe a downloader/packager/wget). I need to think about whether this works -for full-screen programs (e.g. emacs, less, lynx, the above list of programs). - -I noticed that console programs don't typically modify the window or buffer -coordinates. edit.com is an exception. - -I tested the pager in native Python (more?), and I verified that ENTER and SPACE -both paid no attention to the location of the console window within the screen -buffer. This makes sense -- why would they care? The Cygwin less, on the other -hand, does care. If I scroll the window up, then Cygwin less will write to a -position within the window. I didn't really expect this behavior, but it -doesn't seem to be a problem. - -Setting up a TestNetServer service ----------------------------------- - -First run the deploy.sh script to copy files into deploy. Make sure -TestNetServer.exe will run in a bare environment (no MinGW or Qt in the path). - -Install the Windows Server 2003 Resource Kit. It will have two programs in it, -instsrv and srvany. - -Run: - - InstSrv TestNetServer \srvany.exe - -This creates a service named "TestNetServer" that uses the Microsoft service -wrapper. To configure the new service to run TestNetServer, set a registry -value: - - [HKLM\SYSTEM\CurrentControlSet\Services\TestNetServer\Parameters] - Application=\TestNetServer.exe - -Also see http://www.iopus.com/guides/srvany.htm. - -To remove the service, run: - - InstSrv TestNetServer REMOVE - -TODO ----- - -Agent: When resizing the console, consider whether to add lines to the top -or bottom. I remember thinking the current behavior was wrong for some -application, but I forgot which one. - -Make the font as small as possible. The console window dimensions are limited by -the screen size, so making the font small reduces an unnecessary limitation on the -PseudoConsole size. There's a documented Vista/Win7 API for this -(SetCurrentConsoleFontEx), and apparently WinXP has an undocumented API -(SetConsoleFont): - http://blogs.microsoft.co.il/blogs/pavely/archive/2009/07/23/changing-console-fonts.aspx - -Make the agent work with DOS programs like edit and qbasic. - - Detect that the terminal program has resized the window/buffer and enter a - simple just-scrape-and-dont-resize mode. Track the client window size and - send the intersection of the console and the agent's client. - - I also need to generate keyboard scan codes. - - Solve the NTVDM.EXE console shutdown problem, probably by ignoring NTVDM.EXE - when it appears on the GetConsoleProcessList list. - -Rename the agent? Is the term "proxy" more accurate? - -Optimize the polling. e.g. Use a longer poll interval when the console is idle. -Do a minimal poll that checks whether the sync marker or window has moved. - -Increase the console buffer size to ~9000 lines. Beware making it so big that -reading the sync column exhausts the 32KB conhost<->agent heap. - -Reduce the memory overhead of the agent. The agent's m_bufferData array can -be small (a few hundred lines?) relative to the console buffer size. - -Try to handle console background color better. - Unix terminal emulators have a user-configurable foreground and background -color, and for best results, the agent really needs to avoid changing the colors, -especially the background color. It's undesirable/ugly to SSH into a machine -and see the command prompt change the colors. It's especially ugly that the -terminal retains its original colors and only drawn cells get the new colors. -(e.g. Resizing the window to the right uses the local terminal colors rather -than the remote colors.) It's especially ugly in gnome-terminal, which draws -user-configurable black as black, but VT100 black as dark-gray. - If there were a way to query the terminal emulator's colors, then I could -match the console's colors to the terminal and everything would just work. As -far as I know, that's not possible. - I thought of a kludge that might work. Instead of translating console white -and black to VT/100 white and black, I would translate them to "reset" and -"invert". I'd translate other colors normally. This approach should produce -ideal results for command-line work and tolerable results for full-screen -programs without configuration. Configuring the agent for black-on-white or -white-on-black would produce ideal results in all situations. - This kludge only really applies to the SSH application. For a Win32 Konsole -application, it should be easy to get the colors right all the time. - -Try using the screen reader API: - - To eliminate polling. - - To detect when a line wraps. When a line wraps, it'd be nice not to send a - CRLF to the terminal emulator so copy-and-paste works better. - - To detect hard tabs with Cygwin. - -Implement VT100/ANSI escape sequence recognition for input. Decide where this -functionality belongs. PseudoConsole.dll? Disambiguating ESC from an escape -sequence might be tricky. For the SSH server, I was thinking that when a small -SSH payload ended with an ESC character, I could assume the character was really -an ESC keypress, on the assumption that if it were an escape sequence, the -payload would probably contain the whole sequence. I'm not sure this works, -especially if there's a lot of other traffic multiplexed on the SSH socket. - -Support Unicode. - - Some DOS programs draw using line/box characters. Can these characters be - translated to the Unicode equivalents? - -Create automated tests. - -Experiment with the Terminator emulator, an emulator that doesn't wrap lines. -How many columns does it report having? What column does it report the cursor -in as it's writing past the right end of the window? Will Terminator be a -problem if I implement line wrapping detection in the agent? - -BUG: After the unix-adapter/pconsole.exe program exits, the blinking cursor is -replaced with a hidden cursor. - -Fix assert() in the agent. If it fails, the failure message needs to be -reported somewhere. Pop up a dialog box? Maybe switch the active desktop, -then show a dialog box? - -TODO: There's already a pconsole project on GitHub. Maybe rename this project -to something else? winpty? - -TODO: Can the DebugServer system be replaced with OutputDebugString? How -do we decide whose processes' output to collect? - -TODO: Three executables: - build/winpty-agent.exe - build/winpty.dll - build/console.exe - -BUG: Run the pconsole.exe inside another console. As I type dir, I see this: - D:\rprichard\pconsole> - D:\rprichard\pconsole>d - D:\rprichard\pconsole>di - D:\rprichard\pconsole>dir - In the output of "dir", every other line is blank. - There was a bug in Terminal::sendLine that was causing this to happen - frequently. Now that I fixed it, this bug should only manifest on lines - whose last column is not a space (i.e. a full line). diff --git a/deps/winpty/misc/OSVersion.cc b/deps/winpty/misc/OSVersion.cc deleted file mode 100644 index 456708f05..000000000 --- a/deps/winpty/misc/OSVersion.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#include -#include -#include - -#include - -int main() { - setlocale(LC_ALL, ""); - - OSVERSIONINFOEXW info = {0}; - info.dwOSVersionInfoSize = sizeof(info); - assert(GetVersionExW((OSVERSIONINFOW*)&info)); - - printf("dwMajorVersion = %d\n", (int)info.dwMajorVersion); - printf("dwMinorVersion = %d\n", (int)info.dwMinorVersion); - printf("dwBuildNumber = %d\n", (int)info.dwBuildNumber); - printf("dwPlatformId = %d\n", (int)info.dwPlatformId); - printf("szCSDVersion = %ls\n", info.szCSDVersion); - printf("wServicePackMajor = %d\n", info.wServicePackMajor); - printf("wServicePackMinor = %d\n", info.wServicePackMinor); - printf("wSuiteMask = 0x%x\n", (unsigned int)info.wSuiteMask); - printf("wProductType = 0x%x\n", (unsigned int)info.wProductType); - - return 0; -} diff --git a/deps/winpty/misc/ScreenBufferFreezeInactive.cc b/deps/winpty/misc/ScreenBufferFreezeInactive.cc deleted file mode 100644 index 656d4f126..000000000 --- a/deps/winpty/misc/ScreenBufferFreezeInactive.cc +++ /dev/null @@ -1,101 +0,0 @@ -// -// Verify that console selection blocks writes to an inactive console screen -// buffer. Writes TEST PASSED or TEST FAILED to the popup console window. -// - -#include -#include - -#include - -#include "TestUtil.cc" - -const int SC_CONSOLE_MARK = 0xFFF2; -const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - -bool g_useMark = false; - -CALLBACK DWORD pausingThread(LPVOID dummy) -{ - HWND hwnd = GetConsoleWindow(); - trace("Sending selection to freeze"); - SendMessage(hwnd, WM_SYSCOMMAND, - g_useMark ? SC_CONSOLE_MARK : - SC_CONSOLE_SELECT_ALL, - 0); - Sleep(1000); - trace("Sending escape WM_CHAR to unfreeze"); - SendMessage(hwnd, WM_CHAR, 27, 0x00010001); - Sleep(1000); -} - -static HANDLE createBuffer() { - HANDLE buf = CreateConsoleScreenBuffer( - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - CONSOLE_TEXTMODE_BUFFER, - NULL); - ASSERT(buf != INVALID_HANDLE_VALUE); - return buf; -} - -static void runTest(bool useMark, bool createEarly) { - trace("======================================="); - trace("useMark=%d createEarly=%d", useMark, createEarly); - g_useMark = useMark; - HANDLE buf = INVALID_HANDLE_VALUE; - - if (createEarly) { - buf = createBuffer(); - } - - CreateThread(NULL, 0, - pausingThread, NULL, - 0, NULL); - Sleep(500); - - if (!createEarly) { - trace("Creating buffer"); - TimeMeasurement tm1; - buf = createBuffer(); - const double elapsed1 = tm1.elapsed(); - if (elapsed1 >= 0.250) { - printf("!!! TEST FAILED !!!\n"); - Sleep(2000); - return; - } - } - - trace("Writing to aux buffer"); - TimeMeasurement tm2; - DWORD actual = 0; - BOOL ret = WriteConsoleW(buf, L"HI", 2, &actual, NULL); - const double elapsed2 = tm2.elapsed(); - trace("Writing to aux buffer: finished: ret=%d actual=%d (elapsed=%1.3f)", ret, actual, elapsed2); - if (elapsed2 < 0.250) { - printf("!!! TEST FAILED !!!\n"); - } else { - printf("TEST PASSED\n"); - } - Sleep(2000); -} - -int main(int argc, char **argv) { - if (argc == 1) { - startChildProcess(L"child"); - return 0; - } - - std::string arg = argv[1]; - if (arg == "child") { - for (int useMark = 0; useMark <= 1; useMark++) { - for (int createEarly = 0; createEarly <= 1; createEarly++) { - runTest(useMark, createEarly); - } - } - printf("done...\n"); - Sleep(1000); - } - return 0; -} diff --git a/deps/winpty/misc/ScreenBufferTest.cc b/deps/winpty/misc/ScreenBufferTest.cc deleted file mode 100644 index fa584b9fa..000000000 --- a/deps/winpty/misc/ScreenBufferTest.cc +++ /dev/null @@ -1,671 +0,0 @@ -// -// Windows versions tested -// -// Vista Enterprise SP2 32-bit -// - ver reports [Version 6.0.6002] -// - kernel32.dll product/file versions are 6.0.6002.19381 -// -// Windows 7 Ultimate SP1 32-bit -// - ver reports [Version 6.1.7601] -// - conhost.exe product/file versions are 6.1.7601.18847 -// - kernel32.dll product/file versions are 6.1.7601.18847 -// -// Windows Server 2008 R2 Datacenter SP1 64-bit -// - ver reports [Version 6.1.7601] -// - conhost.exe product/file versions are 6.1.7601.23153 -// - kernel32.dll product/file versions are 6.1.7601.23153 -// -// Windows 8 Enterprise 32-bit -// - ver reports [Version 6.2.9200] -// - conhost.exe product/file versions are 6.2.9200.16578 -// - kernel32.dll product/file versions are 6.2.9200.16859 -// - -// -// Specific version details on working Server 2008 R2: -// -// dwMajorVersion = 6 -// dwMinorVersion = 1 -// dwBuildNumber = 7601 -// dwPlatformId = 2 -// szCSDVersion = Service Pack 1 -// wServicePackMajor = 1 -// wServicePackMinor = 0 -// wSuiteMask = 0x190 -// wProductType = 0x3 -// -// Specific version details on broken Win7: -// -// dwMajorVersion = 6 -// dwMinorVersion = 1 -// dwBuildNumber = 7601 -// dwPlatformId = 2 -// szCSDVersion = Service Pack 1 -// wServicePackMajor = 1 -// wServicePackMinor = 0 -// wSuiteMask = 0x100 -// wProductType = 0x1 -// - -#include -#include -#include - -#include "TestUtil.cc" - -const char *g_prefix = ""; - -static void dumpHandles() { - trace("%sSTDIN=0x%I64x STDOUT=0x%I64x STDERR=0x%I64x", - g_prefix, - (long long)GetStdHandle(STD_INPUT_HANDLE), - (long long)GetStdHandle(STD_OUTPUT_HANDLE), - (long long)GetStdHandle(STD_ERROR_HANDLE)); -} - -static const char *successOrFail(BOOL ret) { - return ret ? "ok" : "FAILED"; -} - -static void startChildInSameConsole(const wchar_t *args, BOOL - bInheritHandles=FALSE) { - wchar_t program[1024]; - wchar_t cmdline[1024]; - GetModuleFileNameW(NULL, program, 1024); - swprintf(cmdline, L"\"%ls\" %ls", program, args); - - STARTUPINFOW sui; - PROCESS_INFORMATION pi; - memset(&sui, 0, sizeof(sui)); - memset(&pi, 0, sizeof(pi)); - sui.cb = sizeof(sui); - - CreateProcessW(program, cmdline, - NULL, NULL, - /*bInheritHandles=*/bInheritHandles, - /*dwCreationFlags=*/0, - NULL, NULL, - &sui, &pi); -} - -static void closeHandle(HANDLE h) { - trace("%sClosing handle 0x%I64x...", g_prefix, (long long)h); - trace("%sClosing handle 0x%I64x... %s", g_prefix, (long long)h, successOrFail(CloseHandle(h))); -} - -static HANDLE createBuffer() { - - // If sa isn't provided, the handle defaults to not-inheritable. - SECURITY_ATTRIBUTES sa = {0}; - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - - trace("%sCreating a new buffer...", g_prefix); - HANDLE conout = CreateConsoleScreenBuffer( - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - CONSOLE_TEXTMODE_BUFFER, NULL); - - trace("%sCreating a new buffer... 0x%I64x", g_prefix, (long long)conout); - return conout; -} - -static HANDLE openConout() { - - // If sa isn't provided, the handle defaults to not-inheritable. - SECURITY_ATTRIBUTES sa = {0}; - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - - trace("%sOpening CONOUT...", g_prefix); - HANDLE conout = CreateFileW(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, 0, NULL); - trace("%sOpening CONOUT... 0x%I64x", g_prefix, (long long)conout); - return conout; -} - -static void setConsoleActiveScreenBuffer(HANDLE conout) { - trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called...", - g_prefix, (long long)conout); - trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called... %s", - g_prefix, (long long)conout, - successOrFail(SetConsoleActiveScreenBuffer(conout))); -} - -static void writeTest(HANDLE conout, const char *msg) { - char writeData[256]; - sprintf(writeData, "%s%s\n", g_prefix, msg); - - trace("%sWriting to 0x%I64x: '%s'...", - g_prefix, (long long)conout, msg); - DWORD actual = 0; - BOOL ret = WriteConsoleA(conout, writeData, strlen(writeData), &actual, NULL); - trace("%sWriting to 0x%I64x: '%s'... %s", - g_prefix, (long long)conout, msg, - successOrFail(ret && actual == strlen(writeData))); -} - -static void writeTest(const char *msg) { - writeTest(GetStdHandle(STD_OUTPUT_HANDLE), msg); -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST 1 -- create new buffer, activate it, and close the handle. The console -// automatically switches the screen buffer back to the original. -// -// This test passes everywhere. -// - -static void test1(int argc, char *argv[]) { - if (!strcmp(argv[1], "1")) { - startChildProcess(L"1:child"); - return; - } - - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - writeTest(origBuffer, "<-- origBuffer -->"); - - HANDLE newBuffer = createBuffer(); - writeTest(newBuffer, "<-- newBuffer -->"); - setConsoleActiveScreenBuffer(newBuffer); - Sleep(2000); - - writeTest(origBuffer, "TEST PASSED!"); - - // Closing the handle w/o switching the active screen buffer automatically - // switches the console back to the original buffer. - closeHandle(newBuffer); - - while (true) { - Sleep(1000); - } -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST 2 -- Test program that creates and activates newBuffer, starts a child -// process, then closes its newBuffer handle. newBuffer remains activated, -// because the child keeps it active. (Also see TEST D.) -// - -static void test2(int argc, char *argv[]) { - if (!strcmp(argv[1], "2")) { - startChildProcess(L"2:parent"); - return; - } - - if (!strcmp(argv[1], "2:parent")) { - g_prefix = "parent: "; - dumpHandles(); - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - writeTest(origBuffer, "<-- origBuffer -->"); - - HANDLE newBuffer = createBuffer(); - writeTest(newBuffer, "<-- newBuffer -->"); - setConsoleActiveScreenBuffer(newBuffer); - - Sleep(1000); - writeTest(newBuffer, "bInheritHandles=FALSE:"); - startChildInSameConsole(L"2:child", FALSE); - Sleep(1000); - writeTest(newBuffer, "bInheritHandles=TRUE:"); - startChildInSameConsole(L"2:child", TRUE); - - Sleep(1000); - trace("parent:----"); - - // Close the new buffer. The active screen buffer doesn't automatically - // switch back to origBuffer, because the child process has a handle open - // to the original buffer. - closeHandle(newBuffer); - - Sleep(600 * 1000); - return; - } - - if (!strcmp(argv[1], "2:child")) { - g_prefix = "child: "; - dumpHandles(); - // The child's output isn't visible, because it's still writing to - // origBuffer. - trace("child:----"); - writeTest("writing to STDOUT"); - - // Handle inheritability is curious. The console handles this program - // creates are inheritable, but CreateProcess is called with both - // bInheritHandles=TRUE and bInheritHandles=FALSE. - // - // Vista and Windows 7: bInheritHandles has no effect. The child and - // parent processes have the same STDIN/STDOUT/STDERR handles: - // 0x3, 0x7, and 0xB. The parent has a 0xF handle for newBuffer. - // The child can only write to 0x7, 0xB, and 0xF. Only the writes to - // 0xF are visible (i.e. they touch newBuffer). - // - // Windows 8 or Windows 10 (legacy or non-legacy): the lowest 2 bits of - // the HANDLE to WriteConsole seem to be ignored. The new process' - // console handles always refer to the buffer that was active when they - // started, but the values of the handles depend upon bInheritHandles. - // With bInheritHandles=TRUE, the child has the same - // STDIN/STDOUT/STDERR/newBuffer handles as the parent, and the three - // output handles all work, though their output is all visible. With - // bInheritHandles=FALSE, the child has different STDIN/STDOUT/STDERR - // handles, and only the new STDOUT/STDERR handles work. - // - for (unsigned int i = 0x1; i <= 0xB0; ++i) { - char msg[256]; - sprintf(msg, "Write to handle 0x%x", i); - HANDLE h = reinterpret_cast(i); - writeTest(h, msg); - } - - Sleep(600 * 1000); - return; - } -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST A -- demonstrate an apparent Windows bug with screen buffers -// -// Steps: -// - The parent starts a child process. -// - The child process creates and activates newBuffer -// - The parent opens CONOUT$ and writes to it. -// - The parent closes CONOUT$. -// - At this point, broken Windows reactivates origBuffer. -// - The child writes to newBuffer again. -// - The child activates origBuffer again, then closes newBuffer. -// -// Test passes if the message "TEST PASSED!" is visible. -// Test commonly fails if conhost.exe crashes. -// -// Results: -// - Windows 7 Ultimate SP1 32-bit: conhost.exe crashes -// - Windows Server 2008 R2 Datacenter SP1 64-bit: PASS -// - Windows 8 Enterprise 32-bit: PASS -// - Windows 10 64-bit (legacy and non-legacy): PASS -// - -static void testA_parentWork() { - // Open an extra CONOUT$ handle so that the HANDLE values in parent and - // child don't collide. I think it's OK if they collide, but since we're - // trying to track down a Windows bug, it's best to avoid unnecessary - // complication. - HANDLE dummy = openConout(); - - Sleep(3000); - - // Step 2: Open CONOUT$ in the parent. This opens the active buffer, which - // was just created in the child. It's handle 0x13. Write to it. - - HANDLE newBuffer = openConout(); - writeTest(newBuffer, "step2: writing to newBuffer"); - - Sleep(3000); - - // Step 3: Close handle 0x13. With Windows 7, the console switches back to - // origBuffer, and (unless I'm missing something) it shouldn't. - - closeHandle(newBuffer); -} - -static void testA_childWork() { - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - - // - // Step 1: Create the new screen buffer in the child process and make it - // active. (Typically, it's handle 0x0F.) - // - - HANDLE newBuffer = createBuffer(); - - setConsoleActiveScreenBuffer(newBuffer); - writeTest(newBuffer, "<-- newBuffer -->"); - - Sleep(9000); - trace("child:----"); - - // Step 4: write to the newBuffer again. - writeTest(newBuffer, "TEST PASSED!"); - - // - // Step 5: Switch back to the original screen buffer and close the new - // buffer. The switch call succeeds, but the CloseHandle call freezes for - // several seconds, because conhost.exe crashes. - // - Sleep(3000); - - setConsoleActiveScreenBuffer(origBuffer); - writeTest(origBuffer, "writing to origBuffer"); - - closeHandle(newBuffer); - - // The console HWND is NULL. - trace("child: console HWND=0x%I64x", (long long)GetConsoleWindow()); - - // At this point, the console window has closed, but the parent/child - // processes are still running. Calling AllocConsole would fail, but - // calling FreeConsole followed by AllocConsole would both succeed, and a - // new console would appear. -} - -static void testA(int argc, char *argv[]) { - - if (!strcmp(argv[1], "A")) { - startChildProcess(L"A:parent"); - return; - } - - if (!strcmp(argv[1], "A:parent")) { - g_prefix = "parent: "; - trace("parent:----"); - dumpHandles(); - writeTest("<-- origBuffer -->"); - startChildInSameConsole(L"A:child"); - testA_parentWork(); - Sleep(120000); - return; - } - - if (!strcmp(argv[1], "A:child")) { - g_prefix = "child: "; - dumpHandles(); - testA_childWork(); - Sleep(120000); - return; - } -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST B -- invert TEST A -- also crashes conhost on Windows 7 -// -// Test passes if the message "TEST PASSED!" is visible. -// Test commonly fails if conhost.exe crashes. -// -// Results: -// - Windows 7 Ultimate SP1 32-bit: conhost.exe crashes -// - Windows Server 2008 R2 Datacenter SP1 64-bit: PASS -// - Windows 8 Enterprise 32-bit: PASS -// - Windows 10 64-bit (legacy and non-legacy): PASS -// - -static void testB(int argc, char *argv[]) { - if (!strcmp(argv[1], "B")) { - startChildProcess(L"B:parent"); - return; - } - - if (!strcmp(argv[1], "B:parent")) { - g_prefix = "parent: "; - startChildInSameConsole(L"B:child"); - writeTest("<-- origBuffer -->"); - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - - // - // Step 1: Create the new buffer and make it active. - // - trace("%s----", g_prefix); - HANDLE newBuffer = createBuffer(); - setConsoleActiveScreenBuffer(newBuffer); - writeTest(newBuffer, "<-- newBuffer -->"); - - // - // Step 4: Attempt to write again to the new buffer. - // - Sleep(9000); - trace("%s----", g_prefix); - writeTest(newBuffer, "TEST PASSED!"); - - // - // Step 5: Switch back to the original buffer. - // - Sleep(3000); - trace("%s----", g_prefix); - setConsoleActiveScreenBuffer(origBuffer); - closeHandle(newBuffer); - writeTest(origBuffer, "writing to the initial buffer"); - - Sleep(60000); - return; - } - - if (!strcmp(argv[1], "B:child")) { - g_prefix = "child: "; - Sleep(3000); - trace("%s----", g_prefix); - - // - // Step 2: Open the newly active buffer and write to it. - // - HANDLE newBuffer = openConout(); - writeTest(newBuffer, "writing to newBuffer"); - - // - // Step 3: Close the newly active buffer. - // - Sleep(3000); - closeHandle(newBuffer); - - Sleep(60000); - return; - } -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST C -- Interleaving open/close of console handles also seems to break on -// Windows 7. -// -// Test: -// - child creates and activates newBuf1 -// - parent opens newBuf1 -// - child creates and activates newBuf2 -// - parent opens newBuf2, then closes newBuf1 -// - child switches back to newBuf1 -// * At this point, the console starts malfunctioning. -// - parent and child close newBuf2 -// - child closes newBuf1 -// -// Test passes if the message "TEST PASSED!" is visible. -// Test commonly fails if conhost.exe crashes. -// -// Results: -// - Windows 7 Ultimate SP1 32-bit: conhost.exe crashes -// - Windows Server 2008 R2 Datacenter SP1 64-bit: PASS -// - Windows 8 Enterprise 32-bit: PASS -// - Windows 10 64-bit (legacy and non-legacy): PASS -// - -static void testC(int argc, char *argv[]) { - if (!strcmp(argv[1], "C")) { - startChildProcess(L"C:parent"); - return; - } - - if (!strcmp(argv[1], "C:parent")) { - startChildInSameConsole(L"C:child"); - writeTest("<-- origBuffer -->"); - g_prefix = "parent: "; - - // At time=4, open newBuffer1. - Sleep(4000); - trace("%s---- t=4", g_prefix); - const HANDLE newBuffer1 = openConout(); - - // At time=8, open newBuffer2, and close newBuffer1. - Sleep(4000); - trace("%s---- t=8", g_prefix); - const HANDLE newBuffer2 = openConout(); - closeHandle(newBuffer1); - - // At time=25, cleanup of newBuffer2. - Sleep(17000); - trace("%s---- t=25", g_prefix); - closeHandle(newBuffer2); - - Sleep(240000); - return; - } - - if (!strcmp(argv[1], "C:child")) { - g_prefix = "child: "; - - // At time=2, create newBuffer1 and activate it. - Sleep(2000); - trace("%s---- t=2", g_prefix); - const HANDLE newBuffer1 = createBuffer(); - setConsoleActiveScreenBuffer(newBuffer1); - writeTest(newBuffer1, "<-- newBuffer1 -->"); - - // At time=6, create newBuffer2 and activate it. - Sleep(4000); - trace("%s---- t=6", g_prefix); - const HANDLE newBuffer2 = createBuffer(); - setConsoleActiveScreenBuffer(newBuffer2); - writeTest(newBuffer2, "<-- newBuffer2 -->"); - - // At time=10, attempt to switch back to newBuffer1. The parent process - // has opened and closed its handle to newBuffer1, so does it still exist? - Sleep(4000); - trace("%s---- t=10", g_prefix); - setConsoleActiveScreenBuffer(newBuffer1); - writeTest(newBuffer1, "write to newBuffer1: TEST PASSED!"); - - // At time=25, cleanup of newBuffer2. - Sleep(15000); - trace("%s---- t=25", g_prefix); - closeHandle(newBuffer2); - - // At time=35, cleanup of newBuffer1. The console should switch to the - // initial buffer again. - Sleep(10000); - trace("%s---- t=35", g_prefix); - closeHandle(newBuffer1); - - Sleep(240000); - return; - } -} - - - -/////////////////////////////////////////////////////////////////////////////// -// TEST D -- parent creates a new buffer, child launches, writes, -// closes it output handle, then parent writes again. (Also see TEST 2.) -// -// On success, this will appear: -// -// parent: <-- newBuffer --> -// child: writing to newBuffer -// parent: TEST PASSED! -// -// If this appears, it indicates that the child's closing its output handle did -// not destroy newBuffer. -// -// Results: -// - Windows 7 Ultimate SP1 32-bit: PASS -// - Windows 8 Enterprise 32-bit: PASS -// - Windows 10 64-bit (legacy and non-legacy): PASS -// - -static void testD(int argc, char *argv[]) { - if (!strcmp(argv[1], "D")) { - startChildProcess(L"D:parent"); - return; - } - - if (!strcmp(argv[1], "D:parent")) { - g_prefix = "parent: "; - HANDLE origBuffer = GetStdHandle(STD_OUTPUT_HANDLE); - writeTest(origBuffer, "<-- origBuffer -->"); - - HANDLE newBuffer = createBuffer(); - writeTest(newBuffer, "<-- newBuffer -->"); - setConsoleActiveScreenBuffer(newBuffer); - - // At t=2, start a child process, explicitly forcing it to use - // newBuffer for its standard handles. These calls are apparently - // redundant on Windows 8 and up. - Sleep(2000); - trace("parent:----"); - trace("parent: starting child process"); - SetStdHandle(STD_OUTPUT_HANDLE, newBuffer); - SetStdHandle(STD_ERROR_HANDLE, newBuffer); - startChildInSameConsole(L"D:child"); - SetStdHandle(STD_OUTPUT_HANDLE, origBuffer); - SetStdHandle(STD_ERROR_HANDLE, origBuffer); - - // At t=6, write again to newBuffer. - Sleep(4000); - trace("parent:----"); - writeTest(newBuffer, "TEST PASSED!"); - - // At t=8, close the newBuffer. In earlier versions of windows - // (including Server 2008 R2), the console then switches back to - // origBuffer. As of Windows 8, it doesn't, because somehow the child - // process is keeping the console on newBuffer, even though the child - // process closed its STDIN/STDOUT/STDERR handles. Killing the child - // process by hand after the test finishes *does* force the console - // back to origBuffer. - Sleep(2000); - closeHandle(newBuffer); - - Sleep(120000); - return; - } - - if (!strcmp(argv[1], "D:child")) { - g_prefix = "child: "; - // At t=2, the child starts. - trace("child:----"); - dumpHandles(); - writeTest("writing to newBuffer"); - - // At t=4, the child explicitly closes its handle. - Sleep(2000); - trace("child:----"); - if (GetStdHandle(STD_ERROR_HANDLE) != GetStdHandle(STD_OUTPUT_HANDLE)) { - closeHandle(GetStdHandle(STD_ERROR_HANDLE)); - } - closeHandle(GetStdHandle(STD_OUTPUT_HANDLE)); - closeHandle(GetStdHandle(STD_INPUT_HANDLE)); - - Sleep(120000); - return; - } -} - - - -int main(int argc, char *argv[]) { - if (argc == 1) { - printf("USAGE: %s testnum\n", argv[0]); - return 0; - } - - if (argv[1][0] == '1') { - test1(argc, argv); - } else if (argv[1][0] == '2') { - test2(argc, argv); - } else if (argv[1][0] == 'A') { - testA(argc, argv); - } else if (argv[1][0] == 'B') { - testB(argc, argv); - } else if (argv[1][0] == 'C') { - testC(argc, argv); - } else if (argv[1][0] == 'D') { - testD(argc, argv); - } - return 0; -} diff --git a/deps/winpty/misc/ScreenBufferTest2.cc b/deps/winpty/misc/ScreenBufferTest2.cc deleted file mode 100644 index 2b648c940..000000000 --- a/deps/winpty/misc/ScreenBufferTest2.cc +++ /dev/null @@ -1,151 +0,0 @@ -#include - -#include "TestUtil.cc" - -const char *g_prefix = ""; - -static void dumpHandles() { - trace("%sSTDIN=0x%I64x STDOUT=0x%I64x STDERR=0x%I64x", - g_prefix, - (long long)GetStdHandle(STD_INPUT_HANDLE), - (long long)GetStdHandle(STD_OUTPUT_HANDLE), - (long long)GetStdHandle(STD_ERROR_HANDLE)); -} - -static HANDLE createBuffer() { - - // If sa isn't provided, the handle defaults to not-inheritable. - SECURITY_ATTRIBUTES sa = {0}; - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - - trace("%sCreating a new buffer...", g_prefix); - HANDLE conout = CreateConsoleScreenBuffer( - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - CONSOLE_TEXTMODE_BUFFER, NULL); - - trace("%sCreating a new buffer... 0x%I64x", g_prefix, (long long)conout); - return conout; -} - -static const char *successOrFail(BOOL ret) { - return ret ? "ok" : "FAILED"; -} - -static void setConsoleActiveScreenBuffer(HANDLE conout) { - trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called...", - g_prefix, (long long)conout); - trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called... %s", - g_prefix, (long long)conout, - successOrFail(SetConsoleActiveScreenBuffer(conout))); -} - -static void writeTest(HANDLE conout, const char *msg) { - char writeData[256]; - sprintf(writeData, "%s%s\n", g_prefix, msg); - - trace("%sWriting to 0x%I64x: '%s'...", - g_prefix, (long long)conout, msg); - DWORD actual = 0; - BOOL ret = WriteConsoleA(conout, writeData, strlen(writeData), &actual, NULL); - trace("%sWriting to 0x%I64x: '%s'... %s", - g_prefix, (long long)conout, msg, - successOrFail(ret && actual == strlen(writeData))); -} - -static HANDLE startChildInSameConsole(const wchar_t *args, BOOL - bInheritHandles=FALSE) { - wchar_t program[1024]; - wchar_t cmdline[1024]; - GetModuleFileNameW(NULL, program, 1024); - swprintf(cmdline, L"\"%ls\" %ls", program, args); - - STARTUPINFOW sui; - PROCESS_INFORMATION pi; - memset(&sui, 0, sizeof(sui)); - memset(&pi, 0, sizeof(pi)); - sui.cb = sizeof(sui); - - CreateProcessW(program, cmdline, - NULL, NULL, - /*bInheritHandles=*/bInheritHandles, - /*dwCreationFlags=*/0, - NULL, NULL, - &sui, &pi); - - return pi.hProcess; -} - -static HANDLE dup(HANDLE h, HANDLE targetProcess) { - HANDLE h2 = INVALID_HANDLE_VALUE; - BOOL ret = DuplicateHandle( - GetCurrentProcess(), h, - targetProcess, &h2, - 0, TRUE, DUPLICATE_SAME_ACCESS); - trace("dup(0x%I64x) to process 0x%I64x... %s, 0x%I64x", - (long long)h, - (long long)targetProcess, - successOrFail(ret), - (long long)h2); - return h2; -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"parent"); - return 0; - } - - if (!strcmp(argv[1], "parent")) { - g_prefix = "parent: "; - dumpHandles(); - HANDLE hChild = startChildInSameConsole(L"child"); - - // Windows 10. - HANDLE orig1 = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE new1 = createBuffer(); - - Sleep(2000); - setConsoleActiveScreenBuffer(new1); - - // Handle duplication results to child process in same console: - // - Windows XP: fails - // - Windows 7 Ultimate SP1 32-bit: fails - // - Windows Server 2008 R2 Datacenter SP1 64-bit: fails - // - Windows 8 Enterprise 32-bit: succeeds - // - Windows 10: succeeds - HANDLE orig2 = dup(orig1, GetCurrentProcess()); - HANDLE new2 = dup(new1, GetCurrentProcess()); - - dup(orig1, hChild); - dup(new1, hChild); - - // The writes to orig1/orig2 are invisible. The writes to new1/new2 - // are visible. - writeTest(orig1, "write to orig1"); - writeTest(orig2, "write to orig2"); - writeTest(new1, "write to new1"); - writeTest(new2, "write to new2"); - - Sleep(120000); - return 0; - } - - if (!strcmp(argv[1], "child")) { - g_prefix = "child: "; - dumpHandles(); - Sleep(4000); - for (unsigned int i = 0x1; i <= 0xB0; ++i) { - char msg[256]; - sprintf(msg, "Write to handle 0x%x", i); - HANDLE h = reinterpret_cast(i); - writeTest(h, msg); - } - Sleep(120000); - return 0; - } - - return 0; -} diff --git a/deps/winpty/misc/SelectAllTest.cc b/deps/winpty/misc/SelectAllTest.cc deleted file mode 100644 index a6c27739d..000000000 --- a/deps/winpty/misc/SelectAllTest.cc +++ /dev/null @@ -1,45 +0,0 @@ -#define _WIN32_WINNT 0x0501 -#include -#include - -#include "../src/shared/DebugClient.cc" - -const int SC_CONSOLE_MARK = 0xFFF2; -const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - -CALLBACK DWORD pausingThread(LPVOID dummy) -{ - HWND hwnd = GetConsoleWindow(); - while (true) { - SendMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_SELECT_ALL, 0); - Sleep(1000); - SendMessage(hwnd, WM_CHAR, 27, 0x00010001); - Sleep(1000); - } -} - -int main() -{ - HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO info; - - GetConsoleScreenBufferInfo(out, &info); - COORD initial = info.dwCursorPosition; - - CreateThread(NULL, 0, - pausingThread, NULL, - 0, NULL); - - for (int i = 0; i < 30; ++i) { - Sleep(100); - GetConsoleScreenBufferInfo(out, &info); - if (memcmp(&info.dwCursorPosition, &initial, sizeof(COORD)) != 0) { - trace("cursor moved to [%d,%d]", - info.dwCursorPosition.X, - info.dwCursorPosition.Y); - } else { - trace("cursor in expected position"); - } - } - return 0; -} diff --git a/deps/winpty/misc/SetBufferSize.cc b/deps/winpty/misc/SetBufferSize.cc deleted file mode 100644 index b50a1f8dc..000000000 --- a/deps/winpty/misc/SetBufferSize.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc != 3) { - printf("Usage: %s x y width height\n", argv[0]); - return 1; - } - - const HANDLE conout = CreateFileW(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - ASSERT(conout != INVALID_HANDLE_VALUE); - - COORD size = { - (short)atoi(argv[1]), - (short)atoi(argv[2]), - }; - - BOOL ret = SetConsoleScreenBufferSize(conout, size); - const unsigned lastError = GetLastError(); - const char *const retStr = ret ? "OK" : "failed"; - trace("SetConsoleScreenBufferSize ret: %s (LastError=0x%x)", retStr, lastError); - printf("SetConsoleScreenBufferSize ret: %s (LastError=0x%x)\n", retStr, lastError); - - return 0; -} diff --git a/deps/winpty/misc/SetCursorPos.cc b/deps/winpty/misc/SetCursorPos.cc deleted file mode 100644 index d20fdbdfc..000000000 --- a/deps/winpty/misc/SetCursorPos.cc +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - int col = atoi(argv[1]); - int row = atoi(argv[2]); - setCursorPos(col, row); - return 0; -} diff --git a/deps/winpty/misc/SetFont.cc b/deps/winpty/misc/SetFont.cc deleted file mode 100644 index 9bcd4b4cc..000000000 --- a/deps/winpty/misc/SetFont.cc +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include - -#include "TestUtil.cc" - -#define COUNT_OF(array) (sizeof(array) / sizeof((array)[0])) - -// See https://en.wikipedia.org/wiki/List_of_CJK_fonts -const wchar_t kMSGothic[] = { 0xff2d, 0xff33, 0x0020, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 }; // Japanese -const wchar_t kNSimSun[] = { 0x65b0, 0x5b8b, 0x4f53, 0 }; // Simplified Chinese -const wchar_t kMingLight[] = { 0x7d30, 0x660e, 0x9ad4, 0 }; // Traditional Chinese -const wchar_t kGulimChe[] = { 0xad74, 0xb9bc, 0xccb4, 0 }; // Korean - -int main() { - setlocale(LC_ALL, ""); - wchar_t *cmdline = GetCommandLineW(); - int argc = 0; - wchar_t **argv = CommandLineToArgvW(cmdline, &argc); - const HANDLE conout = openConout(); - - if (argc == 1) { - cprintf(L"Usage:\n"); - cprintf(L" SetFont \n"); - cprintf(L" SetFont options\n"); - cprintf(L"\n"); - cprintf(L"Options for SetCurrentConsoleFontEx:\n"); - cprintf(L" -idx INDEX\n"); - cprintf(L" -w WIDTH\n"); - cprintf(L" -h HEIGHT\n"); - cprintf(L" -family (0xNN|NN)\n"); - cprintf(L" -weight (normal|bold|NNN)\n"); - cprintf(L" -face FACENAME\n"); - cprintf(L" -face-{gothic|simsun|minglight|gulimche) [JP,CN-sim,CN-tra,KR]\n"); - cprintf(L" -tt\n"); - cprintf(L" -vec\n"); - cprintf(L" -vp\n"); - cprintf(L" -dev\n"); - cprintf(L" -roman\n"); - cprintf(L" -swiss\n"); - cprintf(L" -modern\n"); - cprintf(L" -script\n"); - cprintf(L" -decorative\n"); - return 0; - } - - if (isdigit(argv[1][0])) { - int index = _wtoi(argv[1]); - HMODULE kernel32 = LoadLibraryW(L"kernel32.dll"); - FARPROC proc = GetProcAddress(kernel32, "SetConsoleFont"); - if (proc == NULL) { - cprintf(L"Couldn't get address of SetConsoleFont\n"); - } else { - BOOL ret = reinterpret_cast(proc)( - conout, index); - cprintf(L"SetFont returned %d\n", ret); - } - return 0; - } - - CONSOLE_FONT_INFOEX fontex = {0}; - fontex.cbSize = sizeof(fontex); - - for (int i = 1; i < argc; ++i) { - std::wstring arg = argv[i]; - if (i + 1 < argc) { - std::wstring next = argv[i + 1]; - if (arg == L"-idx") { - fontex.nFont = _wtoi(next.c_str()); - ++i; continue; - } else if (arg == L"-w") { - fontex.dwFontSize.X = _wtoi(next.c_str()); - ++i; continue; - } else if (arg == L"-h") { - fontex.dwFontSize.Y = _wtoi(next.c_str()); - ++i; continue; - } else if (arg == L"-weight") { - if (next == L"normal") { - fontex.FontWeight = 400; - } else if (next == L"bold") { - fontex.FontWeight = 700; - } else { - fontex.FontWeight = _wtoi(next.c_str()); - } - ++i; continue; - } else if (arg == L"-face") { - wcsncpy(fontex.FaceName, next.c_str(), COUNT_OF(fontex.FaceName)); - ++i; continue; - } else if (arg == L"-family") { - fontex.FontFamily = strtol(narrowString(next).c_str(), nullptr, 0); - ++i; continue; - } - } - if (arg == L"-tt") { - fontex.FontFamily |= TMPF_TRUETYPE; - } else if (arg == L"-vec") { - fontex.FontFamily |= TMPF_VECTOR; - } else if (arg == L"-vp") { - // Setting the TMPF_FIXED_PITCH bit actually indicates variable - // pitch. - fontex.FontFamily |= TMPF_FIXED_PITCH; - } else if (arg == L"-dev") { - fontex.FontFamily |= TMPF_DEVICE; - } else if (arg == L"-roman") { - fontex.FontFamily = (fontex.FontFamily & ~0xF0) | FF_ROMAN; - } else if (arg == L"-swiss") { - fontex.FontFamily = (fontex.FontFamily & ~0xF0) | FF_SWISS; - } else if (arg == L"-modern") { - fontex.FontFamily = (fontex.FontFamily & ~0xF0) | FF_MODERN; - } else if (arg == L"-script") { - fontex.FontFamily = (fontex.FontFamily & ~0xF0) | FF_SCRIPT; - } else if (arg == L"-decorative") { - fontex.FontFamily = (fontex.FontFamily & ~0xF0) | FF_DECORATIVE; - } else if (arg == L"-face-gothic") { - wcsncpy(fontex.FaceName, kMSGothic, COUNT_OF(fontex.FaceName)); - } else if (arg == L"-face-simsun") { - wcsncpy(fontex.FaceName, kNSimSun, COUNT_OF(fontex.FaceName)); - } else if (arg == L"-face-minglight") { - wcsncpy(fontex.FaceName, kMingLight, COUNT_OF(fontex.FaceName)); - } else if (arg == L"-face-gulimche") { - wcsncpy(fontex.FaceName, kGulimChe, COUNT_OF(fontex.FaceName)); - } else { - cprintf(L"Unrecognized argument: %ls\n", arg.c_str()); - exit(1); - } - } - - cprintf(L"Setting to: nFont=%u dwFontSize=(%d,%d) " - L"FontFamily=0x%x FontWeight=%u " - L"FaceName=\"%ls\"\n", - static_cast(fontex.nFont), - fontex.dwFontSize.X, fontex.dwFontSize.Y, - fontex.FontFamily, fontex.FontWeight, - fontex.FaceName); - - BOOL ret = SetCurrentConsoleFontEx( - conout, - FALSE, - &fontex); - cprintf(L"SetCurrentConsoleFontEx returned %d\n", ret); - - return 0; -} diff --git a/deps/winpty/misc/SetWindowRect.cc b/deps/winpty/misc/SetWindowRect.cc deleted file mode 100644 index 6291dd674..000000000 --- a/deps/winpty/misc/SetWindowRect.cc +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc != 5) { - printf("Usage: %s x y width height\n", argv[0]); - return 1; - } - - const HANDLE conout = CreateFileW(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - ASSERT(conout != INVALID_HANDLE_VALUE); - - SMALL_RECT sr = { - (short)atoi(argv[1]), - (short)atoi(argv[2]), - (short)(atoi(argv[1]) + atoi(argv[3]) - 1), - (short)(atoi(argv[2]) + atoi(argv[4]) - 1), - }; - - trace("Calling SetConsoleWindowInfo with {L=%d,T=%d,R=%d,B=%d}", - sr.Left, sr.Top, sr.Right, sr.Bottom); - BOOL ret = SetConsoleWindowInfo(conout, TRUE, &sr); - const unsigned lastError = GetLastError(); - const char *const retStr = ret ? "OK" : "failed"; - trace("SetConsoleWindowInfo ret: %s (LastError=0x%x)", retStr, lastError); - printf("SetConsoleWindowInfo ret: %s (LastError=0x%x)\n", retStr, lastError); - - return 0; -} diff --git a/deps/winpty/misc/ShowArgv.cc b/deps/winpty/misc/ShowArgv.cc deleted file mode 100644 index 29a0f0913..000000000 --- a/deps/winpty/misc/ShowArgv.cc +++ /dev/null @@ -1,12 +0,0 @@ -// This test program is useful for studying commandline<->argv conversion. - -#include -#include - -int main(int argc, char **argv) -{ - printf("cmdline = [%s]\n", GetCommandLine()); - for (int i = 0; i < argc; ++i) - printf("[%s]\n", argv[i]); - return 0; -} diff --git a/deps/winpty/misc/ShowConsoleInput.cc b/deps/winpty/misc/ShowConsoleInput.cc deleted file mode 100644 index 75fbfb81f..000000000 --- a/deps/winpty/misc/ShowConsoleInput.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include - -int main(int argc, char *argv[]) -{ - static int escCount = 0; - - HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); - while (true) { - DWORD count; - INPUT_RECORD ir; - if (!ReadConsoleInput(hStdin, &ir, 1, &count)) { - printf("ReadConsoleInput failed\n"); - return 1; - } - - if (true) { - DWORD mode; - GetConsoleMode(hStdin, &mode); - SetConsoleMode(hStdin, mode & ~ENABLE_PROCESSED_INPUT); - } - - if (ir.EventType == KEY_EVENT) { - const KEY_EVENT_RECORD &ker = ir.Event.KeyEvent; - printf("%s", ker.bKeyDown ? "dn" : "up"); - printf(" ch="); - if (isprint(ker.uChar.AsciiChar)) - printf("'%c'", ker.uChar.AsciiChar); - printf("%d", ker.uChar.AsciiChar); - printf(" vk=%#x", ker.wVirtualKeyCode); - printf(" scan=%#x", ker.wVirtualScanCode); - printf(" state=%#x", (int)ker.dwControlKeyState); - printf(" repeat=%d", ker.wRepeatCount); - printf("\n"); - if (ker.uChar.AsciiChar == 27 && ++escCount == 6) - break; - } - } -} diff --git a/deps/winpty/misc/Spew.py b/deps/winpty/misc/Spew.py deleted file mode 100644 index 9d1796af3..000000000 --- a/deps/winpty/misc/Spew.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -i = 0; -while True: - i += 1 - print(i) diff --git a/deps/winpty/misc/TestUtil.cc b/deps/winpty/misc/TestUtil.cc deleted file mode 100644 index c832a12b8..000000000 --- a/deps/winpty/misc/TestUtil.cc +++ /dev/null @@ -1,172 +0,0 @@ -// This file is included into test programs using #include - -#include -#include -#include -#include -#include -#include -#include - -#include "../src/shared/DebugClient.h" -#include "../src/shared/TimeMeasurement.h" - -#include "../src/shared/DebugClient.cc" -#include "../src/shared/WinptyAssert.cc" -#include "../src/shared/WinptyException.cc" - -// Launch this test program again, in a new console that we will destroy. -static void startChildProcess(const wchar_t *args) { - wchar_t program[1024]; - wchar_t cmdline[1024]; - GetModuleFileNameW(NULL, program, 1024); - swprintf(cmdline, L"\"%ls\" %ls", program, args); - - STARTUPINFOW sui; - PROCESS_INFORMATION pi; - memset(&sui, 0, sizeof(sui)); - memset(&pi, 0, sizeof(pi)); - sui.cb = sizeof(sui); - - CreateProcessW(program, cmdline, - NULL, NULL, - /*bInheritHandles=*/FALSE, - /*dwCreationFlags=*/CREATE_NEW_CONSOLE, - NULL, NULL, - &sui, &pi); -} - -static void setBufferSize(HANDLE conout, int x, int y) { - COORD size = { static_cast(x), static_cast(y) }; - BOOL success = SetConsoleScreenBufferSize(conout, size); - trace("setBufferSize: (%d,%d), result=%d", x, y, success); -} - -static void setWindowPos(HANDLE conout, int x, int y, int w, int h) { - SMALL_RECT r = { - static_cast(x), static_cast(y), - static_cast(x + w - 1), - static_cast(y + h - 1) - }; - BOOL success = SetConsoleWindowInfo(conout, /*bAbsolute=*/TRUE, &r); - trace("setWindowPos: (%d,%d,%d,%d), result=%d", x, y, w, h, success); -} - -static void setCursorPos(HANDLE conout, int x, int y) { - COORD coord = { static_cast(x), static_cast(y) }; - SetConsoleCursorPosition(conout, coord); -} - -static void setBufferSize(int x, int y) { - setBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), x, y); -} - -static void setWindowPos(int x, int y, int w, int h) { - setWindowPos(GetStdHandle(STD_OUTPUT_HANDLE), x, y, w, h); -} - -static void setCursorPos(int x, int y) { - setCursorPos(GetStdHandle(STD_OUTPUT_HANDLE), x, y); -} - -static void countDown(int sec) { - for (int i = sec; i > 0; --i) { - printf("%d.. ", i); - fflush(stdout); - Sleep(1000); - } - printf("\n"); -} - -static void writeBox(int x, int y, int w, int h, char ch, int attributes=7) { - CHAR_INFO info = { 0 }; - info.Char.AsciiChar = ch; - info.Attributes = attributes; - std::vector buf(w * h, info); - HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - COORD bufSize = { static_cast(w), static_cast(h) }; - COORD bufCoord = { 0, 0 }; - SMALL_RECT writeRegion = { - static_cast(x), - static_cast(y), - static_cast(x + w - 1), - static_cast(y + h - 1) - }; - WriteConsoleOutputA(conout, buf.data(), bufSize, bufCoord, &writeRegion); -} - -static void setChar(int x, int y, char ch, int attributes=7) { - writeBox(x, y, 1, 1, ch, attributes); -} - -static void fillChar(int x, int y, int repeat, char ch) { - COORD coord = { static_cast(x), static_cast(y) }; - DWORD actual = 0; - FillConsoleOutputCharacterA( - GetStdHandle(STD_OUTPUT_HANDLE), - ch, repeat, coord, &actual); -} - -static void repeatChar(int count, char ch) { - for (int i = 0; i < count; ++i) { - putchar(ch); - } - fflush(stdout); -} - -// I don't know why, but wprintf fails to print this face name, -// "MS ゴシック" (aka MS Gothic). It helps to use wprintf instead of printf, and -// it helps to call `setlocale(LC_ALL, "")`, but the Japanese symbols are -// ultimately converted to `?` symbols, even though MS Gothic is able to -// display its own name, and the current code page is 932 (Shift-JIS). -static void cvfprintf(HANDLE conout, const wchar_t *fmt, va_list ap) { - wchar_t buffer[256]; - vswprintf(buffer, 256 - 1, fmt, ap); - buffer[255] = L'\0'; - DWORD actual = 0; - if (!WriteConsoleW(conout, buffer, wcslen(buffer), &actual, NULL)) { - wprintf(L"WriteConsoleW call failed!\n"); - } -} - -static void cfprintf(HANDLE conout, const wchar_t *fmt, ...) { - va_list ap; - va_start(ap, fmt); - cvfprintf(conout, fmt, ap); - va_end(ap); -} - -static void cprintf(const wchar_t *fmt, ...) { - va_list ap; - va_start(ap, fmt); - cvfprintf(GetStdHandle(STD_OUTPUT_HANDLE), fmt, ap); - va_end(ap); -} - -static std::string narrowString(const std::wstring &input) -{ - int mblen = WideCharToMultiByte( - CP_UTF8, 0, - input.data(), input.size(), - NULL, 0, NULL, NULL); - if (mblen <= 0) { - return std::string(); - } - std::vector tmp(mblen); - int mblen2 = WideCharToMultiByte( - CP_UTF8, 0, - input.data(), input.size(), - tmp.data(), tmp.size(), - NULL, NULL); - assert(mblen2 == mblen); - return std::string(tmp.data(), tmp.size()); -} - -HANDLE openConout() { - const HANDLE conout = CreateFileW(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - ASSERT(conout != INVALID_HANDLE_VALUE); - return conout; -} diff --git a/deps/winpty/misc/UnicodeDoubleWidthTest.cc b/deps/winpty/misc/UnicodeDoubleWidthTest.cc deleted file mode 100644 index 7210d4103..000000000 --- a/deps/winpty/misc/UnicodeDoubleWidthTest.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Demonstrates how U+30FC is sometimes handled as a single-width character -// when it should be handled as a double-width character. -// -// It only runs on computers where 932 is a valid code page. Set the system -// local to "Japanese (Japan)" to ensure this. -// -// The problem seems to happen when U+30FC is printed in a console using the -// Lucida Console font, and only when that font is at certain sizes. -// - -#include -#include -#include -#include -#include -#include - -#include "TestUtil.cc" - -#define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) - -static void setFont(const wchar_t *faceName, int pxSize) { - CONSOLE_FONT_INFOEX infoex = {0}; - infoex.cbSize = sizeof(infoex); - infoex.dwFontSize.Y = pxSize; - wcsncpy(infoex.FaceName, faceName, COUNT_OF(infoex.FaceName)); - BOOL ret = SetCurrentConsoleFontEx( - GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &infoex); - assert(ret); -} - -static bool performTest(const wchar_t testChar) { - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - SetConsoleTextAttribute(conout, 7); - - system("cls"); - DWORD actual = 0; - BOOL ret = WriteConsoleW(conout, &testChar, 1, &actual, NULL); - assert(ret && actual == 1); - - CHAR_INFO verify[2]; - COORD bufSize = {2, 1}; - COORD bufCoord = {0, 0}; - const SMALL_RECT readRegion = {0, 0, 1, 0}; - SMALL_RECT actualRegion = readRegion; - ret = ReadConsoleOutputW(conout, verify, bufSize, bufCoord, &actualRegion); - assert(ret && !memcmp(&readRegion, &actualRegion, sizeof(readRegion))); - assert(verify[0].Char.UnicodeChar == testChar); - - if (verify[1].Char.UnicodeChar == testChar) { - // Typical double-width behavior with a TrueType font. Pass. - assert(verify[0].Attributes == 0x107); - assert(verify[1].Attributes == 0x207); - return true; - } else if (verify[1].Char.UnicodeChar == 0) { - // Typical double-width behavior with a Raster Font. Pass. - assert(verify[0].Attributes == 7); - assert(verify[1].Attributes == 0); - return true; - } else if (verify[1].Char.UnicodeChar == L' ') { - // Single-width behavior. Fail. - assert(verify[0].Attributes == 7); - assert(verify[1].Attributes == 7); - return false; - } else { - // Unexpected output. - assert(false); - } -} - -int main(int argc, char *argv[]) { - setlocale(LC_ALL, ""); - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - assert(SetConsoleCP(932)); - assert(SetConsoleOutputCP(932)); - - const wchar_t testChar = 0x30FC; - const wchar_t *const faceNames[] = { - L"Lucida Console", - L"Consolas", - L"MS ゴシック", - }; - - trace("Test started"); - - for (auto faceName : faceNames) { - for (int px = 1; px <= 50; ++px) { - setFont(faceName, px); - if (!performTest(testChar)) { - trace("FAILURE: %s %dpx", narrowString(faceName).c_str(), px); - } - } - } - - trace("Test complete"); - return 0; -} diff --git a/deps/winpty/misc/UnicodeWideTest1.cc b/deps/winpty/misc/UnicodeWideTest1.cc deleted file mode 100644 index a8d798e70..000000000 --- a/deps/winpty/misc/UnicodeWideTest1.cc +++ /dev/null @@ -1,246 +0,0 @@ -#include - -#include -#include - -#include "TestUtil.cc" - -#define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) - - -CHAR_INFO ci(wchar_t ch, WORD attributes) { - CHAR_INFO ret; - ret.Char.UnicodeChar = ch; - ret.Attributes = attributes; - return ret; -} - -CHAR_INFO ci(wchar_t ch) { - return ci(ch, 7); -} - -CHAR_INFO ci() { - return ci(L' '); -} - -bool operator==(SMALL_RECT x, SMALL_RECT y) { - return !memcmp(&x, &y, sizeof(x)); -} - -SMALL_RECT sr(COORD pt, COORD size) { - return { - pt.X, pt.Y, - static_cast(pt.X + size.X - 1), - static_cast(pt.Y + size.Y - 1) - }; -} - -static void set( - const COORD pt, - const COORD size, - const std::vector &data) { - assert(data.size() == size.X * size.Y); - SMALL_RECT writeRegion = sr(pt, size); - BOOL ret = WriteConsoleOutputW( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), size, {0, 0}, &writeRegion); - assert(ret && writeRegion == sr(pt, size)); -} - -static void set( - const COORD pt, - const std::vector &data) { - set(pt, {static_cast(data.size()), 1}, data); -} - -static void writeAttrsAt( - const COORD pt, - const std::vector &data) { - DWORD actual = 0; - BOOL ret = WriteConsoleOutputAttribute( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), data.size(), pt, &actual); - assert(ret && actual == data.size()); -} - -static void writeCharsAt( - const COORD pt, - const std::vector &data) { - DWORD actual = 0; - BOOL ret = WriteConsoleOutputCharacterW( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), data.size(), pt, &actual); - assert(ret && actual == data.size()); -} - -static void writeChars( - const std::vector &data) { - DWORD actual = 0; - BOOL ret = WriteConsoleW( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), data.size(), &actual, NULL); - assert(ret && actual == data.size()); -} - -std::vector get( - const COORD pt, - const COORD size) { - std::vector data(size.X * size.Y); - SMALL_RECT readRegion = sr(pt, size); - BOOL ret = ReadConsoleOutputW( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), size, {0, 0}, &readRegion); - assert(ret && readRegion == sr(pt, size)); - return data; -} - -std::vector readCharsAt( - const COORD pt, - int size) { - std::vector data(size); - DWORD actual = 0; - BOOL ret = ReadConsoleOutputCharacterW( - GetStdHandle(STD_OUTPUT_HANDLE), - data.data(), data.size(), pt, &actual); - assert(ret); - data.resize(actual); // With double-width chars, we can read fewer than `size`. - return data; -} - -static void dump(const COORD pt, const COORD size) { - for (CHAR_INFO ci : get(pt, size)) { - printf("%04X %04X\n", ci.Char.UnicodeChar, ci.Attributes); - } -} - -static void dumpCharsAt(const COORD pt, int size) { - for (wchar_t ch : readCharsAt(pt, size)) { - printf("%04X\n", ch); - } -} - -static COORD getCursorPos() { - CONSOLE_SCREEN_BUFFER_INFO info = { sizeof(info) }; - assert(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info)); - return info.dwCursorPosition; -} - -static void test1() { - // We write "䀀䀀", then write "䀁" in the middle of the two. The second - // write turns the first and last cells into spaces. The LEADING/TRAILING - // flags retain consistency. - printf("test1 - overlap full-width char with full-width char\n"); - writeCharsAt({1,0}, {0x4000, 0x4000}); - dump({0,0}, {6,1}); - printf("\n"); - writeCharsAt({2,0}, {0x4001}); - dump({0,0}, {6,1}); - printf("\n"); -} - -static void test2() { - // Like `test1`, but use a lower-level API to do the write. Consistency is - // preserved here too -- the first and last cells are replaced with spaces. - printf("test2 - overlap full-width char with full-width char (lowlevel)\n"); - writeCharsAt({1,0}, {0x4000, 0x4000}); - dump({0,0}, {6,1}); - printf("\n"); - set({2,0}, {ci(0x4001,0x107), ci(0x4001,0x207)}); - dump({0,0}, {6,1}); - printf("\n"); -} - -static void test3() { - // However, the lower-level API can break the LEADING/TRAILING invariant - // explicitly: - printf("test3 - explicitly violate LEADING/TRAILING using lowlevel API\n"); - set({1,0}, { - ci(0x4000, 0x207), - ci(0x4001, 0x107), - ci(0x3044, 7), - ci(L'X', 0x107), - ci(L'X', 0x207), - }); - dump({0,0}, {7,1}); -} - -static void test4() { - // It is possible for the two cells of a double-width character to have two - // colors. - printf("test4 - use lowlevel to assign two colors to one full-width char\n"); - set({0,0}, { - ci(0x4000, 0x142), - ci(0x4000, 0x224), - }); - dump({0,0}, {2,1}); -} - -static void test5() { - // WriteConsoleOutputAttribute doesn't seem to affect the LEADING/TRAILING - // flags. - printf("test5 - WriteConsoleOutputAttribute cannot affect LEADING/TRAILING\n"); - - // Trying to clear the flags doesn't work... - writeCharsAt({0,0}, {0x4000}); - dump({0,0}, {2,1}); - writeAttrsAt({0,0}, {0x42, 0x24}); - printf("\n"); - dump({0,0}, {2,1}); - - // ... and trying to add them also doesn't work. - writeCharsAt({0,1}, {'A', ' '}); - writeAttrsAt({0,1}, {0x107, 0x207}); - printf("\n"); - dump({0,1}, {2,1}); -} - -static void test6() { - // The cursor position may be on either cell of a double-width character. - // Visually, the cursor appears under both cells, regardless of which - // specific one has the cursor. - printf("test6 - cursor can be either left or right cell of full-width char\n"); - - writeCharsAt({2,1}, {0x4000}); - - setCursorPos(2, 1); - auto pos1 = getCursorPos(); - Sleep(1000); - - setCursorPos(3, 1); - auto pos2 = getCursorPos(); - Sleep(1000); - - setCursorPos(0, 15); - printf("%d,%d\n", pos1.X, pos1.Y); - printf("%d,%d\n", pos2.X, pos2.Y); -} - -static void runTest(void (&test)()) { - system("cls"); - setCursorPos(0, 14); - test(); - system("pause"); -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - setWindowPos(0, 0, 1, 1); - setBufferSize(80, 40); - setWindowPos(0, 0, 80, 40); - - auto cp = GetConsoleOutputCP(); - assert(cp == 932 || cp == 936 || cp == 949 || cp == 950); - - runTest(test1); - runTest(test2); - runTest(test3); - runTest(test4); - runTest(test5); - runTest(test6); - - return 0; -} diff --git a/deps/winpty/misc/UnicodeWideTest2.cc b/deps/winpty/misc/UnicodeWideTest2.cc deleted file mode 100644 index 05f80f70b..000000000 --- a/deps/winpty/misc/UnicodeWideTest2.cc +++ /dev/null @@ -1,130 +0,0 @@ -// -// Test half-width vs full-width characters. -// - -#include -#include -#include -#include - -#include "TestUtil.cc" - -static void writeChars(const wchar_t *text) { - wcslen(text); - const int len = wcslen(text); - DWORD actual = 0; - BOOL ret = WriteConsoleW( - GetStdHandle(STD_OUTPUT_HANDLE), - text, len, &actual, NULL); - trace("writeChars: ret=%d, actual=%lld", ret, (long long)actual); -} - -static void dumpChars(int x, int y, int w, int h) { - BOOL ret; - const COORD bufSize = {w, h}; - const COORD bufCoord = {0, 0}; - const SMALL_RECT topLeft = {x, y, x + w - 1, y + h - 1}; - CHAR_INFO mbcsData[w * h]; - CHAR_INFO unicodeData[w * h]; - SMALL_RECT readRegion; - readRegion = topLeft; - ret = ReadConsoleOutputW(GetStdHandle(STD_OUTPUT_HANDLE), unicodeData, - bufSize, bufCoord, &readRegion); - assert(ret); - readRegion = topLeft; - ret = ReadConsoleOutputA(GetStdHandle(STD_OUTPUT_HANDLE), mbcsData, - bufSize, bufCoord, &readRegion); - assert(ret); - - printf("\n"); - for (int i = 0; i < w * h; ++i) { - printf("(%02d,%02d) CHAR: %04x %4x -- %02x %4x\n", - x + i % w, y + i / w, - (unsigned short)unicodeData[i].Char.UnicodeChar, - (unsigned short)unicodeData[i].Attributes, - (unsigned char)mbcsData[i].Char.AsciiChar, - (unsigned short)mbcsData[i].Attributes); - } -} - -int main(int argc, char *argv[]) { - system("cls"); - setWindowPos(0, 0, 1, 1); - setBufferSize(80, 38); - setWindowPos(0, 0, 80, 38); - - // Write text. - const wchar_t text1[] = { - 0x3044, // U+3044 (HIRAGANA LETTER I) - 0x2014, // U+2014 (EM DASH) - 0x3044, // U+3044 (HIRAGANA LETTER I) - 0xFF2D, // U+FF2D (FULLWIDTH LATIN CAPITAL LETTER M) - 0x30FC, // U+30FC (KATAKANA-HIRAGANA PROLONGED SOUND MARK) - 0x0031, // U+3031 (DIGIT ONE) - 0x2014, // U+2014 (EM DASH) - 0x0032, // U+0032 (DIGIT TWO) - 0x005C, // U+005C (REVERSE SOLIDUS) - 0x3044, // U+3044 (HIRAGANA LETTER I) - 0 - }; - setCursorPos(0, 0); - writeChars(text1); - - setCursorPos(78, 1); - writeChars(L"<>"); - - const wchar_t text2[] = { - 0x0032, // U+3032 (DIGIT TWO) - 0x3044, // U+3044 (HIRAGANA LETTER I) - 0, - }; - setCursorPos(78, 1); - writeChars(text2); - - system("pause"); - - dumpChars(0, 0, 17, 1); - dumpChars(2, 0, 2, 1); - dumpChars(2, 0, 1, 1); - dumpChars(3, 0, 1, 1); - dumpChars(78, 1, 2, 1); - dumpChars(0, 2, 2, 1); - - system("pause"); - system("cls"); - - const wchar_t text3[] = { - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 1 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 2 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 3 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 4 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 5 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 6 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 7 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 8 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 9 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 10 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 11 - 0x30FC, 0x30FC, 0x30FC, 0xFF2D, // 12 - L'\r', '\n', - L'\r', '\n', - 0 - }; - writeChars(text3); - system("pause"); - { - const COORD bufSize = {80, 2}; - const COORD bufCoord = {0, 0}; - SMALL_RECT readRegion = {0, 0, 79, 1}; - CHAR_INFO unicodeData[160]; - BOOL ret = ReadConsoleOutputW(GetStdHandle(STD_OUTPUT_HANDLE), unicodeData, - bufSize, bufCoord, &readRegion); - assert(ret); - for (int i = 0; i < 96; ++i) { - printf("%04x ", unicodeData[i].Char.UnicodeChar); - } - printf("\n"); - } - - return 0; -} diff --git a/deps/winpty/misc/UnixEcho.cc b/deps/winpty/misc/UnixEcho.cc deleted file mode 100644 index 372e04515..000000000 --- a/deps/winpty/misc/UnixEcho.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Unix test code that puts the terminal into raw mode, then echos typed - * characters to stdout. Derived from sample code in the Stevens book, posted - * online at http://www.lafn.org/~dave/linux/terminalIO.html. - */ - -#include -#include -#include -#include -#include "FormatChar.h" - -static struct termios save_termios; -static int term_saved; - -/* RAW! mode */ -int tty_raw(int fd) -{ - struct termios buf; - - if (tcgetattr(fd, &save_termios) < 0) /* get the original state */ - return -1; - - buf = save_termios; - - /* echo off, canonical mode off, extended input - processing off, signal chars off */ - buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - - /* no SIGINT on BREAK, CR-to-NL off, input parity - check off, don't strip the 8th bit on input, - ouput flow control off */ - buf.c_iflag &= ~(BRKINT | ICRNL | ISTRIP | IXON); - - /* clear size bits, parity checking off */ - buf.c_cflag &= ~(CSIZE | PARENB); - - /* set 8 bits/char */ - buf.c_cflag |= CS8; - - /* output processing off */ - buf.c_oflag &= ~(OPOST); - - buf.c_cc[VMIN] = 1; /* 1 byte at a time */ - buf.c_cc[VTIME] = 0; /* no timer on input */ - - if (tcsetattr(fd, TCSAFLUSH, &buf) < 0) - return -1; - - term_saved = 1; - - return 0; -} - - -/* set it to normal! */ -int tty_reset(int fd) -{ - if (term_saved) - if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0) - return -1; - - return 0; -} - - -int main() -{ - tty_raw(0); - - int count = 0; - while (true) { - char ch; - char buf[16]; - int actual = read(0, &ch, 1); - if (actual != 1) { - perror("read error"); - break; - } - formatChar(buf, ch); - fputs(buf, stdout); - fflush(stdout); - if (ch == 3) // Ctrl-C - break; - } - - tty_reset(0); - return 0; -} diff --git a/deps/winpty/misc/Utf16Echo.cc b/deps/winpty/misc/Utf16Echo.cc deleted file mode 100644 index ef5f302de..000000000 --- a/deps/winpty/misc/Utf16Echo.cc +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -int main(int argc, char *argv[]) { - system("cls"); - - if (argc == 1) { - printf("Usage: %s hhhh\n", argv[0]); - return 0; - } - - std::wstring dataToWrite; - for (int i = 1; i < argc; ++i) { - wchar_t ch = strtol(argv[i], NULL, 16); - dataToWrite.push_back(ch); - } - - DWORD actual = 0; - BOOL ret = WriteConsoleW( - GetStdHandle(STD_OUTPUT_HANDLE), - dataToWrite.data(), dataToWrite.size(), &actual, NULL); - assert(ret && actual == dataToWrite.size()); - - // Read it back. - std::vector readBuffer(dataToWrite.size() * 2); - COORD bufSize = {static_cast(readBuffer.size()), 1}; - COORD bufCoord = {0, 0}; - SMALL_RECT topLeft = {0, 0, static_cast(readBuffer.size() - 1), 0}; - ret = ReadConsoleOutputW( - GetStdHandle(STD_OUTPUT_HANDLE), readBuffer.data(), - bufSize, bufCoord, &topLeft); - assert(ret); - - printf("\n"); - for (int i = 0; i < readBuffer.size(); ++i) { - printf("CHAR: %04x %04x\n", - readBuffer[i].Char.UnicodeChar, - readBuffer[i].Attributes); - } - return 0; -} diff --git a/deps/winpty/misc/VeryLargeRead.cc b/deps/winpty/misc/VeryLargeRead.cc deleted file mode 100644 index 58f089702..000000000 --- a/deps/winpty/misc/VeryLargeRead.cc +++ /dev/null @@ -1,122 +0,0 @@ -// -// 2015-09-25 -// I measured these limits on the size of a single ReadConsoleOutputW call. -// The limit seems to more-or-less disppear with Windows 8, which is the first -// OS to stop using ALPCs for console I/O. My guess is that the new I/O -// method does not use the 64KiB shared memory buffer that the ALPC method -// uses. -// -// I'm guessing the remaining difference between Windows 8/8.1 and Windows 10 -// might be related to the 32-vs-64-bitness. -// -// Client OSs -// -// Windows XP 32-bit VM ==> up to 13304 characters -// - 13304x1 works, but 13305x1 fails instantly -// Windows 7 32-bit VM ==> between 16-17 thousand characters -// - 16000x1 works, 17000x1 fails instantly -// - 163x100 *crashes* conhost.exe but leaves VeryLargeRead.exe running -// Windows 8 32-bit VM ==> between 240-250 million characters -// - 10000x24000 works, but 10000x25000 does not -// Windows 8.1 32-bit VM ==> between 240-250 million characters -// - 10000x24000 works, but 10000x25000 does not -// Windows 10 64-bit VM ==> no limit (tested to 576 million characters) -// - 24000x24000 works -// - `ver` reports [Version 10.0.10240], conhost.exe and ConhostV1.dll are -// 10.0.10240.16384 for file and product version. ConhostV2.dll is -// 10.0.10240.16391 for file and product version. -// -// Server OSs -// -// Windows Server 2008 64-bit VM ==> 14300-14400 characters -// - 14300x1 works, 14400x1 fails instantly -// - This OS does not have conhost.exe. -// - `ver` reports [Version 6.0.6002] -// Windows Server 2008 R2 64-bit VM ==> 15600-15700 characters -// - 15600x1 works, 15700x1 fails instantly -// - This OS has conhost.exe, and procexp.exe reveals console ALPC ports in -// use in conhost.exe. -// - `ver` reports [Version 6.1.7601], conhost.exe is 6.1.7601.23153 for file -// and product version. -// Windows Server 2012 64-bit VM ==> at least 100 million characters -// - 10000x10000 works (VM had only 1GiB of RAM, so I skipped larger tests) -// - This OS has Windows 8's task manager and procexp.exe reveals the same -// lack of ALPC ports and the same \Device\ConDrv\* files as Windows 8. -// - `ver` reports [Version 6.2.9200], conhost.exe is 6.2.9200.16579 for file -// and product version. -// -// To summarize: -// -// client-OS server-OS notes -// --------------------------------------------------------------------------- -// XP Server 2008 CSRSS, small reads -// 7 Server 2008 R2 ALPC-to-conhost, small reads -// 8, 8.1 Server 2012 new I/O interface, large reads allowed -// 10 enhanced console w/rewrapping -// -// (Presumably, Win2K, Vista, and Win2K3 behave the same as XP. conhost.exe -// was announced as a Win7 feature.) -// - -#include -#include -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - long long width = 9000; - long long height = 9000; - - assert(argc >= 1); - if (argc == 4) { - width = atoi(argv[2]); - height = atoi(argv[3]); - } else { - if (argc == 3) { - width = atoi(argv[1]); - height = atoi(argv[2]); - } - wchar_t args[1024]; - swprintf(args, 1024, L"CHILD %lld %lld", width, height); - startChildProcess(args); - return 0; - } - - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - setWindowPos(0, 0, 1, 1); - setBufferSize(width, height); - setWindowPos(0, 0, std::min(80LL, width), std::min(50LL, height)); - - setCursorPos(0, 0); - printf("A"); - fflush(stdout); - setCursorPos(width - 2, height - 1); - printf("B"); - fflush(stdout); - - trace("sizeof(CHAR_INFO) = %d", (int)sizeof(CHAR_INFO)); - - trace("Allocating buffer..."); - CHAR_INFO *buffer = new CHAR_INFO[width * height]; - assert(buffer != NULL); - memset(&buffer[0], 0, sizeof(CHAR_INFO)); - memset(&buffer[width * height - 2], 0, sizeof(CHAR_INFO)); - - COORD bufSize = { width, height }; - COORD bufCoord = { 0, 0 }; - SMALL_RECT readRegion = { 0, 0, width - 1, height - 1 }; - trace("ReadConsoleOutputW: calling..."); - BOOL success = ReadConsoleOutputW(conout, buffer, bufSize, bufCoord, &readRegion); - trace("ReadConsoleOutputW: success=%d", success); - - assert(buffer[0].Char.UnicodeChar == L'A'); - assert(buffer[width * height - 2].Char.UnicodeChar == L'B'); - trace("Top-left and bottom-right characters read successfully!"); - - Sleep(30000); - - delete [] buffer; - return 0; -} diff --git a/deps/winpty/misc/VkEscapeTest.cc b/deps/winpty/misc/VkEscapeTest.cc deleted file mode 100644 index 97bf59f99..000000000 --- a/deps/winpty/misc/VkEscapeTest.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Sending VK_PAUSE to the console window almost works as a mechanism for - * pausing it, but it doesn't because the console could turn off the - * ENABLE_LINE_INPUT console mode flag. - */ - -#define _WIN32_WINNT 0x0501 -#include -#include -#include - -CALLBACK DWORD pausingThread(LPVOID dummy) -{ - if (1) { - Sleep(1000); - HWND hwnd = GetConsoleWindow(); - SendMessage(hwnd, WM_KEYDOWN, VK_PAUSE, 1); - Sleep(1000); - SendMessage(hwnd, WM_KEYDOWN, VK_ESCAPE, 1); - } - - if (0) { - INPUT_RECORD ir; - memset(&ir, 0, sizeof(ir)); - ir.EventType = KEY_EVENT; - ir.Event.KeyEvent.bKeyDown = TRUE; - ir.Event.KeyEvent.wVirtualKeyCode = VK_PAUSE; - ir.Event.KeyEvent.wRepeatCount = 1; - } - - return 0; -} - -int main() -{ - HANDLE hin = GetStdHandle(STD_INPUT_HANDLE); - HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); - COORD c = { 0, 0 }; - - DWORD mode; - GetConsoleMode(hin, &mode); - SetConsoleMode(hin, mode & - ~(ENABLE_LINE_INPUT)); - - CreateThread(NULL, 0, - pausingThread, NULL, - 0, NULL); - - int i = 0; - while (true) { - Sleep(100); - printf("%d\n", ++i); - } - - return 0; -} diff --git a/deps/winpty/misc/Win10ResizeWhileFrozen.cc b/deps/winpty/misc/Win10ResizeWhileFrozen.cc deleted file mode 100644 index 82feaf3c5..000000000 --- a/deps/winpty/misc/Win10ResizeWhileFrozen.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Demonstrates a conhost hang that occurs when widening the console buffer - * while selection is in progress. The problem affects the new Windows 10 - * console, not the "legacy" console mode that Windows 10 also includes. - * - * First tested with: - * - Windows 10.0.10240 - * - conhost.exe version 10.0.10240.16384 - * - ConhostV1.dll version 10.0.10240.16384 - * - ConhostV2.dll version 10.0.10240.16391 - */ - -#include -#include -#include -#include - -#include "TestUtil.cc" - -const int SC_CONSOLE_MARK = 0xFFF2; -const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - setWindowPos(0, 0, 1, 1); - setBufferSize(80, 25); - setWindowPos(0, 0, 80, 25); - - countDown(5); - - SendMessage(GetConsoleWindow(), WM_SYSCOMMAND, SC_CONSOLE_SELECT_ALL, 0); - Sleep(2000); - - // This API call does not return. In the console window, the "Select All" - // operation appears to end. The console window becomes non-responsive, - // and the conhost.exe process must be killed from the Task Manager. - // (Killing this test program or closing the console window is not - // sufficient.) - // - // The same hang occurs whether line resizing is off or on. It happens - // with both "Mark" and "Select All". Calling setBufferSize with the - // existing buffer size does not hang, but calling it with only a changed - // buffer height *does* hang. Calling setWindowPos does not hang. - setBufferSize(120, 25); - - printf("Done...\n"); - Sleep(2000); -} diff --git a/deps/winpty/misc/Win10WrapTest1.cc b/deps/winpty/misc/Win10WrapTest1.cc deleted file mode 100644 index 645fa95d5..000000000 --- a/deps/winpty/misc/Win10WrapTest1.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Demonstrates some wrapping behaviors of the new Windows 10 console. - */ - -#include -#include -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - setWindowPos(0, 0, 1, 1); - setBufferSize(40, 20); - setWindowPos(0, 0, 40, 20); - - system("cls"); - - repeatChar(39, 'A'); repeatChar(1, ' '); - repeatChar(39, 'B'); repeatChar(1, ' '); - printf("\n"); - - repeatChar(39, 'C'); repeatChar(1, ' '); - repeatChar(39, 'D'); repeatChar(1, ' '); - printf("\n"); - - repeatChar(40, 'E'); - repeatChar(40, 'F'); - printf("\n"); - - repeatChar(39, 'G'); repeatChar(1, ' '); - repeatChar(39, 'H'); repeatChar(1, ' '); - printf("\n"); - - Sleep(2000); - - setChar(39, 0, '*', 0x24); - setChar(39, 1, '*', 0x24); - - setChar(39, 3, ' ', 0x24); - setChar(39, 4, ' ', 0x24); - - setChar(38, 6, ' ', 0x24); - setChar(38, 7, ' ', 0x24); - - Sleep(2000); - setWindowPos(0, 0, 35, 20); - setBufferSize(35, 20); - trace("DONE"); - - printf("Sleeping forever...\n"); - while(true) { Sleep(1000); } -} diff --git a/deps/winpty/misc/Win10WrapTest2.cc b/deps/winpty/misc/Win10WrapTest2.cc deleted file mode 100644 index 50615fc8c..000000000 --- a/deps/winpty/misc/Win10WrapTest2.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include "TestUtil.cc" - -int main(int argc, char *argv[]) { - if (argc == 1) { - startChildProcess(L"CHILD"); - return 0; - } - - const int WIDTH = 25; - - setWindowPos(0, 0, 1, 1); - setBufferSize(WIDTH, 40); - setWindowPos(0, 0, WIDTH, 20); - - system("cls"); - - for (int i = 0; i < 100; ++i) { - printf("FOO(%d)\n", i); - } - - repeatChar(5, '\n'); - repeatChar(WIDTH * 5, '.'); - repeatChar(10, '\n'); - setWindowPos(0, 20, WIDTH, 20); - writeBox(0, 5, 1, 10, '|'); - - Sleep(120000); -} diff --git a/deps/winpty/misc/Win32Echo1.cc b/deps/winpty/misc/Win32Echo1.cc deleted file mode 100644 index 06fc79f79..000000000 --- a/deps/winpty/misc/Win32Echo1.cc +++ /dev/null @@ -1,26 +0,0 @@ -/* - * A Win32 program that reads raw console input with ReadFile and echos - * it to stdout. - */ - -#include -#include -#include - -int main() -{ - int count = 0; - HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); - HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleMode(hStdIn, 0); - - while (true) { - DWORD actual; - char ch; - ReadFile(hStdIn, &ch, 1, &actual, NULL); - printf("%02x ", ch); - if (++count == 50) - break; - } - return 0; -} diff --git a/deps/winpty/misc/Win32Echo2.cc b/deps/winpty/misc/Win32Echo2.cc deleted file mode 100644 index b2ea2ad1c..000000000 --- a/deps/winpty/misc/Win32Echo2.cc +++ /dev/null @@ -1,19 +0,0 @@ -/* - * A Win32 program that reads raw console input with getch and echos - * it to stdout. - */ - -#include -#include - -int main() -{ - int count = 0; - while (true) { - int ch = getch(); - printf("%02x ", ch); - if (++count == 50) - break; - } - return 0; -} diff --git a/deps/winpty/misc/Win32Test1.cc b/deps/winpty/misc/Win32Test1.cc deleted file mode 100644 index a40d318a9..000000000 --- a/deps/winpty/misc/Win32Test1.cc +++ /dev/null @@ -1,46 +0,0 @@ -#define _WIN32_WINNT 0x0501 -#include "../src/shared/DebugClient.cc" -#include -#include - -const int SC_CONSOLE_MARK = 0xFFF2; - -CALLBACK DWORD writerThread(void*) -{ - while (true) { - Sleep(1000); - trace("writing"); - printf("X\n"); - trace("written"); - } -} - -int main() -{ - CreateThread(NULL, 0, writerThread, NULL, 0, NULL); - trace("marking console"); - HWND hwnd = GetConsoleWindow(); - PostMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_MARK, 0); - - Sleep(2000); - - trace("reading output"); - CHAR_INFO buf[1]; - COORD bufSize = { 1, 1 }; - COORD zeroCoord = { 0, 0 }; - SMALL_RECT readRect = { 0, 0, 0, 0 }; - ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), - buf, - bufSize, - zeroCoord, - &readRect); - trace("done reading output"); - - Sleep(2000); - - PostMessage(hwnd, WM_CHAR, 27, 0x00010001); - - Sleep(1100); - - return 0; -} diff --git a/deps/winpty/misc/Win32Test2.cc b/deps/winpty/misc/Win32Test2.cc deleted file mode 100644 index 2777bad45..000000000 --- a/deps/winpty/misc/Win32Test2.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This test demonstrates that putting a console into selection mode does not - * block the low-level console APIs, even though it blocks WriteFile. - */ - -#define _WIN32_WINNT 0x0501 -#include "../src/shared/DebugClient.cc" -#include -#include - -const int SC_CONSOLE_MARK = 0xFFF2; - -CALLBACK DWORD writerThread(void*) -{ - CHAR_INFO xChar, fillChar; - memset(&xChar, 0, sizeof(xChar)); - xChar.Char.AsciiChar = 'X'; - xChar.Attributes = 7; - memset(&fillChar, 0, sizeof(fillChar)); - fillChar.Char.AsciiChar = ' '; - fillChar.Attributes = 7; - COORD oneCoord = { 1, 1 }; - COORD zeroCoord = { 0, 0 }; - - while (true) { - SMALL_RECT writeRegion = { 5, 5, 5, 5 }; - WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), - &xChar, oneCoord, - zeroCoord, - &writeRegion); - Sleep(500); - SMALL_RECT scrollRect = { 1, 1, 20, 20 }; - COORD destCoord = { 0, 0 }; - ScrollConsoleScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE), - &scrollRect, - NULL, - destCoord, - &fillChar); - } -} - -int main() -{ - CreateThread(NULL, 0, writerThread, NULL, 0, NULL); - trace("marking console"); - HWND hwnd = GetConsoleWindow(); - PostMessage(hwnd, WM_SYSCOMMAND, SC_CONSOLE_MARK, 0); - - Sleep(2000); - - trace("reading output"); - CHAR_INFO buf[1]; - COORD bufSize = { 1, 1 }; - COORD zeroCoord = { 0, 0 }; - SMALL_RECT readRect = { 0, 0, 0, 0 }; - ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), - buf, - bufSize, - zeroCoord, - &readRect); - trace("done reading output"); - - Sleep(2000); - - PostMessage(hwnd, WM_CHAR, 27, 0x00010001); - - Sleep(1100); - - return 0; -} diff --git a/deps/winpty/misc/Win32Test3.cc b/deps/winpty/misc/Win32Test3.cc deleted file mode 100644 index 1fb92aff3..000000000 --- a/deps/winpty/misc/Win32Test3.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Creates a window station and starts a process under it. The new process - * also gets a new console. - */ - -#include -#include -#include - -int main() -{ - BOOL success; - - SECURITY_ATTRIBUTES sa; - memset(&sa, 0, sizeof(sa)); - sa.bInheritHandle = TRUE; - - HWINSTA originalStation = GetProcessWindowStation(); - printf("originalStation == 0x%x\n", originalStation); - HWINSTA station = CreateWindowStation(NULL, - 0, - WINSTA_ALL_ACCESS, - &sa); - printf("station == 0x%x\n", station); - if (!SetProcessWindowStation(station)) - printf("SetWindowStation failed!\n"); - HDESK desktop = CreateDesktop("Default", NULL, NULL, - /*dwFlags=*/0, GENERIC_ALL, - &sa); - printf("desktop = 0x%x\n", desktop); - - char stationName[256]; - stationName[0] = '\0'; - success = GetUserObjectInformation(station, UOI_NAME, - stationName, sizeof(stationName), - NULL); - printf("stationName = [%s]\n", stationName); - - char startupDesktop[256]; - sprintf(startupDesktop, "%s\\Default", stationName); - - STARTUPINFO sui; - PROCESS_INFORMATION pi; - memset(&sui, 0, sizeof(sui)); - memset(&pi, 0, sizeof(pi)); - sui.cb = sizeof(STARTUPINFO); - sui.lpDesktop = startupDesktop; - - // Start a cmd subprocess, and have it start its own cmd subprocess. - // Both subprocesses will connect to the same non-interactive window - // station. - - const char program[] = "c:\\windows\\system32\\cmd.exe"; - char cmdline[256]; - sprintf(cmdline, "%s /c cmd", program); - success = CreateProcess(program, - cmdline, - NULL, - NULL, - /*bInheritHandles=*/FALSE, - /*dwCreationFlags=*/CREATE_NEW_CONSOLE, - NULL, NULL, - &sui, - &pi); - - printf("pid == %d\n", pi.dwProcessId); - - // This sleep is necessary. We must give the child enough time to - // connect to the specified window station. - Sleep(5000); - - SetProcessWindowStation(originalStation); - CloseWindowStation(station); - CloseDesktop(desktop); - Sleep(5000); - - return 0; -} diff --git a/deps/winpty/misc/Win32Write1.cc b/deps/winpty/misc/Win32Write1.cc deleted file mode 100644 index 6e5bf9668..000000000 --- a/deps/winpty/misc/Win32Write1.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * A Win32 program that scrolls and writes to the console using the ioctl-like - * interface. - */ - -#include -#include - -int main() -{ - HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - for (int i = 0; i < 80; ++i) { - - CONSOLE_SCREEN_BUFFER_INFO info; - GetConsoleScreenBufferInfo(conout, &info); - - SMALL_RECT src = { 0, 1, info.dwSize.X - 1, info.dwSize.Y - 1 }; - COORD destOrigin = { 0, 0 }; - CHAR_INFO fillCharInfo = { 0 }; - fillCharInfo.Char.AsciiChar = ' '; - fillCharInfo.Attributes = 7; - ScrollConsoleScreenBuffer(conout, - &src, - NULL, - destOrigin, - &fillCharInfo); - - CHAR_INFO buffer = { 0 }; - buffer.Char.AsciiChar = 'X'; - buffer.Attributes = 7; - COORD bufferSize = { 1, 1 }; - COORD bufferCoord = { 0, 0 }; - SMALL_RECT writeRegion = { 0, 0, 0, 0 }; - writeRegion.Left = writeRegion.Right = i; - writeRegion.Top = writeRegion.Bottom = 5; - WriteConsoleOutput(conout, - &buffer, bufferSize, bufferCoord, - &writeRegion); - - Sleep(250); - } - return 0; -} diff --git a/deps/winpty/misc/WindowsBugCrashReader.cc b/deps/winpty/misc/WindowsBugCrashReader.cc deleted file mode 100644 index e6d9558df..000000000 --- a/deps/winpty/misc/WindowsBugCrashReader.cc +++ /dev/null @@ -1,27 +0,0 @@ -// I noticed this on the ConEmu web site: -// -// https://social.msdn.microsoft.com/Forums/en-US/40c8e395-cca9-45c8-b9b8-2fbe6782ac2b/readconsoleoutput-cause-access-violation-writing-location-exception -// https://conemu.github.io/en/MicrosoftBugs.html -// -// In Windows 7, 8, and 8.1, a ReadConsoleOutputW with an out-of-bounds read -// region crashes the application. I have reproduced the problem on Windows 8 -// and 8.1, but not on Windows 7. -// - -#include - -#include "TestUtil.cc" - -int main() { - setWindowPos(0, 0, 1, 1); - setBufferSize(80, 25); - setWindowPos(0, 0, 80, 25); - - const HANDLE conout = openConout(); - static CHAR_INFO lineBuf[80]; - SMALL_RECT readRegion = { 0, 999, 79, 999 }; - const BOOL ret = ReadConsoleOutputW(conout, lineBuf, {80, 1}, {0, 0}, &readRegion); - ASSERT(!ret && "ReadConsoleOutputW should have failed"); - - return 0; -} diff --git a/deps/winpty/misc/WriteConsole.cc b/deps/winpty/misc/WriteConsole.cc deleted file mode 100644 index a03670ca9..000000000 --- a/deps/winpty/misc/WriteConsole.cc +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -static std::wstring mbsToWcs(const std::string &s) { - const size_t len = mbstowcs(nullptr, s.c_str(), 0); - if (len == static_cast(-1)) { - assert(false && "mbsToWcs: invalid string"); - } - std::wstring ret; - ret.resize(len); - const size_t len2 = mbstowcs(&ret[0], s.c_str(), len); - assert(len == len2); - return ret; -} - -uint32_t parseHex(wchar_t ch, bool &invalid) { - if (ch >= L'0' && ch <= L'9') { - return ch - L'0'; - } else if (ch >= L'a' && ch <= L'f') { - return ch - L'a' + 10; - } else if (ch >= L'A' && ch <= L'F') { - return ch - L'A' + 10; - } else { - invalid = true; - return 0; - } -} - -int main(int argc, char *argv[]) { - std::vector args; - for (int i = 1; i < argc; ++i) { - args.push_back(mbsToWcs(argv[i])); - } - - std::wstring out; - for (const auto &arg : args) { - if (!out.empty()) { - out.push_back(L' '); - } - for (size_t i = 0; i < arg.size(); ++i) { - wchar_t ch = arg[i]; - wchar_t nch = i + 1 < arg.size() ? arg[i + 1] : L'\0'; - if (ch == L'\\') { - switch (nch) { - case L'a': ch = L'\a'; ++i; break; - case L'b': ch = L'\b'; ++i; break; - case L'e': ch = L'\x1b'; ++i; break; - case L'f': ch = L'\f'; ++i; break; - case L'n': ch = L'\n'; ++i; break; - case L'r': ch = L'\r'; ++i; break; - case L't': ch = L'\t'; ++i; break; - case L'v': ch = L'\v'; ++i; break; - case L'\\': ch = L'\\'; ++i; break; - case L'\'': ch = L'\''; ++i; break; - case L'\"': ch = L'\"'; ++i; break; - case L'\?': ch = L'\?'; ++i; break; - case L'x': - if (i + 3 < arg.size()) { - bool invalid = false; - uint32_t d1 = parseHex(arg[i + 2], invalid); - uint32_t d2 = parseHex(arg[i + 3], invalid); - if (!invalid) { - i += 3; - ch = (d1 << 4) | d2; - } - } - break; - case L'u': - if (i + 5 < arg.size()) { - bool invalid = false; - uint32_t d1 = parseHex(arg[i + 2], invalid); - uint32_t d2 = parseHex(arg[i + 3], invalid); - uint32_t d3 = parseHex(arg[i + 4], invalid); - uint32_t d4 = parseHex(arg[i + 5], invalid); - if (!invalid) { - i += 5; - ch = (d1 << 24) | (d2 << 16) | (d3 << 8) | d4; - } - } - break; - default: break; - } - } - out.push_back(ch); - } - } - - DWORD actual = 0; - if (!WriteConsoleW( - GetStdHandle(STD_OUTPUT_HANDLE), - out.c_str(), - out.size(), - &actual, - nullptr)) { - fprintf(stderr, "WriteConsole failed (is stdout a console?)\n"); - exit(1); - } - - return 0; -} diff --git a/deps/winpty/misc/build32.sh b/deps/winpty/misc/build32.sh deleted file mode 100644 index 162993ce3..000000000 --- a/deps/winpty/misc/build32.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e -name=$1 -name=${name%.} -name=${name%.cc} -name=${name%.exe} -echo Compiling $name.cc to $name.exe -i686-w64-mingw32-g++.exe -static -std=c++11 $name.cc -o $name.exe -i686-w64-mingw32-strip $name.exe diff --git a/deps/winpty/misc/build64.sh b/deps/winpty/misc/build64.sh deleted file mode 100644 index 675796768..000000000 --- a/deps/winpty/misc/build64.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e -name=$1 -name=${name%.} -name=${name%.cc} -name=${name%.exe} -echo Compiling $name.cc to $name.exe -x86_64-w64-mingw32-g++.exe -static -std=c++11 $name.cc -o $name.exe -x86_64-w64-mingw32-strip $name.exe diff --git a/deps/winpty/misc/color-test.sh b/deps/winpty/misc/color-test.sh deleted file mode 100644 index 065c8094e..000000000 --- a/deps/winpty/misc/color-test.sh +++ /dev/null @@ -1,212 +0,0 @@ -#!/bin/bash - -FORE=$1 -BACK=$2 -FILL=$3 - -if [ "$FORE" = "" ]; then - FORE=DefaultFore -fi -if [ "$BACK" = "" ]; then - BACK=DefaultBack -fi - -# To detect color changes, we want a character that fills the whole cell -# if possible. U+2588 is perfect, except that it becomes invisible in the -# original xterm, when bolded. For that terminal, use something else, like -# "#" or "@". -if [ "$FILL" = "" ]; then - FILL="█" -fi - -# SGR (Select Graphic Rendition) -s() { - printf '\033[0m' - while [ "$1" != "" ]; do - printf '\033['"$1"'m' - shift - done -} - -# Print -p() { - echo -n "$@" -} - -# Print with newline -pn() { - echo "$@" -} - -# For practical reasons, sandwich black and white in-between the other colors. -FORE_COLORS="31 30 37 32 33 34 35 36" -BACK_COLORS="41 40 47 42 43 44 45 46" - - - -### Test order of Invert(7) -- it does not matter what order it appears in. - -# The Red color setting here (31) is shadowed by the green setting (32). The -# Reverse flag does not cause (32) to alter the background color immediately; -# instead, the Reverse flag is applied once to determine the final effective -# Fore/Back colors. -s 7 31 32; p " -- Should be: $BACK-on-green -- "; s; pn -s 31 7 32; p " -- Should be: $BACK-on-green -- "; s; pn -s 31 32 7; p " -- Should be: $BACK-on-green -- "; s; pn - -# As above, but for the background color. -s 7 41 42; p " -- Should be: green-on-$FORE -- "; s; pn -s 41 7 42; p " -- Should be: green-on-$FORE -- "; s; pn -s 41 42 7; p " -- Should be: green-on-$FORE -- "; s; pn - -# One last, related test -s 7; p "Invert text"; s 7 1; p " with some words bold"; s; pn; -s 0; p "Normal text"; s 0 1; p " with some words bold"; s; pn; - -pn - - - -### Test effect of Bold(1) on color, with and without Invert(7). - -# The Bold flag does not affect the background color when Reverse is missing. -# There should always be 8 colored boxes. -p " " -for x in $BACK_COLORS; do - s $x; p "-"; s $x 1; p "-" -done -s; pn " Bold should not affect background" - -# On some terminals, Bold affects color, and on some it doesn't. If there -# are only 8 colored boxes, then the next two tests will also show 8 colored -# boxes. If there are 16 boxes, then exactly one of the next two tests will -# also have 16 boxes. -p " " -for x in $FORE_COLORS; do - s $x; p "$FILL"; s $x 1; p "$FILL" -done -s; pn " Does bold affect foreground color?" - -# On some terminals, Bold+Invert highlights the final Background color. -p " " -for x in $FORE_COLORS; do - s $x 7; p "-"; s $x 7 1; p "-" -done -s; pn " Test if Bold+Invert affects background color" - -# On some terminals, Bold+Invert highlights the final Foreground color. -p " " -for x in $BACK_COLORS; do - s $x 7; p "$FILL"; s $x 7 1; p "$FILL" -done -s; pn " Test if Bold+Invert affects foreground color" - -pn - - - -### Test for support of ForeHi and BackHi properties. - -# ForeHi -p " " -for x in $FORE_COLORS; do - hi=$(( $x + 60 )) - s $x; p "$FILL"; s $hi; p "$FILL" -done -s; pn " Test for support of ForeHi colors" -p " " -for x in $FORE_COLORS; do - hi=$(( $x + 60 )) - s $x; p "$FILL"; s $x $hi; p "$FILL" -done -s; pn " Test for support of ForeHi colors (w/compat)" - -# BackHi -p " " -for x in $BACK_COLORS; do - hi=$(( $x + 60 )) - s $x; p "-"; s $hi; p "-" -done -s; pn " Test for support of BackHi colors" -p " " -for x in $BACK_COLORS; do - hi=$(( $x + 60 )) - s $x; p "-"; s $x $hi; p "-" -done -s; pn " Test for support of BackHi colors (w/compat)" - -pn - - - -### Identify the default fore and back colors. - -pn "Match default fore and back colors against 16-color palette" -pn " ==fore== ==back==" -for fore in $FORE_COLORS; do - forehi=$(( $fore + 60 )) - back=$(( $fore + 10 )) - backhi=$(( $back + 60 )) - p " " - s $fore; p "$FILL"; s; p "$FILL"; s $fore; p "$FILL"; s; p " " - s $forehi; p "$FILL"; s; p "$FILL"; s $forehi; p "$FILL"; s; p " " - s $back; p "-"; s; p "-"; s $back; p "-"; s; p " " - s $backhi; p "-"; s; p "-"; s $backhi; p "-"; s; p " " - pn " $fore $forehi $back $backhi" -done - -pn - - - -### Test coloring of rest-of-line. - -# -# When a new line is scrolled in, every cell in the line receives the -# current background color, which can be the default/transparent color. -# - -p "Newline with red background: usually no red -->"; s 41; pn -s; pn "This text is plain, but rest is red if scrolled -->" -s; p " "; s 41; printf '\033[1K'; s; printf '\033[1C'; pn "<-- red Erase-in-Line to beginning" -s; p "red Erase-in-Line to end -->"; s 41; printf '\033[0K'; s; pn -pn - - - -### Moving the cursor around does not change colors of anything. - -pn "Test modifying uncolored lines with a colored SGR:" -pn "aaaa" -pn -pn "____e" -s 31 42; printf '\033[4C\033[3A'; pn "bb" -pn "cccc" -pn "dddd" -s; pn - -pn "Test modifying colored+inverted+bold line with plain text:" -s 42 31 7 1; printf 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r'; -s; pn "This text is plain and followed by green-on-red -->" -pn - - - -### Full-width character overwriting - -pn 'Overwrite part of a full-width char with a half-width char' -p 'initial U+4000 ideographs -->'; s 31 42; p '䀀䀀'; s; pn -p 'write X to index #1 -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[24G'; p X; s; pn -p 'write X to index #2 -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[25G'; p X; s; pn -p 'write X to index #3 -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[26G'; p X; s; pn -p 'write X to index #4 -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[27G'; p X; s; pn -pn - -pn 'Verify that Erase-in-Line can "fix" last char in line' -p 'original -->'; s 31 42; p '䀀䀀'; s; pn -p 'overwrite -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[30G'; p 'XXX'; s; pn -p 'overwrite + Erase-in-Line -->'; s 31 42; p '䀀䀀'; s 35 44; printf '\033[30G'; p 'XXX'; s; printf '\033[0K'; pn -p 'original -->'; s 31 42; p 'X䀀䀀'; s; pn -p 'overwrite -->'; s 31 42; p 'X䀀䀀'; s 35 44; printf '\033[30G'; p 'ーー'; s; pn -p 'overwrite + Erase-in-Line -->'; s 31 42; p 'X䀀䀀'; s 35 44; printf '\033[30G'; p 'ーー'; s; printf '\033[0K'; pn -pn diff --git a/deps/winpty/misc/font-notes.txt b/deps/winpty/misc/font-notes.txt deleted file mode 100644 index d4e36d8e2..000000000 --- a/deps/winpty/misc/font-notes.txt +++ /dev/null @@ -1,300 +0,0 @@ -================================================================== -Notes regarding fonts, code pages, and East Asian character widths -================================================================== - - -Registry settings -================= - - * There are console registry settings in `HKCU\Console`. That key has many - default settings (e.g. the default font settings) and also per-app subkeys - for app-specific overrides. - - * It is possible to override the code page with an app-specific setting. - - * There are registry settings in - `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console`. In particular, - the `TrueTypeFont` subkey has a list of suitable font names associated with - various CJK code pages, as well as default font names. - - * There are two values in `HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage` - that specify the current code pages -- `OEMCP` and `ACP`. Setting the - system locale via the Control Panel's "Region" or "Language" dialogs seems - to change these code page values. - - -Console fonts -============= - - * The `FontFamily` field of `CONSOLE_FONT_INFOEX` has two parts: - - The high four bits can be exactly one of the `FF_xxxx` font families: - FF_DONTCARE(0x00) - FF_ROMAN(0x10) - FF_SWISS(0x20) - FF_MODERN(0x30) - FF_SCRIPT(0x40) - FF_DECORATIVE(0x50) - - The low four bits are a bitmask: - TMPF_FIXED_PITCH(1) -- actually means variable pitch - TMPF_VECTOR(2) - TMPF_TRUETYPE(4) - TMPF_DEVICE(8) - - * Each console has its own independent console font table. The current font - is identified with an index into this table. The size of the table is - returned by the undocumented `GetNumberOfConsoleFonts` API. It is apparently - possible to get the table size without this API, by instead calling - `GetConsoleFontSize` on each nonnegative index starting with 0 until the API - fails by returning (0, 0). - - * The font table grows dynamically. Each time the console is configured with - a previously-unused (FaceName, Size) combination, two entries are added to - the font table -- one with normal weight and one with bold weight. Fonts - added this way are always TrueType fonts. - - * Initially, the font table appears to contain only raster fonts. For - example, on an English Windows 8 installation, here is the initial font - table: - font 0: 4x6 - font 1: 6x8 - font 2: 8x8 - font 3: 16x8 - font 4: 5x12 - font 5: 7x12 - font 6: 8x12 -- the current font - font 7: 16x12 - font 8: 12x16 - font 9: 10x18 - `GetNumberOfConsoleFonts` returns 10, and this table matches the raster font - sizes according to the console properties dialog. - - * With a Japanese or Chinese locale, the initial font table appears to contain - the sizes applicable to both the East Asian raster font, as well as the - sizes for the CP437/CP1252 raster font. - - * The index passed to `SetCurrentConsoleFontEx` apparently has no effect. - The undocumented `SetConsoleFont` API, however, accepts *only* a font index, - and on Windows 8 English, it switches between all 10 fonts, even font index - #0. - - * If the index passed to `SetConsoleFont` identifies a Raster Font - incompatible with the current code page, then another Raster Font is - activated. - - * Passing "Terminal" to `SetCurrentConsoleFontEx` seems to have no effect. - Perhaps relatedly, `SetCurrentConsoleFontEx` does not fail if it is given a - bogus `FaceName`. Some font is still chosen and activated. Passing a face - name and height seems to work reliably, modulo the CP936 issue described - below. - - -Console fonts and code pages -============================ - - * On an English Windows installation, the default code page is 437, and it - cannot be set to 932 (Shift-JIS). (The API call fails.) Changing the - system locale to "Japanese (Japan)" using the Region/Language dialog - changes the default CP to 932 and permits changing the console CP between - 437 and 932. - - * A console has both an input code page and an output code page - (`{Get,Set}ConsoleCP` and `{Get,Set}ConsoleOutputCP`). I'm not going to - distinguish between the two for this document; presumably only the output - CP matters. The code page can change while the console is open, e.g. - by running `mode con: cp select={932,437,1252}` or by calling - `SetConsoleOutputCP`. - - * The current code page restricts which TrueType fonts and which Raster Font - sizes are available in the console properties dialog. This can change - while the console is open. - - * Changing the code page almost(?) always changes the current console font. - So far, I don't know how the new font is chosen. - - * With a CP of 932, the only TrueType font available in the console properties - dialog is "MS Gothic", displayed as "MS ゴシック". It is still possible to - use the English-default TrueType console fonts, Lucida Console and Consolas, - via `SetCurrentConsoleFontEx`. - - * When using a Raster Font and CP437 or CP1252, writing a UTF-16 codepoint not - representable in the code page instead writes a question mark ('?') to the - console. This conversion does not apply with a TrueType font, nor with the - Raster Font for CP932 or CP936. - - -ReadConsoleOutput and double-width characters -============================================== - - * With a Raster Font active, when `ReadConsoleOutputW` reads two cells of a - double-width character, it fills only a single `CHAR_INFO` structure. The - unused trailing `CHAR_INFO` structures are zero-filled. With a TrueType - font active, `ReadConsoleOutputW` instead fills two `CHAR_INFO` structures, - the first marked with `COMMON_LVB_LEADING_BYTE` and the second marked with - `COMMON_LVB_TRAILING_BYTE`. The flag is a misnomer--there aren't two - *bytes*, but two cells, and they have equal `CHAR_INFO.Char.UnicodeChar` - values. - - * `ReadConsoleOutputA`, on the other hand, reads two `CHAR_INFO` cells, and - if the UTF-16 value can be represented as two bytes in the ANSI/OEM CP, then - the two bytes are placed in the two `CHAR_INFO.Char.AsciiChar` values, and - the `COMMON_LVB_{LEADING,TRAILING}_BYTE` values are also used. If the - codepoint isn't representable, I don't remember what happens -- I think the - `AsciiChar` values take on an invalid marker. - - * Reading only one cell of a double-width character reads a space (U+0020) - instead. Raster-vs-TrueType and wide-vs-ANSI do not matter. - - XXX: what about attributes? Can a double-width character have mismatched - color attributes? - - XXX: what happens when writing to just one cell of a double-width - character? - - -Default Windows fonts for East Asian languages -============================================== -CP932 / Japanese: "MS ゴシック" (MS Gothic) -CP936 / Chinese Simplified: "新宋体" (SimSun) - - -Unreliable character width (half-width vs full-width) -===================================================== - -The half-width vs full-width status of a codepoint depends on at least these variables: - * OS version (Win10 legacy and new modes are different versions) - * system locale (English vs Japanese vs Chinese Simplified vs Chinese Traditional, etc) - * code page (437 vs 932 vs 936, etc) - * raster vs TrueType (Terminal vs MS Gothic vs SimSun, etc) - * font size - * rendered-vs-model (rendered width can be larger or smaller than model width) - -Example 1: U+2014 (EM DASH): East_Asian_Width: Ambiguous --------------------------------------------------------- - rendered modeled -CP932: Win7/8 Raster Fonts half half -CP932: Win7/8 Gothic 14/15px half full -CP932: Win7/8 Consolas 14/15px half full -CP932: Win7/8 Lucida Console 14px half full -CP932: Win7/8 Lucida Console 15px half half -CP932: Win10New Raster Fonts half half -CP932: Win10New Gothic 14/15px half half -CP932: Win10New Consolas 14/15px half half -CP932: Win10New Lucida Console 14/15px half half - -CP936: Win7/8 Raster Fonts full full -CP936: Win7/8 SimSun 14px full full -CP936: Win7/8 SimSun 15px full half -CP936: Win7/8 Consolas 14/15px half full -CP936: Win10New Raster Fonts full full -CP936: Win10New SimSum 14/15px full full -CP936: Win10New Consolas 14/15px half half - -Example 2: U+3044 (HIRAGANA LETTER I): East_Asian_Width: Wide -------------------------------------------------------------- - rendered modeled -CP932: Win7/8/10N Raster Fonts full full -CP932: Win7/8/10N Gothic 14/15px full full -CP932: Win7/8/10N Consolas 14/15px half(*2) full -CP932: Win7/8/10N Lucida Console 14/15px half(*3) full - -CP936: Win7/8/10N Raster Fonts full full -CP936: Win7/8/10N SimSun 14/15px full full -CP936: Win7/8/10N Consolas 14/15px full full - -Example 3: U+30FC (KATAKANA-HIRAGANA PROLONGED SOUND MARK): East_Asian_Width: Wide ----------------------------------------------------------------------------------- - rendered modeled -CP932: Win7 Raster Fonts full full -CP932: Win7 Gothic 14/15px full full -CP932: Win7 Consolas 14/15px half(*2) full -CP932: Win7 Lucida Console 14px half(*3) full -CP932: Win7 Lucida Console 15px half(*3) half -CP932: Win8 Raster Fonts full full -CP932: Win8 Gothic 14px full half -CP932: Win8 Gothic 15px full full -CP932: Win8 Consolas 14/15px half(*2) full -CP932: Win8 Lucida Console 14px half(*3) full -CP932: Win8 Lucida Console 15px half(*3) half -CP932: Win10New Raster Fonts full full -CP932: Win10New Gothic 14/15px full full -CP932: Win10New Consolas 14/15px half(*2) half -CP932: Win10New Lucida Console 14/15px half(*2) half - -CP936: Win7/8 Raster Fonts full full -CP936: Win7/8 SimSun 14px full full -CP936: Win7/8 SimSun 15px full half -CP936: Win7/8 Consolas 14px full full -CP936: Win7/8 Consolas 15px full half -CP936: Win10New Raster Fonts full full -CP936: Win10New SimSum 14/15px full full -CP936: Win10New Consolas 14/15px full full - -Example 4: U+4000 (CJK UNIFIED IDEOGRAPH-4000): East_Asian_Width: Wide ----------------------------------------------------------------------- - rendered modeled -CP932: Win7 Raster Fonts half(*1) half -CP932: Win7 Gothic 14/15px full full -CP932: Win7 Consolas 14/15px half(*2) full -CP932: Win7 Lucida Console 14px half(*3) full -CP932: Win7 Lucida Console 15px half(*3) half -CP932: Win8 Raster Fonts half(*1) half -CP932: Win8 Gothic 14px full half -CP932: Win8 Gothic 15px full full -CP932: Win8 Consolas 14/15px half(*2) full -CP932: Win8 Lucida Console 14px half(*3) full -CP932: Win8 Lucida Console 15px half(*3) half -CP932: Win10New Raster Fonts half(*1) half -CP932: Win10New Gothic 14/15px full full -CP932: Win10New Consolas 14/15px half(*2) half -CP932: Win10New Lucida Console 14/15px half(*2) half - -CP936: Win7/8 Raster Fonts full full -CP936: Win7/8 SimSun 14px full full -CP936: Win7/8 SimSun 15px full half -CP936: Win7/8 Consolas 14px full full -CP936: Win7/8 Consolas 15px full half -CP936: Win10New Raster Fonts full full -CP936: Win10New SimSum 14/15px full full -CP936: Win10New Consolas 14/15px full full - -(*1) Rendered as a half-width filled white box -(*2) Rendered as a half-width box with a question mark inside -(*3) Rendered as a half-width empty box -(!!) One of the only places in Win10New where rendered and modeled width disagree - - -Windows quirk: unreliable font heights with CP936 / Chinese Simplified -====================================================================== - -When I set the font to 新宋体 17px, using either the properties dialog or -`SetCurrentConsoleFontEx`, the height reported by `GetCurrentConsoleFontEx` is -not 17, but is instead 19. The same problem does not affect Raster Fonts, -nor have I seen the problem in the English or Japanese locales. I observed -this with Windows 7 and Windows 10 new mode. - -If I set the font using the facename, width, *and* height, then the -`SetCurrentConsoleFontEx` and `GetCurrentConsoleFontEx` values agree. If I -set the font using *only* the facename and height, then the two values -disagree. - - -Windows bug: GetCurrentConsoleFontEx is initially invalid -========================================================= - - - Assume there is no configured console font name in the registry. In this - case, the console defaults to a raster font. - - Open a new console and call the `GetCurrentConsoleFontEx` API. - - The `FaceName` field of the returned `CONSOLE_FONT_INFOEX` data - structure is incorrect. On Windows 7, 8, and 10, I observed that the - field was blank. On Windows 8, occasionally, it instead contained: - U+AE72 U+75BE U+0001 - The other fields of the structure all appeared correct: - nFont=6 dwFontSize=(8,12) FontFamily=0x30 FontWeight=400 - - The `FaceName` field becomes initialized easily: - - Open the console properties dialog and click OK. (Cancel is not - sufficient.) - - Call the undocumented `SetConsoleFont` with the current font table - index, which is 6 in the example above. - - It seems that the console uncritically accepts whatever string is - stored in the registry, including a blank string, and passes it on the - the `GetCurrentConsoleFontEx` caller. It is possible to get the console - to *write* a blank setting into the registry -- simply open the console - (default or app-specific) properties and click OK. diff --git a/deps/winpty/misc/winbug-15048.cc b/deps/winpty/misc/winbug-15048.cc deleted file mode 100644 index 0e98d648c..000000000 --- a/deps/winpty/misc/winbug-15048.cc +++ /dev/null @@ -1,201 +0,0 @@ -/* - -Test program demonstrating a problem in Windows 15048's ReadConsoleOutput API. - -To compile: - - cl /nologo /EHsc winbug-15048.cc shell32.lib - -Example of regressed input: - -Case 1: - - > chcp 932 - > winbug-15048 -face-gothic 3044 - - Correct output: - - 1**34 (nb: U+3044 replaced with '**' to avoid MSVC encoding warning) - 5678 - - ReadConsoleOutputW (both rows, 3 cols) - row 0: U+0031(0007) U+3044(0107) U+3044(0207) U+0033(0007) - row 1: U+0035(0007) U+0036(0007) U+0037(0007) U+0038(0007) - - ReadConsoleOutputW (both rows, 4 cols) - row 0: U+0031(0007) U+3044(0107) U+3044(0207) U+0033(0007) U+0034(0007) - row 1: U+0035(0007) U+0036(0007) U+0037(0007) U+0038(0007) U+0020(0007) - - ReadConsoleOutputW (second row) - row 1: U+0035(0007) U+0036(0007) U+0037(0007) U+0038(0007) U+0020(0007) - - ... - - Win10 15048 bad output: - - 1**34 - 5678 - - ReadConsoleOutputW (both rows, 3 cols) - row 0: U+0031(0007) U+3044(0007) U+0033(0007) U+0035(0007) - row 1: U+0036(0007) U+0037(0007) U+0038(0007) U+0000(0000) - - ReadConsoleOutputW (both rows, 4 cols) - row 0: U+0031(0007) U+3044(0007) U+0033(0007) U+0034(0007) U+0035(0007) - row 1: U+0036(0007) U+0037(0007) U+0038(0007) U+0020(0007) U+0000(0000) - - ReadConsoleOutputW (second row) - row 1: U+0035(0007) U+0036(0007) U+0037(0007) U+0038(0007) U+0020(0007) - - ... - - The U+3044 character (HIRAGANA LETTER I) occupies two columns, but it only - fills one record in the ReadConsoleOutput output buffer, which has the - effect of shifting the first cell of the second row into the last cell of - the first row. Ordinarily, the first and second cells would also have the - COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE attributes set, which - allows winpty to detect the double-column character. - -Case 2: - - > chcp 437 - > winbug-15048 -face "Lucida Console" -h 4 221A - - The same issue happens with U+221A (SQUARE ROOT), but only in certain - fonts. The console seems to think this character occupies two columns - if the font is sufficiently small. The Windows console properties dialog - doesn't allow fonts below 5 pt, but winpty tries to use 2pt and 4pt Lucida - Console to allow very large console windows. - -Case 3: - - > chcp 437 - > winbug-15048 -face "Lucida Console" -h 12 FF12 - - The console selection system thinks U+FF12 (FULLWIDTH DIGIT TWO) occupies - two columns, which happens to be correct, but it's displayed as a single - column unrecognized character. It otherwise behaves the same as the other - cases. - -*/ - -#include -#include -#include -#include -#include -#include - -#include - -#define COUNT_OF(array) (sizeof(array) / sizeof((array)[0])) - -// See https://en.wikipedia.org/wiki/List_of_CJK_fonts -const wchar_t kMSGothic[] = { 0xff2d, 0xff33, 0x0020, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 }; // Japanese -const wchar_t kNSimSun[] = { 0x65b0, 0x5b8b, 0x4f53, 0 }; // Simplified Chinese -const wchar_t kMingLight[] = { 0x7d30, 0x660e, 0x9ad4, 0 }; // Traditional Chinese -const wchar_t kGulimChe[] = { 0xad74, 0xb9bc, 0xccb4, 0 }; // Korean - -static void set_font(const wchar_t *name, int size) { - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_FONT_INFOEX fontex {}; - fontex.cbSize = sizeof(fontex); - fontex.dwFontSize.Y = size; - fontex.FontWeight = 400; - fontex.FontFamily = 0x36; - wcsncpy(fontex.FaceName, name, COUNT_OF(fontex.FaceName)); - assert(SetCurrentConsoleFontEx(conout, FALSE, &fontex)); -} - -static void usage(const wchar_t *prog) { - printf("Usage: %ls [options]\n", prog); - printf(" -h HEIGHT\n"); - printf(" -face FACENAME\n"); - printf(" -face-{gothic|simsun|minglight|gulimche) [JP,CN-sim,CN-tra,KR]\n"); - printf(" hhhh -- print U+hhhh\n"); - exit(1); -} - -static void dump_region(SMALL_RECT region, const char *name) { - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - CHAR_INFO buf[1000]; - memset(buf, 0xcc, sizeof(buf)); - - const int w = region.Right - region.Left + 1; - const int h = region.Bottom - region.Top + 1; - - assert(ReadConsoleOutputW( - conout, buf, { (short)w, (short)h }, { 0, 0 }, - ®ion)); - - printf("\n"); - printf("ReadConsoleOutputW (%s)\n", name); - for (int y = 0; y < h; ++y) { - printf("row %d: ", region.Top + y); - for (int i = 0; i < region.Left * 13; ++i) { - printf(" "); - } - for (int x = 0; x < w; ++x) { - const int i = y * w + x; - printf("U+%04x(%04x) ", buf[i].Char.UnicodeChar, buf[i].Attributes); - } - printf("\n"); - } -} - -int main() { - wchar_t *cmdline = GetCommandLineW(); - int argc = 0; - wchar_t **argv = CommandLineToArgvW(cmdline, &argc); - const wchar_t *font_name = L"Lucida Console"; - int font_height = 8; - int test_ch = 0xff12; // U+FF12 FULLWIDTH DIGIT TWO - - for (int i = 1; i < argc; ++i) { - const std::wstring arg = argv[i]; - const std::wstring next = i + 1 < argc ? argv[i + 1] : L""; - if (arg == L"-face" && i + 1 < argc) { - font_name = argv[i + 1]; - i++; - } else if (arg == L"-face-gothic") { - font_name = kMSGothic; - } else if (arg == L"-face-simsun") { - font_name = kNSimSun; - } else if (arg == L"-face-minglight") { - font_name = kMingLight; - } else if (arg == L"-face-gulimche") { - font_name = kGulimChe; - } else if (arg == L"-h" && i + 1 < argc) { - font_height = _wtoi(next.c_str()); - i++; - } else if (arg.c_str()[0] != '-') { - test_ch = wcstol(arg.c_str(), NULL, 16); - } else { - printf("Unrecognized argument: %ls\n", arg.c_str()); - usage(argv[0]); - } - } - - const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE); - - set_font(font_name, font_height); - - system("cls"); - DWORD actual = 0; - wchar_t output[] = L"1234\n5678\n"; - output[1] = test_ch; - WriteConsoleW(conout, output, 10, &actual, nullptr); - - dump_region({ 0, 0, 3, 1 }, "both rows, 3 cols"); - dump_region({ 0, 0, 4, 1 }, "both rows, 4 cols"); - dump_region({ 0, 1, 4, 1 }, "second row"); - dump_region({ 0, 0, 4, 0 }, "first row"); - dump_region({ 1, 0, 4, 0 }, "first row, skip 1"); - dump_region({ 2, 0, 4, 0 }, "first row, skip 2"); - dump_region({ 3, 0, 4, 0 }, "first row, skip 3"); - - set_font(font_name, 14); - - return 0; -} diff --git a/deps/winpty/ship/build-pty4j-libpty.bat b/deps/winpty/ship/build-pty4j-libpty.bat deleted file mode 100644 index b6bca7b07..000000000 --- a/deps/winpty/ship/build-pty4j-libpty.bat +++ /dev/null @@ -1,36 +0,0 @@ -@echo off - -setlocal -cd %~dp0.. -set Path=C:\Python27;C:\Program Files\Git\cmd;%Path% - -call "%VS140COMNTOOLS%\VsDevCmd.bat" || goto :fail - -rmdir /s/q build-libpty 2>NUL -mkdir build-libpty\win -mkdir build-libpty\win\x86 -mkdir build-libpty\win\x86_64 -mkdir build-libpty\win\xp - -rmdir /s/q src\Release 2>NUL -rmdir /s/q src\.vs 2>NUL -del src\*.vcxproj src\*.vcxproj.filters src\*.sln src\*.sdf 2>NUL - -call vcbuild.bat --msvc-platform Win32 --gyp-msvs-version 2015 --toolset v140_xp || goto :fail -copy src\Release\Win32\winpty.dll build-libpty\win\xp || goto :fail -copy src\Release\Win32\winpty-agent.exe build-libpty\win\xp || goto :fail - -call vcbuild.bat --msvc-platform Win32 --gyp-msvs-version 2015 || goto :fail -copy src\Release\Win32\winpty.dll build-libpty\win\x86 || goto :fail -copy src\Release\Win32\winpty-agent.exe build-libpty\win\x86 || goto :fail - -call vcbuild.bat --msvc-platform x64 --gyp-msvs-version 2015 || goto :fail -copy src\Release\x64\winpty.dll build-libpty\win\x86_64 || goto :fail -copy src\Release\x64\winpty-agent.exe build-libpty\win\x86_64 || goto :fail - -echo success -goto :EOF - -:fail -echo error: build failed -exit /b 1 diff --git a/deps/winpty/ship/common_ship.py b/deps/winpty/ship/common_ship.py deleted file mode 100644 index b46cd5b8f..000000000 --- a/deps/winpty/ship/common_ship.py +++ /dev/null @@ -1,53 +0,0 @@ -import os -import sys - -if os.name != "nt": - sys.exit("Error: ship scripts require native Python 2.7. (wrong os.name)") -if sys.version_info[0:2] != (2,7): - sys.exit("Error: ship scripts require native Python 2.7. (wrong version)") - -import glob -import shutil -import subprocess -from distutils.spawn import find_executable - -topDir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) - -with open(topDir + "/VERSION.txt", "rt") as f: - winptyVersion = f.read().strip() - -def rmrf(patterns): - for pattern in patterns: - for path in glob.glob(pattern): - if os.path.isdir(path) and not os.path.islink(path): - print "+ rm -r " + path - sys.stdout.flush() - shutil.rmtree(path) - elif os.path.isfile(path): - print "+ rm " + path - sys.stdout.flush() - os.remove(path) - -def mkdir(path): - if not os.path.isdir(path): - os.makedirs(path) - -def requireExe(name, guesses): - if find_executable(name) is None: - for guess in guesses: - if os.path.exists(guess): - newDir = os.path.dirname(guess) - print "Adding " + newDir + " to Path to provide " + name - os.environ["Path"] = newDir + ";" + os.environ["Path"] - ret = find_executable(name) - if ret is None: - sys.exit("Error: required EXE is missing from Path: " + name) - return ret - -requireExe("git.exe", [ - "C:\\Program Files\\Git\\cmd\\git.exe", - "C:\\Program Files (x86)\\Git\\cmd\\git.exe" -]) - -commitHash = subprocess.check_output(["git.exe", "rev-parse", "HEAD"]).decode().strip() -defaultPathEnviron = "C:\\Windows\\System32;C:\\Windows" diff --git a/deps/winpty/ship/make_msvc_package.py b/deps/winpty/ship/make_msvc_package.py deleted file mode 100644 index 220f02b27..000000000 --- a/deps/winpty/ship/make_msvc_package.py +++ /dev/null @@ -1,165 +0,0 @@ -#!python - -# Copyright (c) 2016 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# -# Run with native CPython 2.7. -# -# This script looks for MSVC using a version-specific environment variable, -# such as VS140COMNTOOLS for MSVC 2015. -# - -import common_ship - -import argparse -import os -import shutil -import subprocess -import sys - -os.chdir(common_ship.topDir) -ZIP_TOOL = common_ship.requireExe("7z.exe", [ - "C:\\Program Files\\7-Zip\\7z.exe", - "C:\\Program Files (x86)\\7-Zip\\7z.exe", -]) - -MSVC_VERSION_TABLE = { - "2015" : { - "package_name" : "msvc2015", - "gyp_version" : "2015", - "common_tools_env" : "VS140COMNTOOLS", - "xp_toolset" : "v140_xp", - }, - "2013" : { - "package_name" : "msvc2013", - "gyp_version" : "2013", - "common_tools_env" : "VS120COMNTOOLS", - "xp_toolset" : "v120_xp", - }, -} - -ARCH_TABLE = { - "x64" : { - "msvc_platform" : "x64", - }, - "ia32" : { - "msvc_platform" : "Win32", - }, -} - -def readArguments(): - parser = argparse.ArgumentParser() - parser.add_argument("--msvc-version", default="2015") - ret = parser.parse_args() - if ret.msvc_version not in MSVC_VERSION_TABLE: - sys.exit("Error: unrecognized version: " + ret.msvc_version + ". " + - "Versions: " + " ".join(sorted(MSVC_VERSION_TABLE.keys()))) - return ret - -ARGS = readArguments() - -def checkoutGyp(): - if os.path.isdir("build-gyp"): - return - subprocess.check_call([ - "git.exe", - "clone", - "https://chromium.googlesource.com/external/gyp", - "build-gyp" - ]) - -def cleanMsvc(): - common_ship.rmrf(""" - src/Release src/.vs src/gen - src/*.vcxproj src/*.vcxproj.filters src/*.sln src/*.sdf - """.split()) - -def build(arch, packageDir, xp=False): - archInfo = ARCH_TABLE[arch] - versionInfo = MSVC_VERSION_TABLE[ARGS.msvc_version] - - devCmdPath = os.path.join(os.environ[versionInfo["common_tools_env"]], "VsDevCmd.bat") - if not os.path.isfile(devCmdPath): - sys.exit("Error: MSVC environment script missing: " + devCmdPath) - - newEnv = os.environ.copy() - newEnv["PATH"] = os.path.dirname(sys.executable) + ";" + common_ship.defaultPathEnviron - commandLine = ( - '"' + devCmdPath + '" && ' - " vcbuild.bat" + - " --gyp-msvs-version " + versionInfo["gyp_version"] + - " --msvc-platform " + archInfo["msvc_platform"] + - " --commit-hash " + common_ship.commitHash - ) - - subprocess.check_call(commandLine, shell=True, env=newEnv) - - archPackageDir = os.path.join(packageDir, arch) - if xp: - archPackageDir += "_xp" - - common_ship.mkdir(archPackageDir + "/bin") - common_ship.mkdir(archPackageDir + "/lib") - - binSrc = os.path.join(common_ship.topDir, "src/Release", archInfo["msvc_platform"]) - - shutil.copy(binSrc + "/winpty.dll", archPackageDir + "/bin") - shutil.copy(binSrc + "/winpty-agent.exe", archPackageDir + "/bin") - shutil.copy(binSrc + "/winpty-debugserver.exe", archPackageDir + "/bin") - shutil.copy(binSrc + "/winpty.lib", archPackageDir + "/lib") - -def buildPackage(): - versionInfo = MSVC_VERSION_TABLE[ARGS.msvc_version] - - packageName = "winpty-%s-%s" % ( - common_ship.winptyVersion, - versionInfo["package_name"], - ) - - packageRoot = os.path.join(common_ship.topDir, "ship/packages") - packageDir = os.path.join(packageRoot, packageName) - packageFile = packageDir + ".zip" - - common_ship.rmrf([packageDir]) - common_ship.rmrf([packageFile]) - common_ship.mkdir(packageDir) - - checkoutGyp() - cleanMsvc() - build("ia32", packageDir, True) - build("x64", packageDir, True) - cleanMsvc() - build("ia32", packageDir) - build("x64", packageDir) - - topDir = common_ship.topDir - - common_ship.mkdir(packageDir + "/include") - shutil.copy(topDir + "/src/include/winpty.h", packageDir + "/include") - shutil.copy(topDir + "/src/include/winpty_constants.h", packageDir + "/include") - shutil.copy(topDir + "/LICENSE", packageDir) - shutil.copy(topDir + "/README.md", packageDir) - shutil.copy(topDir + "/RELEASES.md", packageDir) - - subprocess.check_call([ZIP_TOOL, "a", packageFile, "."], cwd=packageDir) - -if __name__ == "__main__": - buildPackage() diff --git a/deps/winpty/ship/ship.py b/deps/winpty/ship/ship.py deleted file mode 100644 index 12874bac7..000000000 --- a/deps/winpty/ship/ship.py +++ /dev/null @@ -1,108 +0,0 @@ -#!python - -# Copyright (c) 2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# -# Run with native CPython 2.7 on a 64-bit computer. -# -# Each of the targets in BUILD_TARGETS must be installed to the default -# location. Each target must have the appropriate MinGW and non-MinGW -# compilers installed, as well as make and tar. -# - -import common_ship - -import multiprocessing -import os -import shutil -import subprocess -import sys - -os.chdir(common_ship.topDir) - -def dllVersion(path): - version = subprocess.check_output( - ["powershell.exe", - "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"" + path + "\").FileVersion"]) - return version.strip() - -# Determine other build parameters. -print "Determining Cygwin/MSYS2 DLL versions..." -sys.stdout.flush() -BUILD_TARGETS = [ - # { - # "name": "msys", - # "path": "C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin", - # # The parallel make.exe in the original MSYS/MinGW project hangs. - # "make_binary": "mingw32-make.exe", - # }, - { - "name": "msys2-" + dllVersion("C:\\msys32\\usr\\bin\\msys-2.0.dll") + "-ia32", - "path": "C:\\msys32\\mingw32\\bin;C:\\msys32\\usr\\bin", - }, - { - "name": "msys2-" + dllVersion("C:\\msys64\\usr\\bin\\msys-2.0.dll") + "-x64", - "path": "C:\\msys64\\mingw64\\bin;C:\\msys64\\usr\\bin", - }, - { - "name": "cygwin-" + dllVersion("C:\\cygwin\\bin\\cygwin1.dll") + "-ia32", - "path": "C:\\cygwin\\bin", - }, - { - "name": "cygwin-" + dllVersion("C:\\cygwin64\\bin\\cygwin1.dll") + "-x64", - "path": "C:\\cygwin64\\bin", - }, -] - -def buildTarget(target): - packageName = "winpty-" + common_ship.winptyVersion + "-" + target["name"] - if os.path.exists("ship\\packages\\" + packageName): - shutil.rmtree("ship\\packages\\" + packageName) - oldPath = os.environ["PATH"] - os.environ["PATH"] = target["path"] + ";" + common_ship.defaultPathEnviron - subprocess.check_call(["sh.exe", "configure"]) - makeBinary = target.get("make_binary", "make.exe") - subprocess.check_call([makeBinary, "clean"]) - makeBaseCmd = [ - makeBinary, - "USE_PCH=0", - "COMMIT_HASH=" + common_ship.commitHash, - "PREFIX=ship/packages/" + packageName - ] - subprocess.check_call(makeBaseCmd + ["all", "tests", "-j%d" % multiprocessing.cpu_count()]) - subprocess.check_call(["build\\trivial_test.exe"]) - subprocess.check_call(makeBaseCmd + ["install"]) - subprocess.check_call(["tar.exe", "cvfz", - packageName + ".tar.gz", - packageName], cwd=os.path.join(os.getcwd(), "ship", "packages")) - os.environ["PATH"] = oldPath - -def main(): - oldPath = os.environ["PATH"] - for t in BUILD_TARGETS: - os.environ["PATH"] = t["path"] + ";" + common_ship.defaultPathEnviron - subprocess.check_output(["tar.exe", "--help"]) - subprocess.check_output(["make.exe", "--help"]) - for t in BUILD_TARGETS: - buildTarget(t) - -if __name__ == "__main__": - main() diff --git a/deps/winpty/src/agent/Agent.cc b/deps/winpty/src/agent/Agent.cc deleted file mode 100644 index 4ce2a634c..000000000 --- a/deps/winpty/src/agent/Agent.cc +++ /dev/null @@ -1,613 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Agent.h" - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "../include/winpty_constants.h" - -#include "../shared/AgentMsg.h" -#include "../shared/Buffer.h" -#include "../shared/DebugClient.h" -#include "../shared/GenRandom.h" -#include "../shared/StringBuilder.h" -#include "../shared/StringUtil.h" -#include "../shared/WindowsVersion.h" -#include "../shared/WinptyAssert.h" - -#include "ConsoleFont.h" -#include "ConsoleInput.h" -#include "NamedPipe.h" -#include "Scraper.h" -#include "Terminal.h" -#include "Win32ConsoleBuffer.h" - -namespace { - -static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType) -{ - if (dwCtrlType == CTRL_C_EVENT) { - // Do nothing and claim to have handled the event. - return TRUE; - } - return FALSE; -} - -// We can detect the new Windows 10 console by observing the effect of the -// Mark command. In older consoles, Mark temporarily moves the cursor to the -// top-left of the console window. In the new console, the cursor isn't -// initially moved. -// -// We might like to use Mark to freeze the console, but we can't, because when -// the Mark command ends, the console moves the cursor back to its starting -// point, even if the console application has moved it in the meantime. -static void detectNewWindows10Console( - Win32Console &console, Win32ConsoleBuffer &buffer) -{ - if (!isAtLeastWindows8()) { - return; - } - - ConsoleScreenBufferInfo info = buffer.bufferInfo(); - - // Make sure the window isn't 1x1. AFAIK, this should never happen - // accidentally. It is difficult to make it happen deliberately. - if (info.srWindow.Left == info.srWindow.Right && - info.srWindow.Top == info.srWindow.Bottom) { - trace("detectNewWindows10Console: Initial console window was 1x1 -- " - "expanding for test"); - setSmallFont(buffer.conout(), 400, false); - buffer.moveWindow(SmallRect(0, 0, 1, 1)); - buffer.resizeBuffer(Coord(400, 1)); - buffer.moveWindow(SmallRect(0, 0, 2, 1)); - // This use of GetLargestConsoleWindowSize ought to be unnecessary - // given the behavior I've seen from moveWindow(0, 0, 1, 1), but - // I'd like to be especially sure, considering that this code will - // rarely be tested. - const auto largest = GetLargestConsoleWindowSize(buffer.conout()); - buffer.moveWindow( - SmallRect(0, 0, std::min(largest.X, buffer.bufferSize().X), 1)); - info = buffer.bufferInfo(); - ASSERT(info.srWindow.Right > info.srWindow.Left && - "Could not expand console window from 1x1"); - } - - // Test whether MARK moves the cursor. - const Coord initialPosition(info.srWindow.Right, info.srWindow.Bottom); - buffer.setCursorPosition(initialPosition); - ASSERT(!console.frozen()); - console.setFreezeUsesMark(true); - console.setFrozen(true); - const bool isNewW10 = (buffer.cursorPosition() == initialPosition); - console.setFrozen(false); - buffer.setCursorPosition(Coord(0, 0)); - - trace("Attempting to detect new Windows 10 console using MARK: %s", - isNewW10 ? "detected" : "not detected"); - console.setFreezeUsesMark(false); - console.setNewW10(isNewW10); -} - -static inline WriteBuffer newPacket() { - WriteBuffer packet; - packet.putRawValue(0); // Reserve space for size. - return packet; -} - -static HANDLE duplicateHandle(HANDLE h) { - HANDLE ret = nullptr; - if (!DuplicateHandle( - GetCurrentProcess(), h, - GetCurrentProcess(), &ret, - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - ASSERT(false && "DuplicateHandle failed!"); - } - return ret; -} - -// It's safe to truncate a handle from 64-bits to 32-bits, or to sign-extend it -// back to 64-bits. See the MSDN article, "Interprocess Communication Between -// 32-bit and 64-bit Applications". -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203.aspx -static int64_t int64FromHandle(HANDLE h) { - return static_cast(reinterpret_cast(h)); -} - -} // anonymous namespace - -Agent::Agent(LPCWSTR controlPipeName, - uint64_t agentFlags, - int mouseMode, - int initialCols, - int initialRows) : - m_useConerr((agentFlags & WINPTY_FLAG_CONERR) != 0), - m_plainMode((agentFlags & WINPTY_FLAG_PLAIN_OUTPUT) != 0), - m_mouseMode(mouseMode) -{ - trace("Agent::Agent entered"); - - ASSERT(initialCols >= 1 && initialRows >= 1); - initialCols = std::min(initialCols, MAX_CONSOLE_WIDTH); - initialRows = std::min(initialRows, MAX_CONSOLE_HEIGHT); - - const bool outputColor = - !m_plainMode || (agentFlags & WINPTY_FLAG_COLOR_ESCAPES); - const Coord initialSize(initialCols, initialRows); - - auto primaryBuffer = openPrimaryBuffer(); - if (m_useConerr) { - m_errorBuffer = Win32ConsoleBuffer::createErrorBuffer(); - } - - detectNewWindows10Console(m_console, *primaryBuffer); - - m_controlPipe = &connectToControlPipe(controlPipeName); - m_coninPipe = &createDataServerPipe(false, L"conin"); - m_conoutPipe = &createDataServerPipe(true, L"conout"); - if (m_useConerr) { - m_conerrPipe = &createDataServerPipe(true, L"conerr"); - } - - // Send an initial response packet to winpty.dll containing pipe names. - { - auto setupPacket = newPacket(); - setupPacket.putWString(m_coninPipe->name()); - setupPacket.putWString(m_conoutPipe->name()); - if (m_useConerr) { - setupPacket.putWString(m_conerrPipe->name()); - } - writePacket(setupPacket); - } - - std::unique_ptr primaryTerminal; - primaryTerminal.reset(new Terminal(*m_conoutPipe, - m_plainMode, - outputColor)); - m_primaryScraper.reset(new Scraper(m_console, - *primaryBuffer, - std::move(primaryTerminal), - initialSize)); - if (m_useConerr) { - std::unique_ptr errorTerminal; - errorTerminal.reset(new Terminal(*m_conerrPipe, - m_plainMode, - outputColor)); - m_errorScraper.reset(new Scraper(m_console, - *m_errorBuffer, - std::move(errorTerminal), - initialSize)); - } - - m_console.setTitle(m_currentTitle); - - const HANDLE conin = GetStdHandle(STD_INPUT_HANDLE); - m_consoleInput.reset( - new ConsoleInput(conin, m_mouseMode, *this, m_console)); - - // Setup Ctrl-C handling. First restore default handling of Ctrl-C. This - // attribute is inherited by child processes. Then register a custom - // Ctrl-C handler that does nothing. The handler will be called when the - // agent calls GenerateConsoleCtrlEvent. - SetConsoleCtrlHandler(NULL, FALSE); - SetConsoleCtrlHandler(consoleCtrlHandler, TRUE); - - setPollInterval(25); -} - -Agent::~Agent() -{ - trace("Agent::~Agent entered"); - try { - agentShutdown(); - if (m_childProcess != NULL) { - CloseHandle(m_childProcess); - } - } catch (const std::exception &e) { - // Log the exception or handle it as needed - trace("Exception in Agent::~Agent: %s", e.what()); - } catch (...) { - // Catch any other types of exceptions - trace("Unknown exception in Agent::~Agent"); - } -} - -// Write a "Device Status Report" command to the terminal. The terminal will -// reply with a row+col escape sequence. Presumably, the DSR reply will not -// split a keypress escape sequence, so it should be safe to assume that the -// bytes before it are complete keypresses. -void Agent::sendDsr() -{ - if (!m_plainMode && !m_conoutPipe->isClosed()) { - m_conoutPipe->write("\x1B[6n"); - } -} - -NamedPipe &Agent::connectToControlPipe(LPCWSTR pipeName) -{ - NamedPipe &pipe = createNamedPipe(); - pipe.connectToServer(pipeName, NamedPipe::OpenMode::Duplex); - pipe.setReadBufferSize(64 * 1024); - return pipe; -} - -// Returns a new server named pipe. It has not yet been connected. -NamedPipe &Agent::createDataServerPipe(bool write, const wchar_t *kind) -{ - const auto name = - (WStringBuilder(128) - << L"\\\\.\\pipe\\winpty-" - << kind << L'-' - << GenRandom().uniqueName()).str_moved(); - NamedPipe &pipe = createNamedPipe(); - pipe.openServerPipe( - name.c_str(), - write ? NamedPipe::OpenMode::Writing - : NamedPipe::OpenMode::Reading, - write ? 8192 : 0, - write ? 0 : 256); - if (!write) { - pipe.setReadBufferSize(64 * 1024); - } - return pipe; -} - -void Agent::onPipeIo(NamedPipe &namedPipe) -{ - if (&namedPipe == m_conoutPipe || &namedPipe == m_conerrPipe) { - autoClosePipesForShutdown(); - } else if (&namedPipe == m_coninPipe) { - pollConinPipe(); - } else if (&namedPipe == m_controlPipe) { - pollControlPipe(); - } -} - -void Agent::pollControlPipe() -{ - if (m_controlPipe->isClosed()) { - trace("Agent exiting (control pipe is closed)"); - shutdown(); - return; - } - - while (true) { - uint64_t packetSize = 0; - const auto amt1 = - m_controlPipe->peek(&packetSize, sizeof(packetSize)); - if (amt1 < sizeof(packetSize)) { - break; - } - ASSERT(packetSize >= sizeof(packetSize) && packetSize <= SIZE_MAX); - if (m_controlPipe->bytesAvailable() < packetSize) { - if (m_controlPipe->readBufferSize() < packetSize) { - m_controlPipe->setReadBufferSize(packetSize); - } - break; - } - std::vector packetData; - packetData.resize(packetSize); - const auto amt2 = m_controlPipe->read(packetData.data(), packetSize); - ASSERT(amt2 == packetSize); - try { - ReadBuffer buffer(std::move(packetData)); - buffer.getRawValue(); // Discard the size. - handlePacket(buffer); - } catch (const ReadBuffer::DecodeError&) { - ASSERT(false && "Decode error"); - } - } -} - -void Agent::handlePacket(ReadBuffer &packet) -{ - const int type = packet.getInt32(); - switch (type) { - case AgentMsg::StartProcess: - handleStartProcessPacket(packet); - break; - case AgentMsg::SetSize: - // TODO: I think it might make sense to collapse consecutive SetSize - // messages. i.e. The terminal process can probably generate SetSize - // messages faster than they can be processed, and some GUIs might - // generate a flood of them, so if we can read multiple SetSize packets - // at once, we can ignore the early ones. - handleSetSizePacket(packet); - break; - case AgentMsg::GetConsoleProcessList: - handleGetConsoleProcessListPacket(packet); - break; - default: - trace("Unrecognized message, id:%d", type); - } -} - -void Agent::writePacket(WriteBuffer &packet) -{ - const auto &bytes = packet.buf(); - packet.replaceRawValue(0, bytes.size()); - m_controlPipe->write(bytes.data(), bytes.size()); -} - -void Agent::handleStartProcessPacket(ReadBuffer &packet) -{ - ASSERT(m_childProcess == nullptr); - ASSERT(!m_closingOutputPipes); - - const uint64_t spawnFlags = packet.getInt64(); - const bool wantProcessHandle = packet.getInt32() != 0; - const bool wantThreadHandle = packet.getInt32() != 0; - const auto program = packet.getWString(); - const auto cmdline = packet.getWString(); - const auto cwd = packet.getWString(); - const auto env = packet.getWString(); - const auto desktop = packet.getWString(); - packet.assertEof(); - - auto cmdlineV = vectorWithNulFromString(cmdline); - auto desktopV = vectorWithNulFromString(desktop); - auto envV = vectorFromString(env); - - LPCWSTR programArg = program.empty() ? nullptr : program.c_str(); - LPWSTR cmdlineArg = cmdline.empty() ? nullptr : cmdlineV.data(); - LPCWSTR cwdArg = cwd.empty() ? nullptr : cwd.c_str(); - LPWSTR envArg = env.empty() ? nullptr : envV.data(); - - STARTUPINFOW sui = {}; - PROCESS_INFORMATION pi = {}; - sui.cb = sizeof(sui); - sui.lpDesktop = desktop.empty() ? nullptr : desktopV.data(); - BOOL inheritHandles = FALSE; - if (m_useConerr) { - inheritHandles = TRUE; - sui.dwFlags |= STARTF_USESTDHANDLES; - sui.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - sui.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - sui.hStdError = m_errorBuffer->conout(); - } - - const BOOL success = - CreateProcessW(programArg, cmdlineArg, nullptr, nullptr, - /*bInheritHandles=*/inheritHandles, - /*dwCreationFlags=*/CREATE_UNICODE_ENVIRONMENT, - envArg, cwdArg, &sui, &pi); - const int lastError = success ? 0 : GetLastError(); - - trace("CreateProcess: %s %u", - (success ? "success" : "fail"), - static_cast(pi.dwProcessId)); - - auto reply = newPacket(); - if (success) { - int64_t replyProcess = 0; - int64_t replyThread = 0; - if (wantProcessHandle) { - replyProcess = int64FromHandle(duplicateHandle(pi.hProcess)); - } - if (wantThreadHandle) { - replyThread = int64FromHandle(duplicateHandle(pi.hThread)); - } - CloseHandle(pi.hThread); - m_childProcess = pi.hProcess; - m_autoShutdown = (spawnFlags & WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN) != 0; - m_exitAfterShutdown = (spawnFlags & WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN) != 0; - reply.putInt32(static_cast(StartProcessResult::ProcessCreated)); - reply.putInt64(replyProcess); - reply.putInt64(replyThread); - } else { - reply.putInt32(static_cast(StartProcessResult::CreateProcessFailed)); - reply.putInt32(lastError); - } - writePacket(reply); -} - -void Agent::handleSetSizePacket(ReadBuffer &packet) -{ - const int cols = packet.getInt32(); - const int rows = packet.getInt32(); - packet.assertEof(); - resizeWindow(cols, rows); - auto reply = newPacket(); - writePacket(reply); -} - -void Agent::handleGetConsoleProcessListPacket(ReadBuffer &packet) -{ - packet.assertEof(); - - auto processList = std::vector(64); - auto processCount = GetConsoleProcessList(&processList[0], processList.size()); - if (processList.size() < processCount) { - processList.resize(processCount); - processCount = GetConsoleProcessList(&processList[0], processList.size()); - } - - if (processCount == 0) { - trace("GetConsoleProcessList failed"); - } - - auto reply = newPacket(); - reply.putInt32(processCount); - for (DWORD i = 0; i < processCount; i++) { - reply.putInt32(processList[i]); - } - writePacket(reply); -} - -void Agent::pollConinPipe() -{ - const std::string newData = m_coninPipe->readAllToString(); - if (hasDebugFlag("input_separated_bytes")) { - // This debug flag is intended to help with testing incomplete escape - // sequences and multibyte UTF-8 encodings. (I wonder if the normal - // code path ought to advance a state machine one byte at a time.) - for (size_t i = 0; i < newData.size(); ++i) { - m_consoleInput->writeInput(newData.substr(i, 1)); - } - } else { - m_consoleInput->writeInput(newData); - } -} - -void Agent::onPollTimeout() -{ - m_consoleInput->updateInputFlags(); - const bool enableMouseMode = m_consoleInput->shouldActivateTerminalMouse(); - - // Give the ConsoleInput object a chance to flush input from an incomplete - // escape sequence (e.g. pressing ESC). - m_consoleInput->flushIncompleteEscapeCode(); - - const bool shouldScrapeContent = !m_closingOutputPipes; - - // Check if the child process has exited. - if (m_autoShutdown && - m_childProcess != nullptr && - WaitForSingleObject(m_childProcess, 0) == WAIT_OBJECT_0) { - CloseHandle(m_childProcess); - m_childProcess = nullptr; - - // Close the data socket to signal to the client that the child - // process has exited. If there's any data left to send, send it - // before closing the socket. - m_closingOutputPipes = true; - } - - // Scrape for output *after* the above exit-check to ensure that we collect - // the child process's final output. - if (shouldScrapeContent) { - syncConsoleTitle(); - scrapeBuffers(); - } - - // We must ensure that we disable mouse mode before closing the CONOUT - // pipe, so update the mouse mode here. - m_primaryScraper->terminal().enableMouseMode( - enableMouseMode && !m_closingOutputPipes); - - autoClosePipesForShutdown(); -} - -void Agent::autoClosePipesForShutdown() -{ - if (m_closingOutputPipes) { - // We don't want to close a pipe before it's connected! If we do, the - // libwinpty client may try to connect to a non-existent pipe. This - // case is important for short-lived programs. - if (m_conoutPipe->isConnected() && - m_conoutPipe->bytesToSend() == 0) { - trace("Closing CONOUT pipe (auto-shutdown)"); - m_conoutPipe->closePipe(); - } - if (m_conerrPipe != nullptr && - m_conerrPipe->isConnected() && - m_conerrPipe->bytesToSend() == 0) { - trace("Closing CONERR pipe (auto-shutdown)"); - m_conerrPipe->closePipe(); - } - if (m_exitAfterShutdown && - m_conoutPipe->isClosed() && - (m_conerrPipe == nullptr || m_conerrPipe->isClosed())) { - trace("Agent exiting (exit-after-shutdown)"); - shutdown(); - } - } -} - -std::unique_ptr Agent::openPrimaryBuffer() -{ - // If we're using a separate buffer for stderr, and a program were to - // activate the stderr buffer, then we could accidentally scrape the same - // buffer twice. That probably shouldn't happen in ordinary use, but it - // can be avoided anyway by using the original console screen buffer in - // that mode. - if (!m_useConerr) { - return Win32ConsoleBuffer::openConout(); - } else { - return Win32ConsoleBuffer::openStdout(); - } -} - -void Agent::resizeWindow(int cols, int rows) -{ - ASSERT(cols >= 1 && rows >= 1); - cols = std::min(cols, MAX_CONSOLE_WIDTH); - rows = std::min(rows, MAX_CONSOLE_HEIGHT); - - Win32Console::FreezeGuard guard(m_console, m_console.frozen()); - const Coord newSize(cols, rows); - ConsoleScreenBufferInfo info; - auto primaryBuffer = openPrimaryBuffer(); - m_primaryScraper->resizeWindow(*primaryBuffer, newSize, info); - m_consoleInput->setMouseWindowRect(info.windowRect()); - if (m_errorScraper) { - m_errorScraper->resizeWindow(*m_errorBuffer, newSize, info); - } - - // Synthesize a WINDOW_BUFFER_SIZE_EVENT event. Normally, Windows - // generates this event only when the buffer size changes, not when the - // window size changes. This behavior is undesirable in two ways: - // - When winpty expands the window horizontally, it must expand the - // buffer first, then the window. At least some programs (e.g. the WSL - // bash.exe wrapper) use the window width rather than the buffer width, - // so there is a short timespan during which they can read the wrong - // value. - // - If the window's vertical size is changed, no event is generated, - // even though a typical well-behaved console program cares about the - // *window* height, not the *buffer* height. - // This synthesization works around a design flaw in the console. It's probably - // harmless. See https://github.com/rprichard/winpty/issues/110. - INPUT_RECORD sizeEvent {}; - sizeEvent.EventType = WINDOW_BUFFER_SIZE_EVENT; - sizeEvent.Event.WindowBufferSizeEvent.dwSize = primaryBuffer->bufferSize(); - DWORD actual {}; - WriteConsoleInputW(GetStdHandle(STD_INPUT_HANDLE), &sizeEvent, 1, &actual); -} - -void Agent::scrapeBuffers() -{ - Win32Console::FreezeGuard guard(m_console, m_console.frozen()); - ConsoleScreenBufferInfo info; - m_primaryScraper->scrapeBuffer(*openPrimaryBuffer(), info); - m_consoleInput->setMouseWindowRect(info.windowRect()); - if (m_errorScraper) { - m_errorScraper->scrapeBuffer(*m_errorBuffer, info); - } -} - -void Agent::syncConsoleTitle() -{ - std::wstring newTitle = m_console.title(); - if (newTitle != m_currentTitle) { - std::string command = std::string("\x1b]0;") + - utf8FromWide(newTitle) + "\x07"; - m_conoutPipe->write(command.c_str()); - m_currentTitle = newTitle; - } -} diff --git a/deps/winpty/src/agent/Agent.h b/deps/winpty/src/agent/Agent.h deleted file mode 100644 index 1dde48fe4..000000000 --- a/deps/winpty/src/agent/Agent.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_H -#define AGENT_H - -#include -#include - -#include -#include - -#include "DsrSender.h" -#include "EventLoop.h" -#include "Win32Console.h" - -class ConsoleInput; -class NamedPipe; -class ReadBuffer; -class Scraper; -class WriteBuffer; -class Win32ConsoleBuffer; - -class Agent : public EventLoop, public DsrSender -{ -public: - Agent(LPCWSTR controlPipeName, - uint64_t agentFlags, - int mouseMode, - int initialCols, - int initialRows); - virtual ~Agent(); - void sendDsr() override; - -private: - NamedPipe &connectToControlPipe(LPCWSTR pipeName); - NamedPipe &createDataServerPipe(bool write, const wchar_t *kind); - -private: - void pollControlPipe(); - void handlePacket(ReadBuffer &packet); - void writePacket(WriteBuffer &packet); - void handleStartProcessPacket(ReadBuffer &packet); - void handleSetSizePacket(ReadBuffer &packet); - void handleGetConsoleProcessListPacket(ReadBuffer &packet); - void pollConinPipe(); - -protected: - virtual void onPollTimeout() override; - virtual void onPipeIo(NamedPipe &namedPipe) override; - -private: - void autoClosePipesForShutdown(); - std::unique_ptr openPrimaryBuffer(); - void resizeWindow(int cols, int rows); - void scrapeBuffers(); - void syncConsoleTitle(); - -private: - const bool m_useConerr; - const bool m_plainMode; - const int m_mouseMode; - Win32Console m_console; - std::unique_ptr m_primaryScraper; - std::unique_ptr m_errorScraper; - std::unique_ptr m_errorBuffer; - NamedPipe *m_controlPipe = nullptr; - NamedPipe *m_coninPipe = nullptr; - NamedPipe *m_conoutPipe = nullptr; - NamedPipe *m_conerrPipe = nullptr; - bool m_autoShutdown = false; - bool m_exitAfterShutdown = false; - bool m_closingOutputPipes = false; - std::unique_ptr m_consoleInput; - HANDLE m_childProcess = nullptr; - - // If the title is initialized to the empty string, then cmd.exe will - // sometimes print this error: - // Not enough storage is available to process this command. - // It happens on Windows 7 when logged into a Cygwin SSH session, for - // example. Using a title of a single space character avoids the problem. - // See https://github.com/rprichard/winpty/issues/74. - std::wstring m_currentTitle = L" "; -}; - -#endif // AGENT_H diff --git a/deps/winpty/src/agent/AgentCreateDesktop.cc b/deps/winpty/src/agent/AgentCreateDesktop.cc deleted file mode 100644 index 9ad6503b1..000000000 --- a/deps/winpty/src/agent/AgentCreateDesktop.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "AgentCreateDesktop.h" - -#include "../shared/BackgroundDesktop.h" -#include "../shared/Buffer.h" -#include "../shared/DebugClient.h" -#include "../shared/StringUtil.h" - -#include "EventLoop.h" -#include "NamedPipe.h" - -namespace { - -static inline WriteBuffer newPacket() { - WriteBuffer packet; - packet.putRawValue(0); // Reserve space for size. - return packet; -} - -class CreateDesktopLoop : public EventLoop { -public: - CreateDesktopLoop(LPCWSTR controlPipeName); - -protected: - virtual void onPipeIo(NamedPipe &namedPipe) override; - -private: - void writePacket(WriteBuffer &packet); - - BackgroundDesktop m_desktop; - NamedPipe &m_pipe; -}; - -CreateDesktopLoop::CreateDesktopLoop(LPCWSTR controlPipeName) : - m_pipe(createNamedPipe()) { - m_pipe.connectToServer(controlPipeName, NamedPipe::OpenMode::Duplex); - auto packet = newPacket(); - packet.putWString(m_desktop.desktopName()); - writePacket(packet); -} - -void CreateDesktopLoop::writePacket(WriteBuffer &packet) { - const auto &bytes = packet.buf(); - packet.replaceRawValue(0, bytes.size()); - m_pipe.write(bytes.data(), bytes.size()); -} - -void CreateDesktopLoop::onPipeIo(NamedPipe &namedPipe) { - if (m_pipe.isClosed()) { - shutdown(); - } -} - -} // anonymous namespace - -void handleCreateDesktop(LPCWSTR controlPipeName) { - try { - CreateDesktopLoop loop(controlPipeName); - loop.run(); - trace("Agent exiting..."); - } catch (const WinptyException &e) { - trace("handleCreateDesktop: internal error: %s", - utf8FromWide(e.what()).c_str()); - } -} diff --git a/deps/winpty/src/agent/AgentCreateDesktop.h b/deps/winpty/src/agent/AgentCreateDesktop.h deleted file mode 100644 index 2ae539c7f..000000000 --- a/deps/winpty/src/agent/AgentCreateDesktop.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_CREATE_DESKTOP_H -#define AGENT_CREATE_DESKTOP_H - -#include - -void handleCreateDesktop(LPCWSTR controlPipeName); - -#endif // AGENT_CREATE_DESKTOP_H diff --git a/deps/winpty/src/agent/ConsoleFont.cc b/deps/winpty/src/agent/ConsoleFont.cc deleted file mode 100644 index 2e0d979a8..000000000 --- a/deps/winpty/src/agent/ConsoleFont.cc +++ /dev/null @@ -1,632 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "ConsoleFont.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../shared/DebugClient.h" -#include "../shared/OsModule.h" -#include "../shared/StringUtil.h" -#include "../shared/WindowsVersion.h" -#include "../shared/WinptyAssert.h" -#include "../shared/winpty_snprintf.h" - -namespace { - -#define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) - -// See https://en.wikipedia.org/wiki/List_of_CJK_fonts -const wchar_t kLucidaConsole[] = L"Lucida Console"; -const wchar_t kMSGothic[] = { 0xff2d, 0xff33, 0x0020, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 }; // 932, Japanese -const wchar_t kNSimSun[] = { 0x65b0, 0x5b8b, 0x4f53, 0 }; // 936, Chinese Simplified -const wchar_t kGulimChe[] = { 0xad74, 0xb9bc, 0xccb4, 0 }; // 949, Korean -const wchar_t kMingLight[] = { 0x7d30, 0x660e, 0x9ad4, 0 }; // 950, Chinese Traditional - -struct FontSize { - short size; - int width; -}; - -struct Font { - const wchar_t *faceName; - unsigned int family; - short size; -}; - -// Ideographs in East Asian languages take two columns rather than one. -// In the console screen buffer, a "full-width" character will occupy two -// cells of the buffer, the first with attribute 0x100 and the second with -// attribute 0x200. -// -// Windows does not correctly identify code points as double-width in all -// configurations. It depends heavily on the code page, the font facename, -// and (somehow) even the font size. In the 437 code page (MS-DOS), for -// example, no codepoints are interpreted as double-width. When the console -// is in an East Asian code page (932, 936, 949, or 950), then sometimes -// selecting a "Western" facename like "Lucida Console" or "Consolas" doesn't -// register, or if the font *can* be chosen, then the console doesn't handle -// double-width correctly. I tested the double-width handling by writing -// several code points with WriteConsole and checking whether one or two cells -// were filled. -// -// In the Japanese code page (932), Microsoft's default font is MS Gothic. -// MS Gothic double-width handling seems to be broken with console versions -// prior to Windows 10 (including Windows 10's legacy mode), and it's -// especially broken in Windows 8 and 8.1. -// -// Test by running: misc/Utf16Echo A2 A3 2014 3044 30FC 4000 -// -// The first three codepoints are always rendered as half-width with the -// Windows Japanese fonts. (Of these, the first two must be half-width, -// but U+2014 could be either.) The last three are rendered as full-width, -// and they are East_Asian_Width=Wide. -// -// Windows 7 fails by modeling all codepoints as full-width with font -// sizes 22 and above. -// -// Windows 8 gets U+00A2, U+00A3, U+2014, U+30FC, and U+4000 wrong, but -// using a point size not listed in the console properties dialog -// (e.g. "9") is less wrong: -// -// | code point | -// font | 00A2 00A3 2014 3044 30FC 4000 | cell size -// ------------+---------------------------------+---------- -// 8 | F F F F H H | 4x8 -// 9 | F F F F F F | 5x9 -// 16 | F F F F H H | 8x16 -// raster 6x13 | H H H F F H(*) | 6x13 -// -// (*) The Raster Font renders U+4000 as a white box (i.e. an unsupported -// character). -// - -// See: -// - misc/Font-Report-June2016 directory for per-size details -// - misc/font-notes.txt -// - misc/Utf16Echo.cc, misc/FontSurvey.cc, misc/SetFont.cc, misc/GetFont.cc - -const FontSize kLucidaFontSizes[] = { - { 5, 3 }, - { 6, 4 }, - { 8, 5 }, - { 10, 6 }, - { 12, 7 }, - { 14, 8 }, - { 16, 10 }, - { 18, 11 }, - { 20, 12 }, - { 36, 22 }, - { 48, 29 }, - { 60, 36 }, - { 72, 43 }, -}; - -// Japanese. Used on Vista and Windows 7. -const FontSize k932GothicVista[] = { - { 6, 3 }, - { 8, 4 }, - { 10, 5 }, - { 12, 6 }, - { 13, 7 }, - { 15, 8 }, - { 17, 9 }, - { 19, 10 }, - { 21, 11 }, - // All larger fonts are more broken w.r.t. full-size East Asian characters. -}; - -// Japanese. Used on Windows 8, 8.1, and the legacy 10 console. -const FontSize k932GothicWin8[] = { - // All of these characters are broken w.r.t. full-size East Asian - // characters, but they're equally broken. - { 5, 3 }, - { 7, 4 }, - { 9, 5 }, - { 11, 6 }, - { 13, 7 }, - { 15, 8 }, - { 17, 9 }, - { 20, 10 }, - { 22, 11 }, - { 24, 12 }, - // include extra-large fonts for small terminals - { 36, 18 }, - { 48, 24 }, - { 60, 30 }, - { 72, 36 }, -}; - -// Japanese. Used on the new Windows 10 console. -const FontSize k932GothicWin10[] = { - { 6, 3 }, - { 8, 4 }, - { 10, 5 }, - { 12, 6 }, - { 14, 7 }, - { 16, 8 }, - { 18, 9 }, - { 20, 10 }, - { 22, 11 }, - { 24, 12 }, - // include extra-large fonts for small terminals - { 36, 18 }, - { 48, 24 }, - { 60, 30 }, - { 72, 36 }, -}; - -// Chinese Simplified. -const FontSize k936SimSun[] = { - { 6, 3 }, - { 8, 4 }, - { 10, 5 }, - { 12, 6 }, - { 14, 7 }, - { 16, 8 }, - { 18, 9 }, - { 20, 10 }, - { 22, 11 }, - { 24, 12 }, - // include extra-large fonts for small terminals - { 36, 18 }, - { 48, 24 }, - { 60, 30 }, - { 72, 36 }, -}; - -// Korean. -const FontSize k949GulimChe[] = { - { 6, 3 }, - { 8, 4 }, - { 10, 5 }, - { 12, 6 }, - { 14, 7 }, - { 16, 8 }, - { 18, 9 }, - { 20, 10 }, - { 22, 11 }, - { 24, 12 }, - // include extra-large fonts for small terminals - { 36, 18 }, - { 48, 24 }, - { 60, 30 }, - { 72, 36 }, -}; - -// Chinese Traditional. -const FontSize k950MingLight[] = { - { 6, 3 }, - { 8, 4 }, - { 10, 5 }, - { 12, 6 }, - { 14, 7 }, - { 16, 8 }, - { 18, 9 }, - { 20, 10 }, - { 22, 11 }, - { 24, 12 }, - // include extra-large fonts for small terminals - { 36, 18 }, - { 48, 24 }, - { 60, 30 }, - { 72, 36 }, -}; - -// Some of these types and functions are missing from the MinGW headers. -// Others are undocumented. - -struct AGENT_CONSOLE_FONT_INFO { - DWORD nFont; - COORD dwFontSize; -}; - -struct AGENT_CONSOLE_FONT_INFOEX { - ULONG cbSize; - DWORD nFont; - COORD dwFontSize; - UINT FontFamily; - UINT FontWeight; - WCHAR FaceName[LF_FACESIZE]; -}; - -// undocumented XP API -typedef BOOL WINAPI SetConsoleFont_t( - HANDLE hOutput, - DWORD dwFontIndex); - -// undocumented XP API -typedef DWORD WINAPI GetNumberOfConsoleFonts_t(); - -// XP and up -typedef BOOL WINAPI GetCurrentConsoleFont_t( - HANDLE hOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont); - -// XP and up -typedef COORD WINAPI GetConsoleFontSize_t( - HANDLE hConsoleOutput, - DWORD nFont); - -// Vista and up -typedef BOOL WINAPI GetCurrentConsoleFontEx_t( - HANDLE hConsoleOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); - -// Vista and up -typedef BOOL WINAPI SetCurrentConsoleFontEx_t( - HANDLE hConsoleOutput, - BOOL bMaximumWindow, - AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); - -#define GET_MODULE_PROC(mod, funcName) \ - m_##funcName = reinterpret_cast((mod).proc(#funcName)); \ - -#define DEFINE_ACCESSOR(funcName) \ - funcName##_t &funcName() const { \ - ASSERT(valid()); \ - return *m_##funcName; \ - } - -class XPFontAPI { -public: - XPFontAPI() : m_kernel32(L"kernel32.dll") { - GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont); - GET_MODULE_PROC(m_kernel32, GetConsoleFontSize); - } - - bool valid() const { - return m_GetCurrentConsoleFont != NULL && - m_GetConsoleFontSize != NULL; - } - - DEFINE_ACCESSOR(GetCurrentConsoleFont) - DEFINE_ACCESSOR(GetConsoleFontSize) - -private: - OsModule m_kernel32; - GetCurrentConsoleFont_t *m_GetCurrentConsoleFont; - GetConsoleFontSize_t *m_GetConsoleFontSize; -}; - -class VistaFontAPI : public XPFontAPI { -public: - VistaFontAPI() : m_kernel32(L"kernel32.dll") { - GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx); - GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx); - } - - bool valid() const { - return this->XPFontAPI::valid() && - m_GetCurrentConsoleFontEx != NULL && - m_SetCurrentConsoleFontEx != NULL; - } - - DEFINE_ACCESSOR(GetCurrentConsoleFontEx) - DEFINE_ACCESSOR(SetCurrentConsoleFontEx) - -private: - OsModule m_kernel32; - GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx; - SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx; -}; - -static std::vector > readFontTable( - XPFontAPI &api, HANDLE conout, DWORD maxCount) { - std::vector > ret; - for (DWORD i = 0; i < maxCount; ++i) { - COORD size = api.GetConsoleFontSize()(conout, i); - if (size.X == 0 && size.Y == 0) { - break; - } - ret.push_back(std::make_pair(i, size)); - } - return ret; -} - -static void dumpFontTable(HANDLE conout, const char *prefix) { - const int kMaxCount = 1000; - if (!isTracingEnabled()) { - return; - } - XPFontAPI api; - if (!api.valid()) { - trace("dumpFontTable: cannot dump font table -- missing APIs"); - return; - } - std::vector > table = - readFontTable(api, conout, kMaxCount); - std::string line; - char tmp[128]; - size_t first = 0; - while (first < table.size()) { - size_t last = std::min(table.size() - 1, first + 10 - 1); - winpty_snprintf(tmp, "%sfonts %02u-%02u:", - prefix, static_cast(first), static_cast(last)); - line = tmp; - for (size_t i = first; i <= last; ++i) { - if (i % 10 == 5) { - line += " - "; - } - winpty_snprintf(tmp, " %2dx%-2d", - table[i].second.X, table[i].second.Y); - line += tmp; - } - trace("%s", line.c_str()); - first = last + 1; - } - if (table.size() == kMaxCount) { - trace("%sfonts: ... stopped reading at %d fonts ...", - prefix, kMaxCount); - } -} - -static std::string stringToCodePoints(const std::wstring &str) { - std::string ret = "("; - for (size_t i = 0; i < str.size(); ++i) { - char tmp[32]; - winpty_snprintf(tmp, "%X", str[i]); - if (ret.size() > 1) { - ret.push_back(' '); - } - ret += tmp; - } - ret.push_back(')'); - return ret; -} - -static void dumpFontInfoEx( - const AGENT_CONSOLE_FONT_INFOEX &infoex, - const char *prefix) { - if (!isTracingEnabled()) { - return; - } - std::wstring faceName(infoex.FaceName, - winpty_wcsnlen(infoex.FaceName, COUNT_OF(infoex.FaceName))); - trace("%snFont=%u dwFontSize=(%d,%d) " - "FontFamily=0x%x FontWeight=%u FaceName=%s %s", - prefix, - static_cast(infoex.nFont), - infoex.dwFontSize.X, infoex.dwFontSize.Y, - infoex.FontFamily, infoex.FontWeight, utf8FromWide(faceName).c_str(), - stringToCodePoints(faceName).c_str()); -} - -static void dumpVistaFont(VistaFontAPI &api, HANDLE conout, const char *prefix) { - if (!isTracingEnabled()) { - return; - } - AGENT_CONSOLE_FONT_INFOEX infoex = {0}; - infoex.cbSize = sizeof(infoex); - if (!api.GetCurrentConsoleFontEx()(conout, FALSE, &infoex)) { - trace("GetCurrentConsoleFontEx call failed"); - return; - } - dumpFontInfoEx(infoex, prefix); -} - -static void dumpXPFont(XPFontAPI &api, HANDLE conout, const char *prefix) { - if (!isTracingEnabled()) { - return; - } - AGENT_CONSOLE_FONT_INFO info = {0}; - if (!api.GetCurrentConsoleFont()(conout, FALSE, &info)) { - trace("GetCurrentConsoleFont call failed"); - return; - } - trace("%snFont=%u dwFontSize=(%d,%d)", - prefix, - static_cast(info.nFont), - info.dwFontSize.X, info.dwFontSize.Y); -} - -static bool setFontVista( - VistaFontAPI &api, - HANDLE conout, - const Font &font) { - AGENT_CONSOLE_FONT_INFOEX infoex = {}; - infoex.cbSize = sizeof(AGENT_CONSOLE_FONT_INFOEX); - infoex.dwFontSize.Y = font.size; - infoex.FontFamily = font.family; - infoex.FontWeight = 400; - winpty_wcsncpy_nul(infoex.FaceName, font.faceName); - dumpFontInfoEx(infoex, "setFontVista: setting font to: "); - if (!api.SetCurrentConsoleFontEx()(conout, FALSE, &infoex)) { - trace("setFontVista: SetCurrentConsoleFontEx call failed"); - return false; - } - memset(&infoex, 0, sizeof(infoex)); - infoex.cbSize = sizeof(infoex); - if (!api.GetCurrentConsoleFontEx()(conout, FALSE, &infoex)) { - trace("setFontVista: GetCurrentConsoleFontEx call failed"); - return false; - } - if (wcsncmp(infoex.FaceName, font.faceName, - COUNT_OF(infoex.FaceName)) != 0) { - trace("setFontVista: face name was not set"); - dumpFontInfoEx(infoex, "setFontVista: post-call font: "); - return false; - } - // We'd like to verify that the new font size is correct, but we can't - // predict what it will be, even though we just set it to `pxSize` through - // an apprently symmetric interface. For the Chinese and Korean fonts, the - // new `infoex.dwFontSize.Y` value can be slightly larger than the height - // we specified. - return true; -} - -static Font selectSmallFont(int codePage, int columns, bool isNewW10) { - // Iterate over a set of font sizes according to the code page, and select - // one. - - const wchar_t *faceName = nullptr; - unsigned int fontFamily = 0; - const FontSize *table = nullptr; - size_t tableSize = 0; - - switch (codePage) { - case 932: // Japanese - faceName = kMSGothic; - fontFamily = 0x36; - if (isNewW10) { - table = k932GothicWin10; - tableSize = COUNT_OF(k932GothicWin10); - } else if (isAtLeastWindows8()) { - table = k932GothicWin8; - tableSize = COUNT_OF(k932GothicWin8); - } else { - table = k932GothicVista; - tableSize = COUNT_OF(k932GothicVista); - } - break; - case 936: // Chinese Simplified - faceName = kNSimSun; - fontFamily = 0x36; - table = k936SimSun; - tableSize = COUNT_OF(k936SimSun); - break; - case 949: // Korean - faceName = kGulimChe; - fontFamily = 0x36; - table = k949GulimChe; - tableSize = COUNT_OF(k949GulimChe); - break; - case 950: // Chinese Traditional - faceName = kMingLight; - fontFamily = 0x36; - table = k950MingLight; - tableSize = COUNT_OF(k950MingLight); - break; - default: - faceName = kLucidaConsole; - fontFamily = 0x36; - table = kLucidaFontSizes; - tableSize = COUNT_OF(kLucidaFontSizes); - break; - } - - size_t bestIndex = static_cast(-1); - std::tuple bestScore = std::make_tuple(-1, -1); - - // We might want to pick the smallest possible font, because we don't know - // how large the monitor is (and the monitor size can change). We might - // want to pick a larger font to accommodate console programs that resize - // the console on their own, like DOS edit.com, which tends to resize the - // console to 80 columns. - - for (size_t i = 0; i < tableSize; ++i) { - const int width = table[i].width * columns; - - // In general, we'd like to pick a font size where cutting the number - // of columns in half doesn't immediately violate the minimum width - // constraint. (e.g. To run DOS edit.com, a user might resize their - // terminal to ~100 columns so it's big enough to show the 80 columns - // post-resize.) To achieve this, give priority to fonts that allow - // this halving. We don't want to encourage *very* large fonts, - // though, so disable the effect as the number of columns scales from - // 80 to 40. - const int halfColumns = std::min(columns, std::max(40, columns / 2)); - const int halfWidth = table[i].width * halfColumns; - - std::tuple thisScore = std::make_tuple(-1, -1); - if (width >= 160 && halfWidth >= 160) { - // Both sizes are good. Prefer the smaller fonts. - thisScore = std::make_tuple(2, -width); - } else if (width >= 160) { - // Prefer the smaller fonts. - thisScore = std::make_tuple(1, -width); - } else { - // Otherwise, prefer the largest font in our table. - thisScore = std::make_tuple(0, width); - } - if (thisScore > bestScore) { - bestIndex = i; - bestScore = thisScore; - } - } - - ASSERT(bestIndex != static_cast(-1)); - return Font { faceName, fontFamily, table[bestIndex].size }; -} - -static void setSmallFontVista(VistaFontAPI &api, HANDLE conout, - int columns, bool isNewW10) { - int codePage = GetConsoleOutputCP(); - const auto font = selectSmallFont(codePage, columns, isNewW10); - if (setFontVista(api, conout, font)) { - trace("setSmallFontVista: success"); - return; - } - if (codePage == 932 || codePage == 936 || - codePage == 949 || codePage == 950) { - trace("setSmallFontVista: falling back to default codepage font instead"); - const auto fontFB = selectSmallFont(0, columns, isNewW10); - if (setFontVista(api, conout, fontFB)) { - trace("setSmallFontVista: fallback was successful"); - return; - } - } - trace("setSmallFontVista: failure"); -} - -struct FontSizeComparator { - bool operator()(const std::pair &obj1, - const std::pair &obj2) const { - int score1 = obj1.second.X + obj1.second.Y; - int score2 = obj2.second.X + obj2.second.Y; - return score1 < score2; - } -}; - -} // anonymous namespace - -// A Windows console window can never be larger than the desktop window. To -// maximize the possible size of the console in rows*cols, try to configure -// the console with a small font. Unfortunately, we cannot make the font *too* -// small, because there is also a minimum window size in pixels. -void setSmallFont(HANDLE conout, int columns, bool isNewW10) { - trace("setSmallFont: attempting to set a small font for %d columns " - "(CP=%u OutputCP=%u)", - columns, - static_cast(GetConsoleCP()), - static_cast(GetConsoleOutputCP())); - VistaFontAPI vista; - if (vista.valid()) { - dumpVistaFont(vista, conout, "previous font: "); - dumpFontTable(conout, "previous font table: "); - setSmallFontVista(vista, conout, columns, isNewW10); - dumpVistaFont(vista, conout, "new font: "); - dumpFontTable(conout, "new font table: "); - return; - } - trace("setSmallFont: neither Vista nor XP APIs detected -- giving up"); - dumpFontTable(conout, "font table: "); -} diff --git a/deps/winpty/src/agent/ConsoleFont.h b/deps/winpty/src/agent/ConsoleFont.h deleted file mode 100644 index 99cb10698..000000000 --- a/deps/winpty/src/agent/ConsoleFont.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef CONSOLEFONT_H -#define CONSOLEFONT_H - -#include - -void setSmallFont(HANDLE conout, int columns, bool isNewW10); - -#endif // CONSOLEFONT_H diff --git a/deps/winpty/src/agent/ConsoleInput.cc b/deps/winpty/src/agent/ConsoleInput.cc deleted file mode 100644 index 192cac2a2..000000000 --- a/deps/winpty/src/agent/ConsoleInput.cc +++ /dev/null @@ -1,852 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "ConsoleInput.h" - -#include -#include - -#include -#include - -#include "../include/winpty_constants.h" - -#include "../shared/DebugClient.h" -#include "../shared/StringBuilder.h" -#include "../shared/UnixCtrlChars.h" - -#include "ConsoleInputReencoding.h" -#include "DebugShowInput.h" -#include "DefaultInputMap.h" -#include "DsrSender.h" -#include "UnicodeEncoding.h" -#include "Win32Console.h" - -// MAPVK_VK_TO_VSC isn't defined by the old MinGW. -#ifndef MAPVK_VK_TO_VSC -#define MAPVK_VK_TO_VSC 0 -#endif - -namespace { - -struct MouseRecord { - bool release; - int flags; - COORD coord; - - std::string toString() const; -}; - -std::string MouseRecord::toString() const { - StringBuilder sb(40); - sb << "pos=" << coord.X << ',' << coord.Y - << " flags=0x" << hexOfInt(flags); - if (release) { - sb << " release"; - } - return sb.str_moved(); -} - -const unsigned int kIncompleteEscapeTimeoutMs = 1000u; - -#define CHECK(cond) \ - do { \ - if (!(cond)) { return 0; } \ - } while(0) - -#define ADVANCE() \ - do { \ - pch++; \ - if (pch == stop) { return -1; } \ - } while(0) - -#define SCAN_INT(out, maxLen) \ - do { \ - (out) = 0; \ - CHECK(isdigit(*pch)); \ - const char *begin = pch; \ - do { \ - CHECK(pch - begin + 1 < maxLen); \ - (out) = (out) * 10 + *pch - '0'; \ - ADVANCE(); \ - } while (isdigit(*pch)); \ - } while(0) - -#define SCAN_SIGNED_INT(out, maxLen) \ - do { \ - bool negative = false; \ - if (*pch == '-') { \ - negative = true; \ - ADVANCE(); \ - } \ - SCAN_INT(out, maxLen); \ - if (negative) { \ - (out) = -(out); \ - } \ - } while(0) - -// Match the Device Status Report console input: ESC [ nn ; mm R -// Returns: -// 0 no match -// >0 match, returns length of match -// -1 incomplete match -static int matchDsr(const char *input, int inputSize) -{ - int32_t dummy = 0; - const char *pch = input; - const char *stop = input + inputSize; - CHECK(*pch == '\x1B'); ADVANCE(); - CHECK(*pch == '['); ADVANCE(); - SCAN_INT(dummy, 8); - CHECK(*pch == ';'); ADVANCE(); - SCAN_INT(dummy, 8); - CHECK(*pch == 'R'); - return pch - input + 1; -} - -static int matchMouseDefault(const char *input, int inputSize, - MouseRecord &out) -{ - const char *pch = input; - const char *stop = input + inputSize; - CHECK(*pch == '\x1B'); ADVANCE(); - CHECK(*pch == '['); ADVANCE(); - CHECK(*pch == 'M'); ADVANCE(); - out.flags = (*pch - 32) & 0xFF; ADVANCE(); - out.coord.X = (*pch - '!') & 0xFF; - ADVANCE(); - out.coord.Y = (*pch - '!') & 0xFF; - out.release = false; - return pch - input + 1; -} - -static int matchMouse1006(const char *input, int inputSize, MouseRecord &out) -{ - const char *pch = input; - const char *stop = input + inputSize; - int32_t temp; - CHECK(*pch == '\x1B'); ADVANCE(); - CHECK(*pch == '['); ADVANCE(); - CHECK(*pch == '<'); ADVANCE(); - SCAN_INT(out.flags, 8); - CHECK(*pch == ';'); ADVANCE(); - SCAN_SIGNED_INT(temp, 8); out.coord.X = temp - 1; - CHECK(*pch == ';'); ADVANCE(); - SCAN_SIGNED_INT(temp, 8); out.coord.Y = temp - 1; - CHECK(*pch == 'M' || *pch == 'm'); - out.release = (*pch == 'm'); - return pch - input + 1; -} - -static int matchMouse1015(const char *input, int inputSize, MouseRecord &out) -{ - const char *pch = input; - const char *stop = input + inputSize; - int32_t temp; - CHECK(*pch == '\x1B'); ADVANCE(); - CHECK(*pch == '['); ADVANCE(); - SCAN_INT(out.flags, 8); out.flags -= 32; - CHECK(*pch == ';'); ADVANCE(); - SCAN_SIGNED_INT(temp, 8); out.coord.X = temp - 1; - CHECK(*pch == ';'); ADVANCE(); - SCAN_SIGNED_INT(temp, 8); out.coord.Y = temp - 1; - CHECK(*pch == 'M'); - out.release = false; - return pch - input + 1; -} - -// Match a mouse input escape sequence of any kind. -// 0 no match -// >0 match, returns length of match -// -1 incomplete match -static int matchMouseRecord(const char *input, int inputSize, MouseRecord &out) -{ - memset(&out, 0, sizeof(out)); - int ret; - if ((ret = matchMouse1006(input, inputSize, out)) != 0) { return ret; } - if ((ret = matchMouse1015(input, inputSize, out)) != 0) { return ret; } - if ((ret = matchMouseDefault(input, inputSize, out)) != 0) { return ret; } - return 0; -} - -#undef CHECK -#undef ADVANCE -#undef SCAN_INT - -} // anonymous namespace - -ConsoleInput::ConsoleInput(HANDLE conin, int mouseMode, DsrSender &dsrSender, - Win32Console &console) : - m_console(console), - m_conin(conin), - m_mouseMode(mouseMode), - m_dsrSender(dsrSender) -{ - addDefaultEntriesToInputMap(m_inputMap); - if (hasDebugFlag("dump_input_map")) { - m_inputMap.dumpInputMap(); - } - - // Configure Quick Edit mode according to the mouse mode. Enable - // InsertMode for two reasons: - // - If it's OFF, it's difficult for the user to turn it ON. The - // properties dialog is inaccesible. winpty still faithfully handles - // the Insert key, which toggles between the insertion and overwrite - // modes. - // - When we modify the QuickEdit setting, if ExtendedFlags is OFF, - // then we must choose the InsertMode setting. I don't *think* this - // case happens, though, because a new console always has ExtendedFlags - // ON. - // See misc/EnableExtendedFlags.txt. - DWORD mode = 0; - if (!GetConsoleMode(conin, &mode)) { - trace("Agent startup: GetConsoleMode failed"); - } else { - mode |= ENABLE_EXTENDED_FLAGS; - mode |= ENABLE_INSERT_MODE; - if (m_mouseMode == WINPTY_MOUSE_MODE_AUTO) { - mode |= ENABLE_QUICK_EDIT_MODE; - } else { - mode &= ~ENABLE_QUICK_EDIT_MODE; - } - if (!SetConsoleMode(conin, mode)) { - trace("Agent startup: SetConsoleMode failed"); - } - } - - updateInputFlags(true); -} - -void ConsoleInput::writeInput(const std::string &input) -{ - if (input.size() == 0) { - return; - } - - if (isTracingEnabled()) { - static bool debugInput = hasDebugFlag("input"); - if (debugInput) { - std::string dumpString; - for (size_t i = 0; i < input.size(); ++i) { - const char ch = input[i]; - const char ctrl = decodeUnixCtrlChar(ch); - if (ctrl != '\0') { - dumpString += '^'; - dumpString += ctrl; - } else { - dumpString += ch; - } - } - dumpString += " ("; - for (size_t i = 0; i < input.size(); ++i) { - if (i > 0) { - dumpString += ' '; - } - const unsigned char uch = input[i]; - char buf[32]; - winpty_snprintf(buf, "%02X", uch); - dumpString += buf; - } - dumpString += ')'; - trace("input chars: %s", dumpString.c_str()); - } - } - - m_byteQueue.append(input); - doWrite(false); - if (!m_byteQueue.empty() && !m_dsrSent) { - trace("send DSR"); - m_dsrSender.sendDsr(); - m_dsrSent = true; - } - m_lastWriteTick = GetTickCount(); -} - -void ConsoleInput::flushIncompleteEscapeCode() -{ - if (!m_byteQueue.empty() && - (GetTickCount() - m_lastWriteTick) > kIncompleteEscapeTimeoutMs) { - doWrite(true); - m_byteQueue.clear(); - } -} - -void ConsoleInput::updateInputFlags(bool forceTrace) -{ - const DWORD mode = inputConsoleMode(); - const bool newFlagEE = (mode & ENABLE_EXTENDED_FLAGS) != 0; - const bool newFlagMI = (mode & ENABLE_MOUSE_INPUT) != 0; - const bool newFlagQE = (mode & ENABLE_QUICK_EDIT_MODE) != 0; - const bool newFlagEI = (mode & 0x200) != 0; - if (forceTrace || - newFlagEE != m_enableExtendedEnabled || - newFlagMI != m_mouseInputEnabled || - newFlagQE != m_quickEditEnabled || - newFlagEI != m_escapeInputEnabled) { - trace("CONIN modes: Extended=%s, MouseInput=%s QuickEdit=%s EscapeInput=%s", - newFlagEE ? "on" : "off", - newFlagMI ? "on" : "off", - newFlagQE ? "on" : "off", - newFlagEI ? "on" : "off"); - } - m_enableExtendedEnabled = newFlagEE; - m_mouseInputEnabled = newFlagMI; - m_quickEditEnabled = newFlagQE; - m_escapeInputEnabled = newFlagEI; -} - -bool ConsoleInput::shouldActivateTerminalMouse() -{ - // Return whether the agent should activate the terminal's mouse mode. - if (m_mouseMode == WINPTY_MOUSE_MODE_AUTO) { - // Some programs (e.g. Cygwin command-line programs like bash.exe and - // python2.7.exe) turn off ENABLE_EXTENDED_FLAGS and turn on - // ENABLE_MOUSE_INPUT, but do not turn off QuickEdit mode and do not - // actually care about mouse input. Only enable the terminal mouse - // mode if ENABLE_EXTENDED_FLAGS is on. See - // misc/EnableExtendedFlags.txt. - return m_mouseInputEnabled && !m_quickEditEnabled && - m_enableExtendedEnabled; - } else if (m_mouseMode == WINPTY_MOUSE_MODE_FORCE) { - return true; - } else { - return false; - } -} - -void ConsoleInput::doWrite(bool isEof) -{ - const char *data = m_byteQueue.c_str(); - std::vector records; - size_t idx = 0; - while (idx < m_byteQueue.size()) { - int charSize = scanInput(records, &data[idx], m_byteQueue.size() - idx, isEof); - if (charSize == -1) - break; - idx += charSize; - } - m_byteQueue.erase(0, idx); - flushInputRecords(records); -} - -void ConsoleInput::flushInputRecords(std::vector &records) -{ - if (records.size() == 0) { - return; - } - DWORD actual = 0; - if (!WriteConsoleInputW(m_conin, records.data(), records.size(), &actual)) { - trace("WriteConsoleInputW failed"); - } - records.clear(); -} - -// This behavior isn't strictly correct, because the keypresses (probably?) -// adopt the keyboard state (e.g. Ctrl/Alt/Shift modifiers) of the current -// window station's keyboard, which has no necessary relationship to the winpty -// instance. It's unlikely to be an issue in practice, but it's conceivable. -// (Imagine a foreground SSH server, where the local user holds down Ctrl, -// while the remote user tries to use WSL navigation keys.) I suspect using -// the BackgroundDesktop mechanism in winpty would fix the problem. -// -// https://github.com/rprichard/winpty/issues/116 -static void sendKeyMessage(HWND hwnd, bool isKeyDown, uint16_t virtualKey) -{ - uint32_t scanCode = MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC); - if (scanCode > 255) { - scanCode = 0; - } - SendMessage(hwnd, isKeyDown ? WM_KEYDOWN : WM_KEYUP, virtualKey, - (scanCode << 16) | 1u | (isKeyDown ? 0u : 0xc0000000u)); -} - -int ConsoleInput::scanInput(std::vector &records, - const char *input, - int inputSize, - bool isEof) -{ - ASSERT(inputSize >= 1); - - // Ctrl-C. - // - // In processed mode, use GenerateConsoleCtrlEvent so that Ctrl-C handlers - // are called. GenerateConsoleCtrlEvent unfortunately doesn't interrupt - // ReadConsole calls[1]. Using WM_KEYDOWN/UP fixes the ReadConsole - // problem, but breaks in background window stations/desktops. - // - // In unprocessed mode, there's an entry for Ctrl-C in the SimpleEncoding - // table in DefaultInputMap. - // - // [1] https://github.com/rprichard/winpty/issues/116 - if (input[0] == '\x03' && (inputConsoleMode() & ENABLE_PROCESSED_INPUT)) { - flushInputRecords(records); - trace("Ctrl-C"); - const BOOL ret = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - trace("GenerateConsoleCtrlEvent: %d", ret); - return 1; - } - - if (input[0] == '\x1B') { - // Attempt to match the Device Status Report (DSR) reply. - int dsrLen = matchDsr(input, inputSize); - if (dsrLen > 0) { - trace("Received a DSR reply"); - m_dsrSent = false; - return dsrLen; - } else if (!isEof && dsrLen == -1) { - // Incomplete DSR match. - trace("Incomplete DSR match"); - return -1; - } - - int mouseLen = scanMouseInput(records, input, inputSize); - if (mouseLen > 0 || (!isEof && mouseLen == -1)) { - return mouseLen; - } - } - - // Search the input map. - InputMap::Key match; - bool incomplete; - int matchLen = m_inputMap.lookupKey(input, inputSize, match, incomplete); - if (!isEof && incomplete) { - // Incomplete match -- need more characters (or wait for a - // timeout to signify flushed input). - trace("Incomplete escape sequence"); - return -1; - } else if (matchLen > 0) { - uint32_t winCodePointDn = match.unicodeChar; - if ((match.keyState & LEFT_CTRL_PRESSED) && (match.keyState & LEFT_ALT_PRESSED)) { - winCodePointDn = '\0'; - } - uint32_t winCodePointUp = winCodePointDn; - if (match.keyState & LEFT_ALT_PRESSED) { - winCodePointUp = '\0'; - } - appendKeyPress(records, match.virtualKey, - winCodePointDn, winCodePointUp, match.keyState, - match.unicodeChar, match.keyState); - return matchLen; - } - - // Recognize Alt-. - // - // This code doesn't match Alt-ESC, which is encoded as `ESC ESC`, but - // maybe it should. I was concerned that pressing ESC rapidly enough could - // accidentally trigger Alt-ESC. (e.g. The user would have to be faster - // than the DSR flushing mechanism or use a decrepit terminal. The user - // might be on a slow network connection.) - if (input[0] == '\x1B' && inputSize >= 2 && input[1] != '\x1B') { - const int len = utf8CharLength(input[1]); - if (len > 0) { - if (1 + len > inputSize) { - // Incomplete character. - trace("Incomplete UTF-8 character in Alt-"); - return -1; - } - appendUtf8Char(records, &input[1], len, true); - return 1 + len; - } - } - - // A UTF-8 character. - const int len = utf8CharLength(input[0]); - if (len == 0) { - static bool debugInput = isTracingEnabled() && hasDebugFlag("input"); - if (debugInput) { - trace("Discarding invalid input byte: %02X", - static_cast(input[0])); - } - return 1; - } - if (len > inputSize) { - // Incomplete character. - trace("Incomplete UTF-8 character"); - return -1; - } - appendUtf8Char(records, &input[0], len, false); - return len; -} - -int ConsoleInput::scanMouseInput(std::vector &records, - const char *input, - int inputSize) -{ - MouseRecord record; - const int len = matchMouseRecord(input, inputSize, record); - if (len <= 0) { - return len; - } - - if (isTracingEnabled()) { - static bool debugInput = hasDebugFlag("input"); - if (debugInput) { - trace("mouse input: %s", record.toString().c_str()); - } - } - - const int button = record.flags & 0x03; - INPUT_RECORD newRecord = {0}; - newRecord.EventType = MOUSE_EVENT; - MOUSE_EVENT_RECORD &mer = newRecord.Event.MouseEvent; - - mer.dwMousePosition.X = - m_mouseWindowRect.Left + - std::max(0, std::min(record.coord.X, - m_mouseWindowRect.width() - 1)); - - mer.dwMousePosition.Y = - m_mouseWindowRect.Top + - std::max(0, std::min(record.coord.Y, - m_mouseWindowRect.height() - 1)); - - // The modifier state is neatly independent of everything else. - if (record.flags & 0x04) { mer.dwControlKeyState |= SHIFT_PRESSED; } - if (record.flags & 0x08) { mer.dwControlKeyState |= LEFT_ALT_PRESSED; } - if (record.flags & 0x10) { mer.dwControlKeyState |= LEFT_CTRL_PRESSED; } - - if (record.flags & 0x40) { - // Mouse wheel - mer.dwEventFlags |= MOUSE_WHEELED; - if (button == 0) { - // up - mer.dwButtonState |= 0x00780000; - } else if (button == 1) { - // down - mer.dwButtonState |= 0xff880000; - } else { - // Invalid -- do nothing - return len; - } - } else { - // Ordinary mouse event - if (record.flags & 0x20) { mer.dwEventFlags |= MOUSE_MOVED; } - if (button == 3) { - m_mouseButtonState = 0; - // Potentially advance double-click detection. - m_doubleClick.released = true; - } else { - const DWORD relevantFlag = - (button == 0) ? FROM_LEFT_1ST_BUTTON_PRESSED : - (button == 1) ? FROM_LEFT_2ND_BUTTON_PRESSED : - (button == 2) ? RIGHTMOST_BUTTON_PRESSED : - 0; - ASSERT(relevantFlag != 0); - if (record.release) { - m_mouseButtonState &= ~relevantFlag; - if (relevantFlag == m_doubleClick.button) { - // Potentially advance double-click detection. - m_doubleClick.released = true; - } else { - // End double-click detection. - m_doubleClick = DoubleClickDetection(); - } - } else if ((m_mouseButtonState & relevantFlag) == 0) { - // The button has been newly pressed. - m_mouseButtonState |= relevantFlag; - // Detect a double-click. This code looks for an exact - // coordinate match, which is stricter than what Windows does, - // but Windows has pixel coordinates, and we only have terminal - // coordinates. - if (m_doubleClick.button == relevantFlag && - m_doubleClick.pos == record.coord && - (GetTickCount() - m_doubleClick.tick < - GetDoubleClickTime())) { - // Record a double-click and end double-click detection. - mer.dwEventFlags |= DOUBLE_CLICK; - m_doubleClick = DoubleClickDetection(); - } else { - // Begin double-click detection. - m_doubleClick.button = relevantFlag; - m_doubleClick.pos = record.coord; - m_doubleClick.tick = GetTickCount(); - } - } - } - } - - mer.dwButtonState |= m_mouseButtonState; - - if (m_mouseInputEnabled && !m_quickEditEnabled) { - if (isTracingEnabled()) { - static bool debugInput = hasDebugFlag("input"); - if (debugInput) { - trace("mouse event: %s", mouseEventToString(mer).c_str()); - } - } - - records.push_back(newRecord); - } - - return len; -} - -void ConsoleInput::appendUtf8Char(std::vector &records, - const char *charBuffer, - const int charLen, - const bool terminalAltEscape) -{ - const uint32_t codePoint = decodeUtf8(charBuffer); - if (codePoint == static_cast(-1)) { - static bool debugInput = isTracingEnabled() && hasDebugFlag("input"); - if (debugInput) { - StringBuilder error(64); - error << "Discarding invalid UTF-8 sequence:"; - for (int i = 0; i < charLen; ++i) { - error << ' '; - error << hexOfInt(charBuffer[i]); - } - trace("%s", error.c_str()); - } - return; - } - - const short charScan = codePoint > 0xFFFF ? -1 : VkKeyScan(codePoint); - uint16_t virtualKey = 0; - uint16_t winKeyState = 0; - uint32_t winCodePointDn = codePoint; - uint32_t winCodePointUp = codePoint; - uint16_t vtKeyState = 0; - - if (charScan != -1) { - virtualKey = charScan & 0xFF; - if (charScan & 0x100) { - winKeyState |= SHIFT_PRESSED; - } - if (charScan & 0x200) { - winKeyState |= LEFT_CTRL_PRESSED; - } - if (charScan & 0x400) { - winKeyState |= RIGHT_ALT_PRESSED; - } - if (terminalAltEscape && (winKeyState & LEFT_CTRL_PRESSED)) { - // If the terminal escapes a Ctrl- with Alt, then set the - // codepoint to 0. On the other hand, if a character requires - // AltGr (like U+00B2 on a German layout), then VkKeyScan will - // report both Ctrl and Alt pressed, and we should keep the - // codepoint. See https://github.com/rprichard/winpty/issues/109. - winCodePointDn = 0; - winCodePointUp = 0; - } - } - if (terminalAltEscape) { - winCodePointUp = 0; - winKeyState |= LEFT_ALT_PRESSED; - vtKeyState |= LEFT_ALT_PRESSED; - } - - appendKeyPress(records, virtualKey, - winCodePointDn, winCodePointUp, winKeyState, - codePoint, vtKeyState); -} - -void ConsoleInput::appendKeyPress(std::vector &records, - const uint16_t virtualKey, - const uint32_t winCodePointDn, - const uint32_t winCodePointUp, - const uint16_t winKeyState, - const uint32_t vtCodePoint, - const uint16_t vtKeyState) -{ - const bool ctrl = (winKeyState & LEFT_CTRL_PRESSED) != 0; - const bool leftAlt = (winKeyState & LEFT_ALT_PRESSED) != 0; - const bool rightAlt = (winKeyState & RIGHT_ALT_PRESSED) != 0; - const bool shift = (winKeyState & SHIFT_PRESSED) != 0; - const bool enhanced = (winKeyState & ENHANCED_KEY) != 0; - bool hasDebugInput = false; - - if (isTracingEnabled()) { - static bool debugInput = hasDebugFlag("input"); - if (debugInput) { - hasDebugInput = true; - InputMap::Key key = { virtualKey, winCodePointDn, winKeyState }; - trace("keypress: %s", key.toString().c_str()); - } - } - - if (m_escapeInputEnabled && - (virtualKey == VK_UP || - virtualKey == VK_DOWN || - virtualKey == VK_LEFT || - virtualKey == VK_RIGHT || - virtualKey == VK_HOME || - virtualKey == VK_END) && - !ctrl && !leftAlt && !rightAlt && !shift) { - flushInputRecords(records); - if (hasDebugInput) { - trace("sending keypress to console HWND"); - } - sendKeyMessage(m_console.hwnd(), true, virtualKey); - sendKeyMessage(m_console.hwnd(), false, virtualKey); - return; - } - - uint16_t stepKeyState = 0; - if (ctrl) { - stepKeyState |= LEFT_CTRL_PRESSED; - appendInputRecord(records, TRUE, VK_CONTROL, 0, stepKeyState); - } - if (leftAlt) { - stepKeyState |= LEFT_ALT_PRESSED; - appendInputRecord(records, TRUE, VK_MENU, 0, stepKeyState); - } - if (rightAlt) { - stepKeyState |= RIGHT_ALT_PRESSED; - appendInputRecord(records, TRUE, VK_MENU, 0, stepKeyState | ENHANCED_KEY); - } - if (shift) { - stepKeyState |= SHIFT_PRESSED; - appendInputRecord(records, TRUE, VK_SHIFT, 0, stepKeyState); - } - if (enhanced) { - stepKeyState |= ENHANCED_KEY; - } - if (m_escapeInputEnabled) { - reencodeEscapedKeyPress(records, virtualKey, vtCodePoint, vtKeyState); - } else { - appendCPInputRecords(records, TRUE, virtualKey, winCodePointDn, stepKeyState); - } - appendCPInputRecords(records, FALSE, virtualKey, winCodePointUp, stepKeyState); - if (enhanced) { - stepKeyState &= ~ENHANCED_KEY; - } - if (shift) { - stepKeyState &= ~SHIFT_PRESSED; - appendInputRecord(records, FALSE, VK_SHIFT, 0, stepKeyState); - } - if (rightAlt) { - stepKeyState &= ~RIGHT_ALT_PRESSED; - appendInputRecord(records, FALSE, VK_MENU, 0, stepKeyState | ENHANCED_KEY); - } - if (leftAlt) { - stepKeyState &= ~LEFT_ALT_PRESSED; - appendInputRecord(records, FALSE, VK_MENU, 0, stepKeyState); - } - if (ctrl) { - stepKeyState &= ~LEFT_CTRL_PRESSED; - appendInputRecord(records, FALSE, VK_CONTROL, 0, stepKeyState); - } -} - -void ConsoleInput::appendCPInputRecords(std::vector &records, - BOOL keyDown, - uint16_t virtualKey, - uint32_t codePoint, - uint16_t keyState) -{ - // This behavior really doesn't match that of the Windows console (in - // normal, non-escape-mode). Judging by the copy-and-paste behavior, - // Windows apparently handles everything outside of the keyboard layout by - // first sending a sequence of Alt+KeyPad events, then finally a key-up - // event whose UnicodeChar has the appropriate value. For U+00A2 (CENT - // SIGN): - // - // key: dn rpt=1 scn=56 LAlt-MENU ch=0 - // key: dn rpt=1 scn=79 LAlt-NUMPAD1 ch=0 - // key: up rpt=1 scn=79 LAlt-NUMPAD1 ch=0 - // key: dn rpt=1 scn=76 LAlt-NUMPAD5 ch=0 - // key: up rpt=1 scn=76 LAlt-NUMPAD5 ch=0 - // key: dn rpt=1 scn=76 LAlt-NUMPAD5 ch=0 - // key: up rpt=1 scn=76 LAlt-NUMPAD5 ch=0 - // key: up rpt=1 scn=56 MENU ch=0xa2 - // - // The Alt+155 value matches the encoding of U+00A2 in CP-437. Curiously, - // if I use "chcp 1252" to change the encoding, then copy-and-pasting - // produces Alt+162 instead. (U+00A2 is 162 in CP-1252.) However, typing - // Alt+155 or Alt+162 produce the same characters regardless of console - // code page. (That is, they use CP-437 and yield U+00A2 and U+00F3.) - // - // For characters outside the BMP, Windows repeats the process for both - // UTF-16 code units, e.g, for U+1F300 (CYCLONE): - // - // key: dn rpt=1 scn=56 LAlt-MENU ch=0 - // key: dn rpt=1 scn=77 LAlt-NUMPAD6 ch=0 - // key: up rpt=1 scn=77 LAlt-NUMPAD6 ch=0 - // key: dn rpt=1 scn=81 LAlt-NUMPAD3 ch=0 - // key: up rpt=1 scn=81 LAlt-NUMPAD3 ch=0 - // key: up rpt=1 scn=56 MENU ch=0xd83c - // key: dn rpt=1 scn=56 LAlt-MENU ch=0 - // key: dn rpt=1 scn=77 LAlt-NUMPAD6 ch=0 - // key: up rpt=1 scn=77 LAlt-NUMPAD6 ch=0 - // key: dn rpt=1 scn=81 LAlt-NUMPAD3 ch=0 - // key: up rpt=1 scn=81 LAlt-NUMPAD3 ch=0 - // key: up rpt=1 scn=56 MENU ch=0xdf00 - // - // In this case, it sends Alt+63 twice, which signifies '?'. Apparently - // CMD and Cygwin bash are both able to decode this. - // - // Also note that typing Alt+NNN still works if NumLock is off, e.g.: - // - // key: dn rpt=1 scn=56 LAlt-MENU ch=0 - // key: dn rpt=1 scn=79 LAlt-END ch=0 - // key: up rpt=1 scn=79 LAlt-END ch=0 - // key: dn rpt=1 scn=76 LAlt-CLEAR ch=0 - // key: up rpt=1 scn=76 LAlt-CLEAR ch=0 - // key: dn rpt=1 scn=76 LAlt-CLEAR ch=0 - // key: up rpt=1 scn=76 LAlt-CLEAR ch=0 - // key: up rpt=1 scn=56 MENU ch=0xa2 - // - // Evidently, the Alt+NNN key events are not intended to be decoded to a - // character. Maybe programs are looking for a key-up ALT/MENU event with - // a non-zero character? - - wchar_t ws[2]; - const int wslen = encodeUtf16(ws, codePoint); - - if (wslen == 1) { - appendInputRecord(records, keyDown, virtualKey, ws[0], keyState); - } else if (wslen == 2) { - appendInputRecord(records, keyDown, virtualKey, ws[0], keyState); - appendInputRecord(records, keyDown, virtualKey, ws[1], keyState); - } else { - // This situation isn't that bad, but it should never happen, - // because invalid codepoints shouldn't reach this point. - trace("INTERNAL ERROR: appendInputRecordCP: invalid codePoint: " - "U+%04X", codePoint); - } -} - -void ConsoleInput::appendInputRecord(std::vector &records, - BOOL keyDown, - uint16_t virtualKey, - wchar_t utf16Char, - uint16_t keyState) -{ - INPUT_RECORD ir = {}; - ir.EventType = KEY_EVENT; - ir.Event.KeyEvent.bKeyDown = keyDown; - ir.Event.KeyEvent.wRepeatCount = 1; - ir.Event.KeyEvent.wVirtualKeyCode = virtualKey; - ir.Event.KeyEvent.wVirtualScanCode = - MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC); - ir.Event.KeyEvent.uChar.UnicodeChar = utf16Char; - ir.Event.KeyEvent.dwControlKeyState = keyState; - records.push_back(ir); -} - -DWORD ConsoleInput::inputConsoleMode() -{ - DWORD mode = 0; - if (!GetConsoleMode(m_conin, &mode)) { - trace("GetConsoleMode failed"); - return 0; - } - return mode; -} diff --git a/deps/winpty/src/agent/ConsoleInput.h b/deps/winpty/src/agent/ConsoleInput.h deleted file mode 100644 index e807d973b..000000000 --- a/deps/winpty/src/agent/ConsoleInput.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef CONSOLEINPUT_H -#define CONSOLEINPUT_H - -#include -#include - -#include -#include -#include - -#include "Coord.h" -#include "InputMap.h" -#include "SmallRect.h" - -class Win32Console; -class DsrSender; - -class ConsoleInput -{ -public: - ConsoleInput(HANDLE conin, int mouseMode, DsrSender &dsrSender, - Win32Console &console); - void writeInput(const std::string &input); - void flushIncompleteEscapeCode(); - void setMouseWindowRect(SmallRect val) { m_mouseWindowRect = val; } - void updateInputFlags(bool forceTrace=false); - bool shouldActivateTerminalMouse(); - -private: - void doWrite(bool isEof); - void flushInputRecords(std::vector &records); - int scanInput(std::vector &records, - const char *input, - int inputSize, - bool isEof); - int scanMouseInput(std::vector &records, - const char *input, - int inputSize); - void appendUtf8Char(std::vector &records, - const char *charBuffer, - int charLen, - bool terminalAltEscape); - void appendKeyPress(std::vector &records, - uint16_t virtualKey, - uint32_t winCodePointDn, - uint32_t winCodePointUp, - uint16_t winKeyState, - uint32_t vtCodePoint, - uint16_t vtKeyState); - -public: - static void appendCPInputRecords(std::vector &records, - BOOL keyDown, - uint16_t virtualKey, - uint32_t codePoint, - uint16_t keyState); - static void appendInputRecord(std::vector &records, - BOOL keyDown, - uint16_t virtualKey, - wchar_t utf16Char, - uint16_t keyState); - -private: - DWORD inputConsoleMode(); - -private: - Win32Console &m_console; - HANDLE m_conin = nullptr; - int m_mouseMode = 0; - DsrSender &m_dsrSender; - bool m_dsrSent = false; - std::string m_byteQueue; - InputMap m_inputMap; - DWORD m_lastWriteTick = 0; - DWORD m_mouseButtonState = 0; - struct DoubleClickDetection { - DWORD button = 0; - Coord pos; - DWORD tick = 0; - bool released = false; - } m_doubleClick; - bool m_enableExtendedEnabled = false; - bool m_mouseInputEnabled = false; - bool m_quickEditEnabled = false; - bool m_escapeInputEnabled = false; - SmallRect m_mouseWindowRect; -}; - -#endif // CONSOLEINPUT_H diff --git a/deps/winpty/src/agent/ConsoleInputReencoding.cc b/deps/winpty/src/agent/ConsoleInputReencoding.cc deleted file mode 100644 index b79545eea..000000000 --- a/deps/winpty/src/agent/ConsoleInputReencoding.cc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "ConsoleInputReencoding.h" - -#include "ConsoleInput.h" - -namespace { - -static void outch(std::vector &out, wchar_t ch) { - ConsoleInput::appendInputRecord(out, TRUE, 0, ch, 0); -} - -} // anonymous namespace - -void reencodeEscapedKeyPress( - std::vector &out, - uint16_t virtualKey, - uint32_t codePoint, - uint16_t keyState) { - - struct EscapedKey { - enum { None, Numeric, Letter } kind; - wchar_t content[2]; - }; - - EscapedKey escapeCode = {}; - switch (virtualKey) { - case VK_UP: escapeCode = { EscapedKey::Letter, {'A'} }; break; - case VK_DOWN: escapeCode = { EscapedKey::Letter, {'B'} }; break; - case VK_RIGHT: escapeCode = { EscapedKey::Letter, {'C'} }; break; - case VK_LEFT: escapeCode = { EscapedKey::Letter, {'D'} }; break; - case VK_CLEAR: escapeCode = { EscapedKey::Letter, {'E'} }; break; - case VK_F1: escapeCode = { EscapedKey::Numeric, {'1', '1'} }; break; - case VK_F2: escapeCode = { EscapedKey::Numeric, {'1', '2'} }; break; - case VK_F3: escapeCode = { EscapedKey::Numeric, {'1', '3'} }; break; - case VK_F4: escapeCode = { EscapedKey::Numeric, {'1', '4'} }; break; - case VK_F5: escapeCode = { EscapedKey::Numeric, {'1', '5'} }; break; - case VK_F6: escapeCode = { EscapedKey::Numeric, {'1', '7'} }; break; - case VK_F7: escapeCode = { EscapedKey::Numeric, {'1', '8'} }; break; - case VK_F8: escapeCode = { EscapedKey::Numeric, {'1', '9'} }; break; - case VK_F9: escapeCode = { EscapedKey::Numeric, {'2', '0'} }; break; - case VK_F10: escapeCode = { EscapedKey::Numeric, {'2', '1'} }; break; - case VK_F11: escapeCode = { EscapedKey::Numeric, {'2', '3'} }; break; - case VK_F12: escapeCode = { EscapedKey::Numeric, {'2', '4'} }; break; - case VK_HOME: escapeCode = { EscapedKey::Letter, {'H'} }; break; - case VK_INSERT: escapeCode = { EscapedKey::Numeric, {'2'} }; break; - case VK_DELETE: escapeCode = { EscapedKey::Numeric, {'3'} }; break; - case VK_END: escapeCode = { EscapedKey::Letter, {'F'} }; break; - case VK_PRIOR: escapeCode = { EscapedKey::Numeric, {'5'} }; break; - case VK_NEXT: escapeCode = { EscapedKey::Numeric, {'6'} }; break; - } - if (escapeCode.kind != EscapedKey::None) { - int flags = 0; - if (keyState & SHIFT_PRESSED) { flags |= 0x1; } - if (keyState & LEFT_ALT_PRESSED) { flags |= 0x2; } - if (keyState & LEFT_CTRL_PRESSED) { flags |= 0x4; } - outch(out, L'\x1b'); - outch(out, L'['); - if (escapeCode.kind == EscapedKey::Numeric) { - for (wchar_t ch : escapeCode.content) { - if (ch != L'\0') { - outch(out, ch); - } - } - } else if (flags != 0) { - outch(out, L'1'); - } - if (flags != 0) { - outch(out, L';'); - outch(out, L'1' + flags); - } - if (escapeCode.kind == EscapedKey::Numeric) { - outch(out, L'~'); - } else { - outch(out, escapeCode.content[0]); - } - return; - } - - switch (virtualKey) { - case VK_BACK: - if (keyState & LEFT_ALT_PRESSED) { - outch(out, L'\x1b'); - } - outch(out, L'\x7f'); - return; - case VK_TAB: - if (keyState & SHIFT_PRESSED) { - outch(out, L'\x1b'); - outch(out, L'['); - outch(out, L'Z'); - return; - } - break; - } - - if (codePoint != 0) { - if (keyState & LEFT_ALT_PRESSED) { - outch(out, L'\x1b'); - } - ConsoleInput::appendCPInputRecords(out, TRUE, 0, codePoint, 0); - } -} diff --git a/deps/winpty/src/agent/ConsoleInputReencoding.h b/deps/winpty/src/agent/ConsoleInputReencoding.h deleted file mode 100644 index 63bc006b5..000000000 --- a/deps/winpty/src/agent/ConsoleInputReencoding.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_CONSOLE_INPUT_REENCODING_H -#define AGENT_CONSOLE_INPUT_REENCODING_H - -#include - -#include - -#include - -void reencodeEscapedKeyPress( - std::vector &records, - uint16_t virtualKey, - uint32_t codePoint, - uint16_t keyState); - -#endif // AGENT_CONSOLE_INPUT_REENCODING_H diff --git a/deps/winpty/src/agent/ConsoleLine.cc b/deps/winpty/src/agent/ConsoleLine.cc deleted file mode 100644 index 1d2bcb768..000000000 --- a/deps/winpty/src/agent/ConsoleLine.cc +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// -// ConsoleLine -// -// This data structure keep tracks of the previous CHAR_INFO content of an -// output line and determines when a line has changed. Detecting line changes -// is made complicated by terminal resizing. -// - -#include "ConsoleLine.h" - -#include - -#include "../shared/WinptyAssert.h" - -static CHAR_INFO blankChar(WORD attributes) -{ - // N.B.: As long as we write to UnicodeChar rather than AsciiChar, there - // are no padding bytes that could contain uninitialized bytes. This fact - // is important for efficient comparison. - CHAR_INFO ret; - ret.Attributes = attributes; - ret.Char.UnicodeChar = L' '; - return ret; -} - -static bool isLineBlank(const CHAR_INFO *line, int length, WORD attributes) -{ - for (int col = 0; col < length; ++col) { - if (line[col].Attributes != attributes || - line[col].Char.UnicodeChar != L' ') { - return false; - } - } - return true; -} - -static inline bool areLinesEqual( - const CHAR_INFO *line1, - const CHAR_INFO *line2, - int length) -{ - return memcmp(line1, line2, sizeof(CHAR_INFO) * length) == 0; -} - -ConsoleLine::ConsoleLine() : m_prevLength(0) -{ -} - -void ConsoleLine::reset() -{ - m_prevLength = 0; - m_prevData.clear(); -} - -// Determines whether the given line is sufficiently different from the -// previously seen line as to justify reoutputting the line. The function -// also sets the `ConsoleLine` to the given line, exactly as if `setLine` had -// been called. -bool ConsoleLine::detectChangeAndSetLine(const CHAR_INFO *const line, const int newLength) -{ - ASSERT(newLength >= 1); - ASSERT(m_prevLength <= static_cast(m_prevData.size())); - - if (newLength == m_prevLength) { - bool equalLines = areLinesEqual(m_prevData.data(), line, newLength); - if (!equalLines) { - setLine(line, newLength); - } - return !equalLines; - } else { - if (m_prevLength == 0) { - setLine(line, newLength); - return true; - } - - ASSERT(m_prevLength >= 1); - const WORD prevBlank = m_prevData[m_prevLength - 1].Attributes; - const WORD newBlank = line[newLength - 1].Attributes; - - bool equalLines = false; - if (newLength < m_prevLength) { - // The line has become shorter. The lines are equal if the common - // part is equal, and if the newly truncated characters were blank. - equalLines = - areLinesEqual(m_prevData.data(), line, newLength) && - isLineBlank(m_prevData.data() + newLength, - m_prevLength - newLength, - newBlank); - } else { - // - // The line has become longer. The lines are equal if the common - // part is equal, and if both the extra characters and any - // potentially reexposed characters are blank. - // - // Two of the most relevant terminals for winpty--mintty and - // jediterm--don't (currently) erase the obscured content when a - // line is cleared, so we should anticipate its existence when - // making a terminal wider and reoutput the line. See: - // - // * https://github.com/mintty/mintty/issues/480 - // * https://github.com/JetBrains/jediterm/issues/118 - // - ASSERT(newLength > m_prevLength); - equalLines = - areLinesEqual(m_prevData.data(), line, m_prevLength) && - isLineBlank(m_prevData.data() + m_prevLength, - std::min(m_prevData.size(), newLength) - m_prevLength, - prevBlank) && - isLineBlank(line + m_prevLength, - newLength - m_prevLength, - prevBlank); - } - setLine(line, newLength); - return !equalLines; - } -} - -void ConsoleLine::setLine(const CHAR_INFO *const line, const int newLength) -{ - if (static_cast(m_prevData.size()) < newLength) { - m_prevData.resize(newLength); - } - memcpy(m_prevData.data(), line, sizeof(CHAR_INFO) * newLength); - m_prevLength = newLength; -} - -void ConsoleLine::blank(WORD attributes) -{ - m_prevData.resize(1); - m_prevData[0] = blankChar(attributes); - m_prevLength = 1; -} diff --git a/deps/winpty/src/agent/ConsoleLine.h b/deps/winpty/src/agent/ConsoleLine.h deleted file mode 100644 index 802c189c7..000000000 --- a/deps/winpty/src/agent/ConsoleLine.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef CONSOLE_LINE_H -#define CONSOLE_LINE_H - -#include - -#include - -class ConsoleLine -{ -public: - ConsoleLine(); - void reset(); - bool detectChangeAndSetLine(const CHAR_INFO *line, int newLength); - void setLine(const CHAR_INFO *line, int newLength); - void blank(WORD attributes); -private: - int m_prevLength; - std::vector m_prevData; -}; - -#endif // CONSOLE_LINE_H diff --git a/deps/winpty/src/agent/Coord.h b/deps/winpty/src/agent/Coord.h deleted file mode 100644 index 74c98adda..000000000 --- a/deps/winpty/src/agent/Coord.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef COORD_H -#define COORD_H - -#include - -#include - -#include "../shared/winpty_snprintf.h" - -struct Coord : COORD { - Coord() - { - X = 0; - Y = 0; - } - - Coord(SHORT x, SHORT y) - { - X = x; - Y = y; - } - - Coord(COORD other) - { - *(COORD*)this = other; - } - - Coord(const Coord &other) - { - *(COORD*)this = *(const COORD*)&other; - } - - Coord &operator=(const Coord &other) - { - *(COORD*)this = *(const COORD*)&other; - return *this; - } - - bool operator==(const Coord &other) const - { - return X == other.X && Y == other.Y; - } - - bool operator!=(const Coord &other) const - { - return !(*this == other); - } - - Coord operator+(const Coord &other) const - { - return Coord(X + other.X, Y + other.Y); - } - - bool isEmpty() const - { - return X <= 0 || Y <= 0; - } - - std::string toString() const - { - char ret[32]; - winpty_snprintf(ret, "(%d,%d)", X, Y); - return std::string(ret); - } -}; - -#endif // COORD_H diff --git a/deps/winpty/src/agent/DebugShowInput.cc b/deps/winpty/src/agent/DebugShowInput.cc deleted file mode 100644 index 191b2e146..000000000 --- a/deps/winpty/src/agent/DebugShowInput.cc +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "DebugShowInput.h" - -#include -#include -#include -#include - -#include - -#include "../shared/StringBuilder.h" -#include "InputMap.h" - -namespace { - -struct Flag { - DWORD value; - const char *text; -}; - -static const Flag kButtonStates[] = { - { FROM_LEFT_1ST_BUTTON_PRESSED, "1" }, - { FROM_LEFT_2ND_BUTTON_PRESSED, "2" }, - { FROM_LEFT_3RD_BUTTON_PRESSED, "3" }, - { FROM_LEFT_4TH_BUTTON_PRESSED, "4" }, - { RIGHTMOST_BUTTON_PRESSED, "R" }, -}; - -static const Flag kControlKeyStates[] = { - { CAPSLOCK_ON, "CapsLock" }, - { ENHANCED_KEY, "Enhanced" }, - { LEFT_ALT_PRESSED, "LAlt" }, - { LEFT_CTRL_PRESSED, "LCtrl" }, - { NUMLOCK_ON, "NumLock" }, - { RIGHT_ALT_PRESSED, "RAlt" }, - { RIGHT_CTRL_PRESSED, "RCtrl" }, - { SCROLLLOCK_ON, "ScrollLock" }, - { SHIFT_PRESSED, "Shift" }, -}; - -static const Flag kMouseEventFlags[] = { - { DOUBLE_CLICK, "Double" }, - { 8/*MOUSE_HWHEELED*/, "HWheel" }, - { MOUSE_MOVED, "Move" }, - { MOUSE_WHEELED, "Wheel" }, -}; - -static void writeFlags(StringBuilder &out, DWORD flags, - const char *remainderName, - const Flag *table, size_t tableSize, - char pre, char sep, char post) { - DWORD remaining = flags; - bool wroteSomething = false; - for (size_t i = 0; i < tableSize; ++i) { - const Flag &f = table[i]; - if ((f.value & flags) == f.value) { - if (!wroteSomething && pre != '\0') { - out << pre; - } else if (wroteSomething && sep != '\0') { - out << sep; - } - out << f.text; - wroteSomething = true; - remaining &= ~f.value; - } - } - if (remaining != 0) { - if (!wroteSomething && pre != '\0') { - out << pre; - } else if (wroteSomething && sep != '\0') { - out << sep; - } - out << remainderName << "(0x" << hexOfInt(remaining) << ')'; - wroteSomething = true; - } - if (wroteSomething && post != '\0') { - out << post; - } -} - -template -static void writeFlags(StringBuilder &out, DWORD flags, - const char *remainderName, - const Flag (&table)[n], - char pre, char sep, char post) { - writeFlags(out, flags, remainderName, table, n, pre, sep, post); -} - -} // anonymous namespace - -std::string controlKeyStatePrefix(DWORD controlKeyState) { - StringBuilder sb; - writeFlags(sb, controlKeyState, - "keyState", kControlKeyStates, '\0', '-', '-'); - return sb.str_moved(); -} - -std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer) { - const uint16_t buttons = mer.dwButtonState & 0xFFFF; - const int16_t wheel = mer.dwButtonState >> 16; - StringBuilder sb; - sb << "pos=" << mer.dwMousePosition.X << ',' - << mer.dwMousePosition.Y; - writeFlags(sb, mer.dwControlKeyState, "keyState", kControlKeyStates, ' ', ' ', '\0'); - writeFlags(sb, mer.dwEventFlags, "flags", kMouseEventFlags, ' ', ' ', '\0'); - writeFlags(sb, buttons, "buttons", kButtonStates, ' ', ' ', '\0'); - if (wheel != 0) { - sb << " wheel=" << wheel; - } - return sb.str_moved(); -} - -void debugShowInput(bool enableMouse, bool escapeInput) { - HANDLE conin = GetStdHandle(STD_INPUT_HANDLE); - DWORD origConsoleMode = 0; - if (!GetConsoleMode(conin, &origConsoleMode)) { - fprintf(stderr, "Error: could not read console mode -- " - "is STDIN a console handle?\n"); - exit(1); - } - DWORD restoreConsoleMode = origConsoleMode; - if (enableMouse && !(restoreConsoleMode & ENABLE_EXTENDED_FLAGS)) { - // We need to disable QuickEdit mode, because it blocks mouse events. - // If ENABLE_EXTENDED_FLAGS wasn't originally in the console mode, then - // we have no way of knowning whether QuickEdit or InsertMode are - // currently enabled. Enable them both (eventually), because they're - // sensible defaults. This case shouldn't happen typically. See - // misc/EnableExtendedFlags.txt. - restoreConsoleMode |= ENABLE_EXTENDED_FLAGS; - restoreConsoleMode |= ENABLE_QUICK_EDIT_MODE; - restoreConsoleMode |= ENABLE_INSERT_MODE; - } - DWORD newConsoleMode = restoreConsoleMode; - newConsoleMode &= ~ENABLE_PROCESSED_INPUT; - newConsoleMode &= ~ENABLE_LINE_INPUT; - newConsoleMode &= ~ENABLE_ECHO_INPUT; - newConsoleMode |= ENABLE_WINDOW_INPUT; - if (enableMouse) { - newConsoleMode |= ENABLE_MOUSE_INPUT; - newConsoleMode &= ~ENABLE_QUICK_EDIT_MODE; - } else { - newConsoleMode &= ~ENABLE_MOUSE_INPUT; - } - if (escapeInput) { - // As of this writing (2016-06-05), Microsoft has shipped two preview - // builds of Windows 10 (14316 and 14342) that include a new "Windows - // Subsystem for Linux" that runs Ubuntu in a new subsystem. Running - // bash in this subsystem requires the non-legacy console mode, and the - // console input buffer is put into a special mode where escape - // sequences are written into the console input buffer. This mode is - // enabled with the 0x200 flag, which is as-yet undocumented. - // See https://github.com/rprichard/winpty/issues/82. - newConsoleMode |= 0x200; - } - if (!SetConsoleMode(conin, newConsoleMode)) { - fprintf(stderr, "Error: could not set console mode " - "(0x%x -> 0x%x -> 0x%x)\n", - static_cast(origConsoleMode), - static_cast(newConsoleMode), - static_cast(restoreConsoleMode)); - exit(1); - } - printf("\nPress any keys -- Ctrl-D exits\n\n"); - INPUT_RECORD records[32]; - DWORD actual = 0; - bool finished = false; - while (!finished && - ReadConsoleInputW(conin, records, 32, &actual) && actual >= 1) { - StringBuilder sb; - for (DWORD i = 0; i < actual; ++i) { - const INPUT_RECORD &record = records[i]; - if (record.EventType == KEY_EVENT) { - const KEY_EVENT_RECORD &ker = record.Event.KeyEvent; - InputMap::Key key = { - ker.wVirtualKeyCode, - ker.uChar.UnicodeChar, - static_cast(ker.dwControlKeyState), - }; - sb << "key: " << (ker.bKeyDown ? "dn" : "up") - << " rpt=" << ker.wRepeatCount - << " scn=" << (ker.wVirtualScanCode ? "0x" : "") << hexOfInt(ker.wVirtualScanCode) - << ' ' << key.toString() << '\n'; - if ((ker.dwControlKeyState & - (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && - ker.wVirtualKeyCode == 'D') { - finished = true; - break; - } else if (ker.wVirtualKeyCode == 0 && - ker.wVirtualScanCode == 0 && - ker.uChar.UnicodeChar == 4) { - // Also look for a zeroed-out Ctrl-D record generated for - // ENABLE_VIRTUAL_TERMINAL_INPUT. - finished = true; - break; - } - } else if (record.EventType == MOUSE_EVENT) { - const MOUSE_EVENT_RECORD &mer = record.Event.MouseEvent; - sb << "mouse: " << mouseEventToString(mer) << '\n'; - } else if (record.EventType == WINDOW_BUFFER_SIZE_EVENT) { - const WINDOW_BUFFER_SIZE_RECORD &wbsr = - record.Event.WindowBufferSizeEvent; - sb << "buffer-resized: dwSize=(" - << wbsr.dwSize.X << ',' - << wbsr.dwSize.Y << ")\n"; - } else if (record.EventType == MENU_EVENT) { - const MENU_EVENT_RECORD &mer = record.Event.MenuEvent; - sb << "menu-event: commandId=0x" - << hexOfInt(mer.dwCommandId) << '\n'; - } else if (record.EventType == FOCUS_EVENT) { - const FOCUS_EVENT_RECORD &fer = record.Event.FocusEvent; - sb << "focus: " << (fer.bSetFocus ? "gained" : "lost") << '\n'; - } - } - - const auto str = sb.str_moved(); - fwrite(str.data(), 1, str.size(), stdout); - fflush(stdout); - } - SetConsoleMode(conin, restoreConsoleMode); -} diff --git a/deps/winpty/src/agent/DebugShowInput.h b/deps/winpty/src/agent/DebugShowInput.h deleted file mode 100644 index 4fa13604b..000000000 --- a/deps/winpty/src/agent/DebugShowInput.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_DEBUG_SHOW_INPUT_H -#define AGENT_DEBUG_SHOW_INPUT_H - -#include - -#include - -std::string controlKeyStatePrefix(DWORD controlKeyState); -std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer); -void debugShowInput(bool enableMouse, bool escapeInput); - -#endif // AGENT_DEBUG_SHOW_INPUT_H diff --git a/deps/winpty/src/agent/DefaultInputMap.cc b/deps/winpty/src/agent/DefaultInputMap.cc deleted file mode 100644 index 5e29d98e4..000000000 --- a/deps/winpty/src/agent/DefaultInputMap.cc +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "DefaultInputMap.h" - -#include -#include - -#include - -#include "../shared/StringBuilder.h" -#include "../shared/WinptyAssert.h" -#include "InputMap.h" - -#define ESC "\x1B" -#define DIM(x) (sizeof(x) / sizeof((x)[0])) - -namespace { - -struct EscapeEncoding { - bool alt_prefix_allowed; - char prefix; - char id; - int modifiers; - InputMap::Key key; -}; - -// Modifiers. A "modifier" is an integer from 2 to 8 that conveys the status -// of Shift(1), Alt(2), and Ctrl(4). The value is constructed by OR'ing the -// appropriate value for each active modifier, then adding 1. -// -// Details: -// - kBare: expands to: ESC -// - kSemiMod: expands to: ESC ; -// - kBareMod: expands to: ESC -const int kBare = 0x01; -const int kSemiMod = 0x02; -const int kBareMod = 0x04; - -// Numeric escape sequences suffixes: -// - with no flag: accept: ~ -// - kSuffixCtrl: accept: ~ ^ -// - kSuffixShift: accept: ~ $ -// - kSuffixBoth: accept: ~ ^ $ @ -const int kSuffixCtrl = 0x08; -const int kSuffixShift = 0x10; -const int kSuffixBoth = kSuffixCtrl | kSuffixShift; - -static const EscapeEncoding escapeLetterEncodings[] = { - // Conventional arrow keys - // kBareMod: Ubuntu /etc/inputrc and IntelliJ/JediTerm use escapes like: ESC [ n ABCD - { true, '[', 'A', kBare | kBareMod | kSemiMod, { VK_UP, '\0', 0 } }, - { true, '[', 'B', kBare | kBareMod | kSemiMod, { VK_DOWN, '\0', 0 } }, - { true, '[', 'C', kBare | kBareMod | kSemiMod, { VK_RIGHT, '\0', 0 } }, - { true, '[', 'D', kBare | kBareMod | kSemiMod, { VK_LEFT, '\0', 0 } }, - - // putty. putty uses this sequence for Ctrl-Arrow, Shift-Arrow, and - // Ctrl-Shift-Arrow, but I can only decode to one choice, so I'm just - // leaving the modifier off altogether. - { true, 'O', 'A', kBare, { VK_UP, '\0', 0 } }, - { true, 'O', 'B', kBare, { VK_DOWN, '\0', 0 } }, - { true, 'O', 'C', kBare, { VK_RIGHT, '\0', 0 } }, - { true, 'O', 'D', kBare, { VK_LEFT, '\0', 0 } }, - - // rxvt, rxvt-unicode - // Shift-Ctrl-Arrow can't be identified. It's the same as Shift-Arrow. - { true, '[', 'a', kBare, { VK_UP, '\0', SHIFT_PRESSED } }, - { true, '[', 'b', kBare, { VK_DOWN, '\0', SHIFT_PRESSED } }, - { true, '[', 'c', kBare, { VK_RIGHT, '\0', SHIFT_PRESSED } }, - { true, '[', 'd', kBare, { VK_LEFT, '\0', SHIFT_PRESSED } }, - { true, 'O', 'a', kBare, { VK_UP, '\0', LEFT_CTRL_PRESSED } }, - { true, 'O', 'b', kBare, { VK_DOWN, '\0', LEFT_CTRL_PRESSED } }, - { true, 'O', 'c', kBare, { VK_RIGHT, '\0', LEFT_CTRL_PRESSED } }, - { true, 'O', 'd', kBare, { VK_LEFT, '\0', LEFT_CTRL_PRESSED } }, - - // Numpad 5 with NumLock off - // * xterm, mintty, and gnome-terminal use `ESC [ E`. - // * putty, TERM=cygwin, TERM=linux all use `ESC [ G` for 5 - // * putty uses `ESC O G` for Ctrl-5 and Shift-5. Omit the modifier - // as with putty's arrow keys. - // * I never saw modifiers inserted into these escapes, but I think - // it should be completely OK with the CSI escapes. - { true, '[', 'E', kBare | kSemiMod, { VK_CLEAR, '\0', 0 } }, - { true, '[', 'G', kBare | kSemiMod, { VK_CLEAR, '\0', 0 } }, - { true, 'O', 'G', kBare, { VK_CLEAR, '\0', 0 } }, - - // Home/End, letter version - // * gnome-terminal uses `ESC O [HF]`. I never saw it modified. - // kBareMod: IntelliJ/JediTerm uses escapes like: ESC [ n HF - { true, '[', 'H', kBare | kBareMod | kSemiMod, { VK_HOME, '\0', 0 } }, - { true, '[', 'F', kBare | kBareMod | kSemiMod, { VK_END, '\0', 0 } }, - { true, 'O', 'H', kBare, { VK_HOME, '\0', 0 } }, - { true, 'O', 'F', kBare, { VK_END, '\0', 0 } }, - - // F1-F4, letter version (xterm, VTE, konsole) - { true, '[', 'P', kSemiMod, { VK_F1, '\0', 0 } }, - { true, '[', 'Q', kSemiMod, { VK_F2, '\0', 0 } }, - { true, '[', 'R', kSemiMod, { VK_F3, '\0', 0 } }, - { true, '[', 'S', kSemiMod, { VK_F4, '\0', 0 } }, - - // GNOME VTE and Konsole have special encodings for modified F1-F4: - // * [VTE] ESC O 1 ; n [PQRS] - // * [Konsole] ESC O n [PQRS] - { false, 'O', 'P', kBare | kBareMod | kSemiMod, { VK_F1, '\0', 0 } }, - { false, 'O', 'Q', kBare | kBareMod | kSemiMod, { VK_F2, '\0', 0 } }, - { false, 'O', 'R', kBare | kBareMod | kSemiMod, { VK_F3, '\0', 0 } }, - { false, 'O', 'S', kBare | kBareMod | kSemiMod, { VK_F4, '\0', 0 } }, - - // Handle the "application numpad" escape sequences. - // - // Terminals output these codes under various circumstances: - // * rxvt-unicode: numpad, hold down SHIFT - // * rxvt: numpad, by default - // * xterm: numpad, after enabling app-mode using DECPAM (`ESC =`). xterm - // generates `ESC O ` for modified numpad presses, - // necessitating kBareMod. - // * mintty: by combining Ctrl with various keys such as '1' or ','. - // Handling those keys is difficult, because mintty is generating the - // same sequence for Ctrl-1 and Ctrl-NumPadEnd -- should the virtualKey - // be '1' or VK_HOME? - - { true, 'O', 'M', kBare | kBareMod, { VK_RETURN, '\r', 0 } }, - { true, 'O', 'j', kBare | kBareMod, { VK_MULTIPLY, '*', 0 } }, - { true, 'O', 'k', kBare | kBareMod, { VK_ADD, '+', 0 } }, - { true, 'O', 'm', kBare | kBareMod, { VK_SUBTRACT, '-', 0 } }, - { true, 'O', 'n', kBare | kBareMod, { VK_DELETE, '\0', 0 } }, - { true, 'O', 'o', kBare | kBareMod, { VK_DIVIDE, '/', 0 } }, - { true, 'O', 'p', kBare | kBareMod, { VK_INSERT, '\0', 0 } }, - { true, 'O', 'q', kBare | kBareMod, { VK_END, '\0', 0 } }, - { true, 'O', 'r', kBare | kBareMod, { VK_DOWN, '\0', 0 } }, - { true, 'O', 's', kBare | kBareMod, { VK_NEXT, '\0', 0 } }, - { true, 'O', 't', kBare | kBareMod, { VK_LEFT, '\0', 0 } }, - { true, 'O', 'u', kBare | kBareMod, { VK_CLEAR, '\0', 0 } }, - { true, 'O', 'v', kBare | kBareMod, { VK_RIGHT, '\0', 0 } }, - { true, 'O', 'w', kBare | kBareMod, { VK_HOME, '\0', 0 } }, - { true, 'O', 'x', kBare | kBareMod, { VK_UP, '\0', 0 } }, - { true, 'O', 'y', kBare | kBareMod, { VK_PRIOR, '\0', 0 } }, - - { true, '[', 'M', kBare | kSemiMod, { VK_RETURN, '\r', 0 } }, - { true, '[', 'j', kBare | kSemiMod, { VK_MULTIPLY, '*', 0 } }, - { true, '[', 'k', kBare | kSemiMod, { VK_ADD, '+', 0 } }, - { true, '[', 'm', kBare | kSemiMod, { VK_SUBTRACT, '-', 0 } }, - { true, '[', 'n', kBare | kSemiMod, { VK_DELETE, '\0', 0 } }, - { true, '[', 'o', kBare | kSemiMod, { VK_DIVIDE, '/', 0 } }, - { true, '[', 'p', kBare | kSemiMod, { VK_INSERT, '\0', 0 } }, - { true, '[', 'q', kBare | kSemiMod, { VK_END, '\0', 0 } }, - { true, '[', 'r', kBare | kSemiMod, { VK_DOWN, '\0', 0 } }, - { true, '[', 's', kBare | kSemiMod, { VK_NEXT, '\0', 0 } }, - { true, '[', 't', kBare | kSemiMod, { VK_LEFT, '\0', 0 } }, - { true, '[', 'u', kBare | kSemiMod, { VK_CLEAR, '\0', 0 } }, - { true, '[', 'v', kBare | kSemiMod, { VK_RIGHT, '\0', 0 } }, - { true, '[', 'w', kBare | kSemiMod, { VK_HOME, '\0', 0 } }, - { true, '[', 'x', kBare | kSemiMod, { VK_UP, '\0', 0 } }, - { true, '[', 'y', kBare | kSemiMod, { VK_PRIOR, '\0', 0 } }, - - { false, '[', 'Z', kBare, { VK_TAB, '\t', SHIFT_PRESSED } }, -}; - -static const EscapeEncoding escapeNumericEncodings[] = { - { true, '[', 1, kBare | kSemiMod | kSuffixBoth, { VK_HOME, '\0', 0 } }, - { true, '[', 2, kBare | kSemiMod | kSuffixBoth, { VK_INSERT, '\0', 0 } }, - { true, '[', 3, kBare | kSemiMod | kSuffixBoth, { VK_DELETE, '\0', 0 } }, - { true, '[', 4, kBare | kSemiMod | kSuffixBoth, { VK_END, '\0', 0 } }, - { true, '[', 5, kBare | kSemiMod | kSuffixBoth, { VK_PRIOR, '\0', 0 } }, - { true, '[', 6, kBare | kSemiMod | kSuffixBoth, { VK_NEXT, '\0', 0 } }, - { true, '[', 7, kBare | kSemiMod | kSuffixBoth, { VK_HOME, '\0', 0 } }, - { true, '[', 8, kBare | kSemiMod | kSuffixBoth, { VK_END, '\0', 0 } }, - { true, '[', 11, kBare | kSemiMod | kSuffixBoth, { VK_F1, '\0', 0 } }, - { true, '[', 12, kBare | kSemiMod | kSuffixBoth, { VK_F2, '\0', 0 } }, - { true, '[', 13, kBare | kSemiMod | kSuffixBoth, { VK_F3, '\0', 0 } }, - { true, '[', 14, kBare | kSemiMod | kSuffixBoth, { VK_F4, '\0', 0 } }, - { true, '[', 15, kBare | kSemiMod | kSuffixBoth, { VK_F5, '\0', 0 } }, - { true, '[', 17, kBare | kSemiMod | kSuffixBoth, { VK_F6, '\0', 0 } }, - { true, '[', 18, kBare | kSemiMod | kSuffixBoth, { VK_F7, '\0', 0 } }, - { true, '[', 19, kBare | kSemiMod | kSuffixBoth, { VK_F8, '\0', 0 } }, - { true, '[', 20, kBare | kSemiMod | kSuffixBoth, { VK_F9, '\0', 0 } }, - { true, '[', 21, kBare | kSemiMod | kSuffixBoth, { VK_F10, '\0', 0 } }, - { true, '[', 23, kBare | kSemiMod | kSuffixBoth, { VK_F11, '\0', 0 } }, - { true, '[', 24, kBare | kSemiMod | kSuffixBoth, { VK_F12, '\0', 0 } }, - { true, '[', 25, kBare | kSemiMod | kSuffixBoth, { VK_F3, '\0', SHIFT_PRESSED } }, - { true, '[', 26, kBare | kSemiMod | kSuffixBoth, { VK_F4, '\0', SHIFT_PRESSED } }, - { true, '[', 28, kBare | kSemiMod | kSuffixBoth, { VK_F5, '\0', SHIFT_PRESSED } }, - { true, '[', 29, kBare | kSemiMod | kSuffixBoth, { VK_F6, '\0', SHIFT_PRESSED } }, - { true, '[', 31, kBare | kSemiMod | kSuffixBoth, { VK_F7, '\0', SHIFT_PRESSED } }, - { true, '[', 32, kBare | kSemiMod | kSuffixBoth, { VK_F8, '\0', SHIFT_PRESSED } }, - { true, '[', 33, kBare | kSemiMod | kSuffixBoth, { VK_F9, '\0', SHIFT_PRESSED } }, - { true, '[', 34, kBare | kSemiMod | kSuffixBoth, { VK_F10, '\0', SHIFT_PRESSED } }, -}; - -const int kCsiShiftModifier = 1; -const int kCsiAltModifier = 2; -const int kCsiCtrlModifier = 4; - -static inline bool useEnhancedForVirtualKey(uint16_t vk) { - switch (vk) { - case VK_UP: - case VK_DOWN: - case VK_LEFT: - case VK_RIGHT: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - return true; - default: - return false; - } -} - -static void addSimpleEntries(InputMap &inputMap) { - struct SimpleEncoding { - const char *encoding; - InputMap::Key key; - }; - - static const SimpleEncoding simpleEncodings[] = { - // Ctrl- seems to be handled OK by the default code path. - - { "\x7F", { VK_BACK, '\x08', 0, } }, - { ESC "\x7F", { VK_BACK, '\x08', LEFT_ALT_PRESSED, } }, - { "\x03", { 'C', '\x03', LEFT_CTRL_PRESSED, } }, - - // Handle special F1-F5 for TERM=linux and TERM=cygwin. - { ESC "[[A", { VK_F1, '\0', 0 } }, - { ESC "[[B", { VK_F2, '\0', 0 } }, - { ESC "[[C", { VK_F3, '\0', 0 } }, - { ESC "[[D", { VK_F4, '\0', 0 } }, - { ESC "[[E", { VK_F5, '\0', 0 } }, - - { ESC ESC "[[A", { VK_F1, '\0', LEFT_ALT_PRESSED } }, - { ESC ESC "[[B", { VK_F2, '\0', LEFT_ALT_PRESSED } }, - { ESC ESC "[[C", { VK_F3, '\0', LEFT_ALT_PRESSED } }, - { ESC ESC "[[D", { VK_F4, '\0', LEFT_ALT_PRESSED } }, - { ESC ESC "[[E", { VK_F5, '\0', LEFT_ALT_PRESSED } }, - }; - - for (size_t i = 0; i < DIM(simpleEncodings); ++i) { - auto k = simpleEncodings[i].key; - if (useEnhancedForVirtualKey(k.virtualKey)) { - k.keyState |= ENHANCED_KEY; - } - inputMap.set(simpleEncodings[i].encoding, - strlen(simpleEncodings[i].encoding), - k); - } -} - -struct ExpandContext { - InputMap &inputMap; - const EscapeEncoding &e; - char *buffer; - char *bufferEnd; -}; - -static inline void setEncoding(const ExpandContext &ctx, char *end, - uint16_t extraKeyState) { - InputMap::Key k = ctx.e.key; - k.keyState |= extraKeyState; - if (k.keyState & LEFT_CTRL_PRESSED) { - switch (k.virtualKey) { - case VK_ADD: - case VK_DIVIDE: - case VK_MULTIPLY: - case VK_SUBTRACT: - k.unicodeChar = '\0'; - break; - case VK_RETURN: - k.unicodeChar = '\n'; - break; - } - } - if (useEnhancedForVirtualKey(k.virtualKey)) { - k.keyState |= ENHANCED_KEY; - } - ctx.inputMap.set(ctx.buffer, end - ctx.buffer, k); -} - -static inline uint16_t keyStateForMod(int mod) { - int ret = 0; - if ((mod - 1) & kCsiShiftModifier) ret |= SHIFT_PRESSED; - if ((mod - 1) & kCsiAltModifier) ret |= LEFT_ALT_PRESSED; - if ((mod - 1) & kCsiCtrlModifier) ret |= LEFT_CTRL_PRESSED; - return ret; -} - -static void expandNumericEncodingSuffix(const ExpandContext &ctx, char *p, - uint16_t extraKeyState) { - ASSERT(p <= ctx.bufferEnd - 1); - { - char *q = p; - *q++ = '~'; - setEncoding(ctx, q, extraKeyState); - } - if (ctx.e.modifiers & kSuffixShift) { - char *q = p; - *q++ = '$'; - setEncoding(ctx, q, extraKeyState | SHIFT_PRESSED); - } - if (ctx.e.modifiers & kSuffixCtrl) { - char *q = p; - *q++ = '^'; - setEncoding(ctx, q, extraKeyState | LEFT_CTRL_PRESSED); - } - if (ctx.e.modifiers & (kSuffixCtrl | kSuffixShift)) { - char *q = p; - *q++ = '@'; - setEncoding(ctx, q, extraKeyState | SHIFT_PRESSED | LEFT_CTRL_PRESSED); - } -} - -template -static inline void expandEncodingAfterAltPrefix( - const ExpandContext &ctx, char *p, uint16_t extraKeyState) { - auto appendId = [&](char *&ptr) { - const auto idstr = decOfInt(ctx.e.id); - ASSERT(ptr <= ctx.bufferEnd - idstr.size()); - std::copy(idstr.data(), idstr.data() + idstr.size(), ptr); - ptr += idstr.size(); - }; - ASSERT(p <= ctx.bufferEnd - 2); - *p++ = '\x1b'; - *p++ = ctx.e.prefix; - if (ctx.e.modifiers & kBare) { - char *q = p; - if (is_numeric) { - appendId(q); - expandNumericEncodingSuffix(ctx, q, extraKeyState); - } else { - ASSERT(q <= ctx.bufferEnd - 1); - *q++ = ctx.e.id; - setEncoding(ctx, q, extraKeyState); - } - } - if (ctx.e.modifiers & kBareMod) { - ASSERT(!is_numeric && "kBareMod is invalid with numeric sequences"); - for (int mod = 2; mod <= 8; ++mod) { - char *q = p; - ASSERT(q <= ctx.bufferEnd - 2); - *q++ = '0' + mod; - *q++ = ctx.e.id; - setEncoding(ctx, q, extraKeyState | keyStateForMod(mod)); - } - } - if (ctx.e.modifiers & kSemiMod) { - for (int mod = 2; mod <= 8; ++mod) { - char *q = p; - if (is_numeric) { - appendId(q); - ASSERT(q <= ctx.bufferEnd - 2); - *q++ = ';'; - *q++ = '0' + mod; - expandNumericEncodingSuffix( - ctx, q, extraKeyState | keyStateForMod(mod)); - } else { - ASSERT(q <= ctx.bufferEnd - 4); - *q++ = '1'; - *q++ = ';'; - *q++ = '0' + mod; - *q++ = ctx.e.id; - setEncoding(ctx, q, extraKeyState | keyStateForMod(mod)); - } - } - } -} - -template -static inline void expandEncoding(const ExpandContext &ctx) { - if (ctx.e.alt_prefix_allowed) { - // For better or for worse, this code expands all of: - // * ESC [ -- - // * ESC ESC [ -- Alt- - // * ESC [ 1 ; 3 -- Alt- - // * ESC ESC [ 1 ; 3 -- Alt- specified twice - // I suspect no terminal actually emits the last one (i.e. specifying - // the Alt modifier using both methods), but I have seen a terminal - // that emitted a prefix ESC for Alt and a non-Alt modifier. - char *p = ctx.buffer; - ASSERT(p <= ctx.bufferEnd - 1); - *p++ = '\x1b'; - expandEncodingAfterAltPrefix(ctx, p, LEFT_ALT_PRESSED); - } - expandEncodingAfterAltPrefix(ctx, ctx.buffer, 0); -} - -template -static void addEscapes(InputMap &inputMap, const EscapeEncoding (&encodings)[N]) { - char buffer[32]; - for (size_t i = 0; i < DIM(encodings); ++i) { - ExpandContext ctx = { - inputMap, encodings[i], - buffer, buffer + sizeof(buffer) - }; - expandEncoding(ctx); - } -} - -} // anonymous namespace - -void addDefaultEntriesToInputMap(InputMap &inputMap) { - addEscapes(inputMap, escapeLetterEncodings); - addEscapes(inputMap, escapeNumericEncodings); - addSimpleEntries(inputMap); -} diff --git a/deps/winpty/src/agent/DefaultInputMap.h b/deps/winpty/src/agent/DefaultInputMap.h deleted file mode 100644 index c4b908367..000000000 --- a/deps/winpty/src/agent/DefaultInputMap.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef DEFAULT_INPUT_MAP_H -#define DEFAULT_INPUT_MAP_H - -class InputMap; - -void addDefaultEntriesToInputMap(InputMap &inputMap); - -#endif // DEFAULT_INPUT_MAP_H diff --git a/deps/winpty/src/agent/DsrSender.h b/deps/winpty/src/agent/DsrSender.h deleted file mode 100644 index 1ec0a97d2..000000000 --- a/deps/winpty/src/agent/DsrSender.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef DSRSENDER_H -#define DSRSENDER_H - -class DsrSender -{ -public: - virtual void sendDsr() = 0; -}; - -#endif // DSRSENDER_H diff --git a/deps/winpty/src/agent/EventLoop.cc b/deps/winpty/src/agent/EventLoop.cc deleted file mode 100644 index ba5cf18cc..000000000 --- a/deps/winpty/src/agent/EventLoop.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "EventLoop.h" - -#include - -#include "NamedPipe.h" -#include "../shared/DebugClient.h" -#include "../shared/WinptyAssert.h" - -EventLoop::~EventLoop() { - for (NamedPipe *pipe : m_pipes) { - delete pipe; - } - m_pipes.clear(); -} - -// Enter the event loop. Runs until the I/O or timeout handler calls exit(). -void EventLoop::run() -{ - std::vector waitHandles; - DWORD lastTime = GetTickCount(); - while (!m_exiting) { - bool didSomething = false; - - // Attempt to make progress with the pipes. - waitHandles.clear(); - for (size_t i = 0; i < m_pipes.size(); ++i) { - if (m_pipes[i]->serviceIo(&waitHandles)) { - onPipeIo(*m_pipes[i]); - didSomething = true; - } - } - - // Call the timeout if enough time has elapsed. - if (m_pollInterval > 0) { - int elapsed = GetTickCount() - lastTime; - if (elapsed >= m_pollInterval) { - onPollTimeout(); - lastTime = GetTickCount(); - didSomething = true; - } - } - - if (didSomething) - continue; - - // If there's nothing to do, wait. - DWORD timeout = INFINITE; - if (m_pollInterval > 0) - timeout = std::max(0, (int)(lastTime + m_pollInterval - GetTickCount())); - if (waitHandles.size() == 0) { - ASSERT(timeout != INFINITE); - if (timeout > 0) - Sleep(timeout); - } else { - DWORD result = WaitForMultipleObjects(waitHandles.size(), - waitHandles.data(), - FALSE, - timeout); - ASSERT(result != WAIT_FAILED); - } - } -} - -NamedPipe &EventLoop::createNamedPipe() -{ - NamedPipe *ret = new NamedPipe(); - m_pipes.push_back(ret); - return *ret; -} - -void EventLoop::setPollInterval(int ms) -{ - m_pollInterval = ms; -} - -void EventLoop::shutdown() -{ - m_exiting = true; -} diff --git a/deps/winpty/src/agent/EventLoop.h b/deps/winpty/src/agent/EventLoop.h deleted file mode 100644 index eddb0f626..000000000 --- a/deps/winpty/src/agent/EventLoop.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef EVENTLOOP_H -#define EVENTLOOP_H - -#include - -class NamedPipe; - -class EventLoop -{ -public: - virtual ~EventLoop(); - void run(); - -protected: - NamedPipe &createNamedPipe(); - void setPollInterval(int ms); - void shutdown(); - virtual void onPollTimeout() {} - virtual void onPipeIo(NamedPipe &namedPipe) {} - -private: - bool m_exiting = false; - std::vector m_pipes; - int m_pollInterval = 0; -}; - -#endif // EVENTLOOP_H diff --git a/deps/winpty/src/agent/InputMap.cc b/deps/winpty/src/agent/InputMap.cc deleted file mode 100644 index b1fbfc2e3..000000000 --- a/deps/winpty/src/agent/InputMap.cc +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "InputMap.h" - -#include -#include -#include -#include - -#include "DebugShowInput.h" -#include "SimplePool.h" -#include "../shared/DebugClient.h" -#include "../shared/UnixCtrlChars.h" -#include "../shared/WinptyAssert.h" -#include "../shared/winpty_snprintf.h" - -namespace { - -static const char *getVirtualKeyString(int virtualKey) -{ - switch (virtualKey) { -#define WINPTY_GVKS_KEY(x) case VK_##x: return #x; - WINPTY_GVKS_KEY(RBUTTON) WINPTY_GVKS_KEY(F9) - WINPTY_GVKS_KEY(CANCEL) WINPTY_GVKS_KEY(F10) - WINPTY_GVKS_KEY(MBUTTON) WINPTY_GVKS_KEY(F11) - WINPTY_GVKS_KEY(XBUTTON1) WINPTY_GVKS_KEY(F12) - WINPTY_GVKS_KEY(XBUTTON2) WINPTY_GVKS_KEY(F13) - WINPTY_GVKS_KEY(BACK) WINPTY_GVKS_KEY(F14) - WINPTY_GVKS_KEY(TAB) WINPTY_GVKS_KEY(F15) - WINPTY_GVKS_KEY(CLEAR) WINPTY_GVKS_KEY(F16) - WINPTY_GVKS_KEY(RETURN) WINPTY_GVKS_KEY(F17) - WINPTY_GVKS_KEY(SHIFT) WINPTY_GVKS_KEY(F18) - WINPTY_GVKS_KEY(CONTROL) WINPTY_GVKS_KEY(F19) - WINPTY_GVKS_KEY(MENU) WINPTY_GVKS_KEY(F20) - WINPTY_GVKS_KEY(PAUSE) WINPTY_GVKS_KEY(F21) - WINPTY_GVKS_KEY(CAPITAL) WINPTY_GVKS_KEY(F22) - WINPTY_GVKS_KEY(HANGUL) WINPTY_GVKS_KEY(F23) - WINPTY_GVKS_KEY(JUNJA) WINPTY_GVKS_KEY(F24) - WINPTY_GVKS_KEY(FINAL) WINPTY_GVKS_KEY(NUMLOCK) - WINPTY_GVKS_KEY(KANJI) WINPTY_GVKS_KEY(SCROLL) - WINPTY_GVKS_KEY(ESCAPE) WINPTY_GVKS_KEY(LSHIFT) - WINPTY_GVKS_KEY(CONVERT) WINPTY_GVKS_KEY(RSHIFT) - WINPTY_GVKS_KEY(NONCONVERT) WINPTY_GVKS_KEY(LCONTROL) - WINPTY_GVKS_KEY(ACCEPT) WINPTY_GVKS_KEY(RCONTROL) - WINPTY_GVKS_KEY(MODECHANGE) WINPTY_GVKS_KEY(LMENU) - WINPTY_GVKS_KEY(SPACE) WINPTY_GVKS_KEY(RMENU) - WINPTY_GVKS_KEY(PRIOR) WINPTY_GVKS_KEY(BROWSER_BACK) - WINPTY_GVKS_KEY(NEXT) WINPTY_GVKS_KEY(BROWSER_FORWARD) - WINPTY_GVKS_KEY(END) WINPTY_GVKS_KEY(BROWSER_REFRESH) - WINPTY_GVKS_KEY(HOME) WINPTY_GVKS_KEY(BROWSER_STOP) - WINPTY_GVKS_KEY(LEFT) WINPTY_GVKS_KEY(BROWSER_SEARCH) - WINPTY_GVKS_KEY(UP) WINPTY_GVKS_KEY(BROWSER_FAVORITES) - WINPTY_GVKS_KEY(RIGHT) WINPTY_GVKS_KEY(BROWSER_HOME) - WINPTY_GVKS_KEY(DOWN) WINPTY_GVKS_KEY(VOLUME_MUTE) - WINPTY_GVKS_KEY(SELECT) WINPTY_GVKS_KEY(VOLUME_DOWN) - WINPTY_GVKS_KEY(PRINT) WINPTY_GVKS_KEY(VOLUME_UP) - WINPTY_GVKS_KEY(EXECUTE) WINPTY_GVKS_KEY(MEDIA_NEXT_TRACK) - WINPTY_GVKS_KEY(SNAPSHOT) WINPTY_GVKS_KEY(MEDIA_PREV_TRACK) - WINPTY_GVKS_KEY(INSERT) WINPTY_GVKS_KEY(MEDIA_STOP) - WINPTY_GVKS_KEY(DELETE) WINPTY_GVKS_KEY(MEDIA_PLAY_PAUSE) - WINPTY_GVKS_KEY(HELP) WINPTY_GVKS_KEY(LAUNCH_MAIL) - WINPTY_GVKS_KEY(LWIN) WINPTY_GVKS_KEY(LAUNCH_MEDIA_SELECT) - WINPTY_GVKS_KEY(RWIN) WINPTY_GVKS_KEY(LAUNCH_APP1) - WINPTY_GVKS_KEY(APPS) WINPTY_GVKS_KEY(LAUNCH_APP2) - WINPTY_GVKS_KEY(SLEEP) WINPTY_GVKS_KEY(OEM_1) - WINPTY_GVKS_KEY(NUMPAD0) WINPTY_GVKS_KEY(OEM_PLUS) - WINPTY_GVKS_KEY(NUMPAD1) WINPTY_GVKS_KEY(OEM_COMMA) - WINPTY_GVKS_KEY(NUMPAD2) WINPTY_GVKS_KEY(OEM_MINUS) - WINPTY_GVKS_KEY(NUMPAD3) WINPTY_GVKS_KEY(OEM_PERIOD) - WINPTY_GVKS_KEY(NUMPAD4) WINPTY_GVKS_KEY(OEM_2) - WINPTY_GVKS_KEY(NUMPAD5) WINPTY_GVKS_KEY(OEM_3) - WINPTY_GVKS_KEY(NUMPAD6) WINPTY_GVKS_KEY(OEM_4) - WINPTY_GVKS_KEY(NUMPAD7) WINPTY_GVKS_KEY(OEM_5) - WINPTY_GVKS_KEY(NUMPAD8) WINPTY_GVKS_KEY(OEM_6) - WINPTY_GVKS_KEY(NUMPAD9) WINPTY_GVKS_KEY(OEM_7) - WINPTY_GVKS_KEY(MULTIPLY) WINPTY_GVKS_KEY(OEM_8) - WINPTY_GVKS_KEY(ADD) WINPTY_GVKS_KEY(OEM_102) - WINPTY_GVKS_KEY(SEPARATOR) WINPTY_GVKS_KEY(PROCESSKEY) - WINPTY_GVKS_KEY(SUBTRACT) WINPTY_GVKS_KEY(PACKET) - WINPTY_GVKS_KEY(DECIMAL) WINPTY_GVKS_KEY(ATTN) - WINPTY_GVKS_KEY(DIVIDE) WINPTY_GVKS_KEY(CRSEL) - WINPTY_GVKS_KEY(F1) WINPTY_GVKS_KEY(EXSEL) - WINPTY_GVKS_KEY(F2) WINPTY_GVKS_KEY(EREOF) - WINPTY_GVKS_KEY(F3) WINPTY_GVKS_KEY(PLAY) - WINPTY_GVKS_KEY(F4) WINPTY_GVKS_KEY(ZOOM) - WINPTY_GVKS_KEY(F5) WINPTY_GVKS_KEY(NONAME) - WINPTY_GVKS_KEY(F6) WINPTY_GVKS_KEY(PA1) - WINPTY_GVKS_KEY(F7) WINPTY_GVKS_KEY(OEM_CLEAR) - WINPTY_GVKS_KEY(F8) -#undef WINPTY_GVKS_KEY - default: return NULL; - } -} - -} // anonymous namespace - -std::string InputMap::Key::toString() const { - std::string ret; - ret += controlKeyStatePrefix(keyState); - char buf[256]; - const char *vkString = getVirtualKeyString(virtualKey); - if (vkString != NULL) { - ret += vkString; - } else if ((virtualKey >= 'A' && virtualKey <= 'Z') || - (virtualKey >= '0' && virtualKey <= '9')) { - ret += static_cast(virtualKey); - } else { - winpty_snprintf(buf, "%#x", virtualKey); - ret += buf; - } - if (unicodeChar >= 32 && unicodeChar <= 126) { - winpty_snprintf(buf, " ch='%c'", - static_cast(unicodeChar)); - } else { - winpty_snprintf(buf, " ch=%#x", - static_cast(unicodeChar)); - } - ret += buf; - return ret; -} - -void InputMap::set(const char *encoding, int encodingLen, const Key &key) { - ASSERT(encodingLen > 0); - setHelper(m_root, encoding, encodingLen, key); -} - -void InputMap::setHelper(Node &node, const char *encoding, int encodingLen, const Key &key) { - if (encodingLen == 0) { - node.key = key; - } else { - setHelper(getOrCreateChild(node, encoding[0]), encoding + 1, encodingLen - 1, key); - } -} - -InputMap::Node &InputMap::getOrCreateChild(Node &node, unsigned char ch) { - Node *ret = getChild(node, ch); - if (ret != NULL) { - return *ret; - } - if (node.childCount < Node::kTinyCount) { - // Maintain sorted order for the sake of the InputMap dumping. - int insertIndex = node.childCount; - for (int i = 0; i < node.childCount; ++i) { - if (ch < node.u.tiny.values[i]) { - insertIndex = i; - break; - } - } - for (int j = node.childCount; j > insertIndex; --j) { - node.u.tiny.values[j] = node.u.tiny.values[j - 1]; - node.u.tiny.children[j] = node.u.tiny.children[j - 1]; - } - node.u.tiny.values[insertIndex] = ch; - node.u.tiny.children[insertIndex] = ret = m_nodePool.alloc(); - ++node.childCount; - return *ret; - } - if (node.childCount == Node::kTinyCount) { - Branch *branch = m_branchPool.alloc(); - for (int i = 0; i < node.childCount; ++i) { - branch->children[node.u.tiny.values[i]] = node.u.tiny.children[i]; - } - node.u.branch = branch; - } - node.u.branch->children[ch] = ret = m_nodePool.alloc(); - ++node.childCount; - return *ret; -} - -// Find the longest matching key and node. -int InputMap::lookupKey(const char *input, int inputSize, - Key &keyOut, bool &incompleteOut) const { - keyOut = kKeyZero; - incompleteOut = false; - - const Node *node = &m_root; - InputMap::Key longestMatch = kKeyZero; - int longestMatchLen = 0; - - for (int i = 0; i < inputSize; ++i) { - unsigned char ch = input[i]; - node = getChild(*node, ch); - if (node == NULL) { - keyOut = longestMatch; - return longestMatchLen; - } else if (node->hasKey()) { - longestMatchLen = i + 1; - longestMatch = node->key; - } - } - keyOut = longestMatch; - incompleteOut = node->childCount > 0; - return longestMatchLen; -} - -void InputMap::dumpInputMap() const { - std::string encoding; - dumpInputMapHelper(m_root, encoding); -} - -void InputMap::dumpInputMapHelper( - const Node &node, std::string &encoding) const { - if (node.hasKey()) { - trace("%s -> %s", - encoding.c_str(), - node.key.toString().c_str()); - } - for (int i = 0; i < 256; ++i) { - const Node *child = getChild(node, i); - if (child != NULL) { - size_t oldSize = encoding.size(); - if (!encoding.empty()) { - encoding.push_back(' '); - } - char ctrlChar = decodeUnixCtrlChar(i); - if (ctrlChar != '\0') { - encoding.push_back('^'); - encoding.push_back(static_cast(ctrlChar)); - } else if (i == ' ') { - encoding.append("' '"); - } else { - encoding.push_back(static_cast(i)); - } - dumpInputMapHelper(*child, encoding); - encoding.resize(oldSize); - } - } -} diff --git a/deps/winpty/src/agent/InputMap.h b/deps/winpty/src/agent/InputMap.h deleted file mode 100644 index 9a666c797..000000000 --- a/deps/winpty/src/agent/InputMap.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef INPUT_MAP_H -#define INPUT_MAP_H - -#include -#include -#include - -#include - -#include "SimplePool.h" -#include "../shared/WinptyAssert.h" - -class InputMap { -public: - struct Key { - uint16_t virtualKey; - uint32_t unicodeChar; - uint16_t keyState; - - std::string toString() const; - }; - -private: - struct Node; - - struct Branch { - Branch() { - memset(&children, 0, sizeof(children)); - } - - Node *children[256]; - }; - - struct Node { - Node() : childCount(0) { - Key zeroKey = { 0, 0, 0 }; - key = zeroKey; - } - - Key key; - int childCount; - enum { kTinyCount = 8 }; - union { - Branch *branch; - struct { - unsigned char values[kTinyCount]; - Node *children[kTinyCount]; - } tiny; - } u; - - bool hasKey() const { - return key.virtualKey != 0 || key.unicodeChar != 0; - } - }; - -private: - SimplePool m_nodePool; - SimplePool m_branchPool; - Node m_root; - -public: - void set(const char *encoding, int encodingLen, const Key &key); - int lookupKey(const char *input, int inputSize, - Key &keyOut, bool &incompleteOut) const; - void dumpInputMap() const; - -private: - Node *getChild(Node &node, unsigned char ch) { - return const_cast(getChild(static_cast(node), ch)); - } - - const Node *getChild(const Node &node, unsigned char ch) const { - if (node.childCount <= Node::kTinyCount) { - for (int i = 0; i < node.childCount; ++i) { - if (node.u.tiny.values[i] == ch) { - return node.u.tiny.children[i]; - } - } - return NULL; - } else { - return node.u.branch->children[ch]; - } - } - - void setHelper(Node &node, const char *encoding, int encodingLen, const Key &key); - Node &getOrCreateChild(Node &node, unsigned char ch); - void dumpInputMapHelper(const Node &node, std::string &encoding) const; -}; - -const InputMap::Key kKeyZero = { 0, 0, 0 }; - -void dumpInputMap(InputMap &inputMap); - -#endif // INPUT_MAP_H diff --git a/deps/winpty/src/agent/LargeConsoleRead.cc b/deps/winpty/src/agent/LargeConsoleRead.cc deleted file mode 100644 index 80ac640e4..000000000 --- a/deps/winpty/src/agent/LargeConsoleRead.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "LargeConsoleRead.h" - -#include - -#include "../shared/WindowsVersion.h" -#include "Scraper.h" -#include "Win32ConsoleBuffer.h" - -LargeConsoleReadBuffer::LargeConsoleReadBuffer() : - m_rect(0, 0, 0, 0), m_rectWidth(0) -{ -} - -void largeConsoleRead(LargeConsoleReadBuffer &out, - Win32ConsoleBuffer &buffer, - const SmallRect &readArea, - WORD attributesMask) { - ASSERT(readArea.Left >= 0 && - readArea.Top >= 0 && - readArea.Right >= readArea.Left && - readArea.Bottom >= readArea.Top && - readArea.width() <= MAX_CONSOLE_WIDTH); - const size_t count = readArea.width() * readArea.height(); - if (out.m_data.size() < count) { - out.m_data.resize(count); - } - out.m_rect = readArea; - out.m_rectWidth = readArea.width(); - - static const bool useLargeReads = isAtLeastWindows8(); - if (useLargeReads) { - buffer.read(readArea, out.m_data.data()); - } else { - const int maxReadLines = std::max(1, MAX_CONSOLE_WIDTH / readArea.width()); - int curLine = readArea.Top; - while (curLine <= readArea.Bottom) { - const SmallRect subReadArea( - readArea.Left, - curLine, - readArea.width(), - std::min(maxReadLines, readArea.Bottom + 1 - curLine)); - buffer.read(subReadArea, out.lineDataMut(curLine)); - curLine = subReadArea.Bottom + 1; - } - } - if (attributesMask != static_cast(~0)) { - for (size_t i = 0; i < count; ++i) { - out.m_data[i].Attributes &= attributesMask; - } - } -} diff --git a/deps/winpty/src/agent/LargeConsoleRead.h b/deps/winpty/src/agent/LargeConsoleRead.h deleted file mode 100644 index 1bcf2c023..000000000 --- a/deps/winpty/src/agent/LargeConsoleRead.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef LARGE_CONSOLE_READ_H -#define LARGE_CONSOLE_READ_H - -#include -#include - -#include - -#include "SmallRect.h" -#include "../shared/DebugClient.h" -#include "../shared/WinptyAssert.h" - -class Win32ConsoleBuffer; - -class LargeConsoleReadBuffer { -public: - LargeConsoleReadBuffer(); - const SmallRect &rect() const { return m_rect; } - const CHAR_INFO *lineData(int line) const { - validateLineNumber(line); - return &m_data[(line - m_rect.Top) * m_rectWidth]; - } - -private: - CHAR_INFO *lineDataMut(int line) { - validateLineNumber(line); - return &m_data[(line - m_rect.Top) * m_rectWidth]; - } - - void validateLineNumber(int line) const { - if (line < m_rect.Top || line > m_rect.Bottom) { - trace("Fatal error: LargeConsoleReadBuffer: invalid line %d for " - "read rect %s", line, m_rect.toString().c_str()); - abort(); - } - } - - SmallRect m_rect; - int m_rectWidth; - std::vector m_data; - - friend void largeConsoleRead(LargeConsoleReadBuffer &out, - Win32ConsoleBuffer &buffer, - const SmallRect &readArea, - WORD attributesMask); -}; - -#endif // LARGE_CONSOLE_READ_H diff --git a/deps/winpty/src/agent/NamedPipe.cc b/deps/winpty/src/agent/NamedPipe.cc deleted file mode 100644 index 64044e6e5..000000000 --- a/deps/winpty/src/agent/NamedPipe.cc +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include - -#include - -#include "EventLoop.h" -#include "NamedPipe.h" -#include "../shared/DebugClient.h" -#include "../shared/StringUtil.h" -#include "../shared/WindowsSecurity.h" -#include "../shared/WinptyAssert.h" - -// Returns true if anything happens (data received, data sent, pipe error). -bool NamedPipe::serviceIo(std::vector *waitHandles) -{ - bool justConnected = false; - const auto kError = ServiceResult::Error; - const auto kProgress = ServiceResult::Progress; - const auto kNoProgress = ServiceResult::NoProgress; - if (m_handle == NULL) { - return false; - } - if (m_connectEvent.get() != nullptr) { - // We're still connecting this server pipe. Check whether the pipe is - // now connected. If it isn't, add the pipe to the list of handles to - // wait on. - DWORD actual = 0; - BOOL success = - GetOverlappedResult(m_handle, &m_connectOver, &actual, FALSE); - if (!success && GetLastError() == ERROR_PIPE_CONNECTED) { - // I'm not sure this can happen, but it's easy to handle if it - // does. - success = TRUE; - } - if (!success) { - ASSERT(GetLastError() == ERROR_IO_INCOMPLETE && - "Pended ConnectNamedPipe call failed"); - waitHandles->push_back(m_connectEvent.get()); - } else { - TRACE("Server pipe [%s] connected", - utf8FromWide(m_name).c_str()); - m_connectEvent.dispose(); - startPipeWorkers(); - justConnected = true; - } - } - const auto readProgress = m_inputWorker ? m_inputWorker->service() : kNoProgress; - const auto writeProgress = m_outputWorker ? m_outputWorker->service() : kNoProgress; - if (readProgress == kError || writeProgress == kError) { - closePipe(); - return true; - } - if (m_inputWorker && m_inputWorker->getWaitEvent() != nullptr) { - waitHandles->push_back(m_inputWorker->getWaitEvent()); - } - if (m_outputWorker && m_outputWorker->getWaitEvent() != nullptr) { - waitHandles->push_back(m_outputWorker->getWaitEvent()); - } - return justConnected - || readProgress == kProgress - || writeProgress == kProgress; -} - -// manual reset, initially unset -static OwnedHandle createEvent() { - HANDLE ret = CreateEventW(nullptr, TRUE, FALSE, nullptr); - ASSERT(ret != nullptr && "CreateEventW failed"); - return OwnedHandle(ret); -} - -NamedPipe::IoWorker::IoWorker(NamedPipe &namedPipe) : - m_namedPipe(namedPipe), - m_event(createEvent()) -{ -} - -NamedPipe::ServiceResult NamedPipe::IoWorker::service() -{ - ServiceResult progress = ServiceResult::NoProgress; - if (m_pending) { - DWORD actual = 0; - BOOL ret = GetOverlappedResult(m_namedPipe.m_handle, &m_over, &actual, FALSE); - if (!ret) { - if (GetLastError() == ERROR_IO_INCOMPLETE) { - // There is a pending I/O. - return progress; - } else { - // Pipe error. - return ServiceResult::Error; - } - } - ResetEvent(m_event.get()); - m_pending = false; - completeIo(actual); - m_currentIoSize = 0; - progress = ServiceResult::Progress; - } - DWORD nextSize = 0; - bool isRead = false; - while (shouldIssueIo(&nextSize, &isRead)) { - m_currentIoSize = nextSize; - DWORD actual = 0; - memset(&m_over, 0, sizeof(m_over)); - m_over.hEvent = m_event.get(); - BOOL ret = isRead - ? ReadFile(m_namedPipe.m_handle, m_buffer, nextSize, &actual, &m_over) - : WriteFile(m_namedPipe.m_handle, m_buffer, nextSize, &actual, &m_over); - if (!ret) { - if (GetLastError() == ERROR_IO_PENDING) { - // There is a pending I/O. - m_pending = true; - return progress; - } else { - // Pipe error. - return ServiceResult::Error; - } - } - ResetEvent(m_event.get()); - completeIo(actual); - m_currentIoSize = 0; - progress = ServiceResult::Progress; - } - return progress; -} - -// This function is called after CancelIo has returned. We need to block until -// the I/O operations have completed, which should happen very quickly. -// https://blogs.msdn.microsoft.com/oldnewthing/20110202-00/?p=11613 -void NamedPipe::IoWorker::waitForCanceledIo() -{ - if (m_pending) { - DWORD actual = 0; - GetOverlappedResult(m_namedPipe.m_handle, &m_over, &actual, TRUE); - m_pending = false; - } -} - -HANDLE NamedPipe::IoWorker::getWaitEvent() -{ - return m_pending ? m_event.get() : NULL; -} - -void NamedPipe::InputWorker::completeIo(DWORD size) -{ - m_namedPipe.m_inQueue.append(m_buffer, size); -} - -bool NamedPipe::InputWorker::shouldIssueIo(DWORD *size, bool *isRead) -{ - *isRead = true; - ASSERT(!m_namedPipe.isConnecting()); - if (m_namedPipe.isClosed()) { - return false; - } else if (m_namedPipe.m_inQueue.size() < m_namedPipe.readBufferSize()) { - *size = kIoSize; - return true; - } else { - return false; - } -} - -void NamedPipe::OutputWorker::completeIo(DWORD size) -{ - ASSERT(size == m_currentIoSize); -} - -bool NamedPipe::OutputWorker::shouldIssueIo(DWORD *size, bool *isRead) -{ - *isRead = false; - if (!m_namedPipe.m_outQueue.empty()) { - auto &out = m_namedPipe.m_outQueue; - const DWORD writeSize = std::min(out.size(), kIoSize); - std::copy(&out[0], &out[writeSize], m_buffer); - out.erase(0, writeSize); - *size = writeSize; - return true; - } else { - return false; - } -} - -DWORD NamedPipe::OutputWorker::getPendingIoSize() -{ - return m_pending ? m_currentIoSize : 0; -} - -void NamedPipe::openServerPipe(LPCWSTR pipeName, OpenMode::t openMode, - int outBufferSize, int inBufferSize) { - ASSERT(isClosed()); - ASSERT((openMode & OpenMode::Duplex) != 0); - const DWORD winOpenMode = - ((openMode & OpenMode::Reading) ? PIPE_ACCESS_INBOUND : 0) - | ((openMode & OpenMode::Writing) ? PIPE_ACCESS_OUTBOUND : 0) - | FILE_FLAG_FIRST_PIPE_INSTANCE - | FILE_FLAG_OVERLAPPED; - const auto sd = createPipeSecurityDescriptorOwnerFullControl(); - ASSERT(sd && "error creating data pipe SECURITY_DESCRIPTOR"); - SECURITY_ATTRIBUTES sa = {}; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = sd.get(); - HANDLE handle = CreateNamedPipeW( - pipeName, - /*dwOpenMode=*/winOpenMode, - /*dwPipeMode=*/rejectRemoteClientsPipeFlag(), - /*nMaxInstances=*/1, - /*nOutBufferSize=*/outBufferSize, - /*nInBufferSize=*/inBufferSize, - /*nDefaultTimeOut=*/30000, - &sa); - TRACE("opened server pipe [%s], handle == %p", - utf8FromWide(pipeName).c_str(), handle); - ASSERT(handle != INVALID_HANDLE_VALUE && "Could not open server pipe"); - m_name = pipeName; - m_handle = handle; - m_openMode = openMode; - - // Start an asynchronous connection attempt. - m_connectEvent = createEvent(); - memset(&m_connectOver, 0, sizeof(m_connectOver)); - m_connectOver.hEvent = m_connectEvent.get(); - BOOL success = ConnectNamedPipe(m_handle, &m_connectOver); - const auto err = GetLastError(); - if (!success && err == ERROR_PIPE_CONNECTED) { - success = TRUE; - } - if (success) { - TRACE("Server pipe [%s] connected", utf8FromWide(pipeName).c_str()); - m_connectEvent.dispose(); - startPipeWorkers(); - } else if (err != ERROR_IO_PENDING) { - ASSERT(false && "ConnectNamedPipe call failed"); - } -} - -void NamedPipe::connectToServer(LPCWSTR pipeName, OpenMode::t openMode) -{ - ASSERT(isClosed()); - ASSERT((openMode & OpenMode::Duplex) != 0); - HANDLE handle = CreateFileW( - pipeName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | FILE_FLAG_OVERLAPPED, - NULL); - TRACE("connected to [%s], handle == %p", - utf8FromWide(pipeName).c_str(), handle); - ASSERT(handle != INVALID_HANDLE_VALUE && "Could not connect to pipe"); - m_name = pipeName; - m_handle = handle; - m_openMode = openMode; - startPipeWorkers(); -} - -void NamedPipe::startPipeWorkers() -{ - if (m_openMode & OpenMode::Reading) { - m_inputWorker.reset(new InputWorker(*this)); - } - if (m_openMode & OpenMode::Writing) { - m_outputWorker.reset(new OutputWorker(*this)); - } -} - -size_t NamedPipe::bytesToSend() -{ - ASSERT(m_openMode & OpenMode::Writing); - auto ret = m_outQueue.size(); - if (m_outputWorker != NULL) { - ret += m_outputWorker->getPendingIoSize(); - } - return ret; -} - -void NamedPipe::write(const void *data, size_t size) -{ - ASSERT(m_openMode & OpenMode::Writing); - m_outQueue.append(reinterpret_cast(data), size); -} - -void NamedPipe::write(const char *text) -{ - write(text, strlen(text)); -} - -size_t NamedPipe::readBufferSize() -{ - ASSERT(m_openMode & OpenMode::Reading); - return m_readBufferSize; -} - -void NamedPipe::setReadBufferSize(size_t size) -{ - ASSERT(m_openMode & OpenMode::Reading); - m_readBufferSize = size; -} - -size_t NamedPipe::bytesAvailable() -{ - ASSERT(m_openMode & OpenMode::Reading); - return m_inQueue.size(); -} - -size_t NamedPipe::peek(void *data, size_t size) -{ - ASSERT(m_openMode & OpenMode::Reading); - const auto out = reinterpret_cast(data); - const size_t ret = std::min(size, m_inQueue.size()); - std::copy(&m_inQueue[0], &m_inQueue[ret], out); - return ret; -} - -size_t NamedPipe::read(void *data, size_t size) -{ - size_t ret = peek(data, size); - m_inQueue.erase(0, ret); - return ret; -} - -std::string NamedPipe::readToString(size_t size) -{ - ASSERT(m_openMode & OpenMode::Reading); - size_t retSize = std::min(size, m_inQueue.size()); - std::string ret = m_inQueue.substr(0, retSize); - m_inQueue.erase(0, retSize); - return ret; -} - -std::string NamedPipe::readAllToString() -{ - ASSERT(m_openMode & OpenMode::Reading); - std::string ret = m_inQueue; - m_inQueue.clear(); - return ret; -} - -void NamedPipe::closePipe() -{ - if (m_handle == NULL) { - return; - } - CancelIo(m_handle); - if (m_connectEvent.get() != nullptr) { - DWORD actual = 0; - GetOverlappedResult(m_handle, &m_connectOver, &actual, TRUE); - m_connectEvent.dispose(); - } - if (m_inputWorker) { - m_inputWorker->waitForCanceledIo(); - m_inputWorker.reset(); - } - if (m_outputWorker) { - m_outputWorker->waitForCanceledIo(); - m_outputWorker.reset(); - } - CloseHandle(m_handle); - m_handle = NULL; -} diff --git a/deps/winpty/src/agent/NamedPipe.h b/deps/winpty/src/agent/NamedPipe.h deleted file mode 100644 index 0a4d8b0c7..000000000 --- a/deps/winpty/src/agent/NamedPipe.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef NAMEDPIPE_H -#define NAMEDPIPE_H - -#include - -#include -#include -#include - -#include "../shared/OwnedHandle.h" - -class EventLoop; - -class NamedPipe -{ -private: - // The EventLoop uses these private members. - friend class EventLoop; - NamedPipe() {} - ~NamedPipe() { closePipe(); } - bool serviceIo(std::vector *waitHandles); - void startPipeWorkers(); - - enum class ServiceResult { NoProgress, Error, Progress }; - -private: - class IoWorker - { - public: - IoWorker(NamedPipe &namedPipe); - virtual ~IoWorker() {} - ServiceResult service(); - void waitForCanceledIo(); - HANDLE getWaitEvent(); - protected: - NamedPipe &m_namedPipe; - bool m_pending = false; - DWORD m_currentIoSize = 0; - OwnedHandle m_event; - OVERLAPPED m_over = {}; - enum { kIoSize = 64 * 1024 }; - char m_buffer[kIoSize]; - virtual void completeIo(DWORD size) = 0; - virtual bool shouldIssueIo(DWORD *size, bool *isRead) = 0; - }; - - class InputWorker : public IoWorker - { - public: - InputWorker(NamedPipe &namedPipe) : IoWorker(namedPipe) {} - protected: - virtual void completeIo(DWORD size) override; - virtual bool shouldIssueIo(DWORD *size, bool *isRead) override; - }; - - class OutputWorker : public IoWorker - { - public: - OutputWorker(NamedPipe &namedPipe) : IoWorker(namedPipe) {} - DWORD getPendingIoSize(); - protected: - virtual void completeIo(DWORD size) override; - virtual bool shouldIssueIo(DWORD *size, bool *isRead) override; - }; - -public: - struct OpenMode { - typedef int t; - enum { None = 0, Reading = 1, Writing = 2, Duplex = 3 }; - }; - - std::wstring name() const { return m_name; } - void openServerPipe(LPCWSTR pipeName, OpenMode::t openMode, - int outBufferSize, int inBufferSize); - void connectToServer(LPCWSTR pipeName, OpenMode::t openMode); - size_t bytesToSend(); - void write(const void *data, size_t size); - void write(const char *text); - size_t readBufferSize(); - void setReadBufferSize(size_t size); - size_t bytesAvailable(); - size_t peek(void *data, size_t size); - size_t read(void *data, size_t size); - std::string readToString(size_t size); - std::string readAllToString(); - void closePipe(); - bool isClosed() { return m_handle == nullptr; } - bool isConnected() { return !isClosed() && !isConnecting(); } - bool isConnecting() { return m_connectEvent.get() != nullptr; } - -private: - // Input/output buffers - std::wstring m_name; - OVERLAPPED m_connectOver = {}; - OwnedHandle m_connectEvent; - OpenMode::t m_openMode = OpenMode::None; - size_t m_readBufferSize = 64 * 1024; - std::string m_inQueue; - std::string m_outQueue; - HANDLE m_handle = nullptr; - std::unique_ptr m_inputWorker; - std::unique_ptr m_outputWorker; -}; - -#endif // NAMEDPIPE_H diff --git a/deps/winpty/src/agent/Scraper.cc b/deps/winpty/src/agent/Scraper.cc deleted file mode 100644 index 21f9c6710..000000000 --- a/deps/winpty/src/agent/Scraper.cc +++ /dev/null @@ -1,699 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Scraper.h" - -#include - -#include - -#include -#include - -#include "../shared/WinptyAssert.h" -#include "../shared/winpty_snprintf.h" - -#include "ConsoleFont.h" -#include "Win32Console.h" -#include "Win32ConsoleBuffer.h" - -namespace { - -template -T constrained(T min, T val, T max) { - ASSERT(min <= max); - return std::min(std::max(min, val), max); -} - -} // anonymous namespace - -Scraper::Scraper( - Win32Console &console, - Win32ConsoleBuffer &buffer, - std::unique_ptr terminal, - Coord initialSize) : - m_console(console), - m_terminal(std::move(terminal)), - m_ptySize(initialSize) -{ - m_consoleBuffer = &buffer; - - resetConsoleTracking(Terminal::OmitClear, buffer.windowRect().top()); - - m_bufferData.resize(BUFFER_LINE_COUNT); - - // Setup the initial screen buffer and window size. - // - // Use SetConsoleWindowInfo to shrink the console window as much as - // possible -- to a 1x1 cell at the top-left. This call always succeeds. - // Prior to the new Windows 10 console, it also actually resizes the GUI - // window to 1x1 cell. Nevertheless, even though the GUI window can - // therefore be narrower than its minimum, calling - // SetConsoleScreenBufferSize with a 1x1 size still fails. - // - // While the small font intends to support large buffers, a user could - // still hit a limit imposed by their monitor width, so cap the new window - // size to GetLargestConsoleWindowSize(). - setSmallFont(buffer.conout(), initialSize.X, m_console.isNewW10()); - buffer.moveWindow(SmallRect(0, 0, 1, 1)); - buffer.resizeBufferRange(Coord(initialSize.X, BUFFER_LINE_COUNT)); - const auto largest = GetLargestConsoleWindowSize(buffer.conout()); - buffer.moveWindow(SmallRect( - 0, 0, - std::min(initialSize.X, largest.X), - std::min(initialSize.Y, largest.Y))); - buffer.setCursorPosition(Coord(0, 0)); - - // For the sake of the color translation heuristic, set the console color - // to LtGray-on-Black. - buffer.setTextAttribute(Win32ConsoleBuffer::kDefaultAttributes); - buffer.clearAllLines(m_consoleBuffer->bufferInfo()); - - m_consoleBuffer = nullptr; -} - -Scraper::~Scraper() -{ -} - -// Whether or not the agent is frozen on entry, it will be frozen on exit. -void Scraper::resizeWindow(Win32ConsoleBuffer &buffer, - Coord newSize, - ConsoleScreenBufferInfo &finalInfoOut) -{ - m_consoleBuffer = &buffer; - m_ptySize = newSize; - syncConsoleContentAndSize(true, finalInfoOut); - m_consoleBuffer = nullptr; -} - -// This function may freeze the agent, but it will not unfreeze it. -void Scraper::scrapeBuffer(Win32ConsoleBuffer &buffer, - ConsoleScreenBufferInfo &finalInfoOut) -{ - m_consoleBuffer = &buffer; - syncConsoleContentAndSize(false, finalInfoOut); - m_consoleBuffer = nullptr; -} - -void Scraper::resetConsoleTracking( - Terminal::SendClearFlag sendClear, int64_t scrapedLineCount) -{ - for (ConsoleLine &line : m_bufferData) { - line.reset(); - } - m_syncRow = -1; - m_scrapedLineCount = scrapedLineCount; - m_scrolledCount = 0; - m_maxBufferedLine = -1; - m_dirtyWindowTop = -1; - m_dirtyLineCount = 0; - m_terminal->reset(sendClear, m_scrapedLineCount); -} - -// Detect window movement. If the window moves down (presumably as a -// result of scrolling), then assume that all screen buffer lines down to -// the bottom of the window are dirty. -void Scraper::markEntireWindowDirty(const SmallRect &windowRect) -{ - m_dirtyLineCount = std::max(m_dirtyLineCount, - windowRect.top() + windowRect.height()); -} - -// Scan the screen buffer and advance the dirty line count when we find -// non-empty lines. -void Scraper::scanForDirtyLines(const SmallRect &windowRect) -{ - const int w = m_readBuffer.rect().width(); - ASSERT(m_dirtyLineCount >= 1); - const CHAR_INFO *const prevLine = - m_readBuffer.lineData(m_dirtyLineCount - 1); - WORD prevLineAttr = prevLine[w - 1].Attributes; - const int stopLine = windowRect.top() + windowRect.height(); - - for (int line = m_dirtyLineCount; line < stopLine; ++line) { - const CHAR_INFO *lineData = m_readBuffer.lineData(line); - for (int col = 0; col < w; ++col) { - const WORD colAttr = lineData[col].Attributes; - if (lineData[col].Char.UnicodeChar != L' ' || - colAttr != prevLineAttr) { - m_dirtyLineCount = line + 1; - break; - } - } - prevLineAttr = lineData[w - 1].Attributes; - } -} - -// Clear lines in the line buffer. The `firstRow` parameter is in -// screen-buffer coordinates. -void Scraper::clearBufferLines( - const int firstRow, - const int count) -{ - ASSERT(!m_directMode); - for (int row = firstRow; row < firstRow + count; ++row) { - const int64_t bufLine = row + m_scrolledCount; - m_maxBufferedLine = std::max(m_maxBufferedLine, bufLine); - m_bufferData[bufLine % BUFFER_LINE_COUNT].blank( - Win32ConsoleBuffer::kDefaultAttributes); - } -} - -static bool cursorInWindow(const ConsoleScreenBufferInfo &info) -{ - return info.dwCursorPosition.Y >= info.srWindow.Top && - info.dwCursorPosition.Y <= info.srWindow.Bottom; -} - -void Scraper::resizeImpl(const ConsoleScreenBufferInfo &origInfo) -{ - ASSERT(m_console.frozen()); - const int cols = m_ptySize.X; - const int rows = m_ptySize.Y; - Coord finalBufferSize; - - { - // - // To accommodate Windows 10, erase all lines up to the top of the - // visible window. It's hard to tell whether this is strictly - // necessary. It ensures that the sync marker won't move downward, - // and it ensures that we won't repeat lines that have already scrolled - // up into the scrollback. - // - // It *is* possible for these blank lines to reappear in the visible - // window (e.g. if the window is made taller), but because we blanked - // the lines in the line buffer, we still don't output them again. - // - const Coord origBufferSize = origInfo.bufferSize(); - const SmallRect origWindowRect = origInfo.windowRect(); - - if (m_directMode) { - for (ConsoleLine &line : m_bufferData) { - line.reset(); - } - } else { - m_consoleBuffer->clearLines(0, origWindowRect.Top, origInfo); - clearBufferLines(0, origWindowRect.Top); - if (m_syncRow != -1) { - createSyncMarker(std::min( - m_syncRow, - BUFFER_LINE_COUNT - rows - - SYNC_MARKER_LEN - - SYNC_MARKER_MARGIN)); - } - } - - finalBufferSize = Coord( - cols, - // If there was previously no scrollback (e.g. a full-screen app - // in direct mode) and we're reducing the window height, then - // reduce the console buffer's height too. - (origWindowRect.height() == origBufferSize.Y) - ? rows - : std::max(rows, origBufferSize.Y)); - - // Reset the console font size. We need to do this before shrinking - // the window, because we might need to make the font bigger to permit - // a smaller window width. Making the font smaller could expand the - // screen buffer, which would hang the conhost process in the - // Windows 10 (10240 build) if the console selection is in progress, so - // unfreeze it first. - m_console.setFrozen(false); - setSmallFont(m_consoleBuffer->conout(), cols, m_console.isNewW10()); - } - - // We try to make the font small enough so that the entire screen buffer - // fits on the monitor, but it can't be guaranteed. - const auto largest = - GetLargestConsoleWindowSize(m_consoleBuffer->conout()); - const short visibleCols = std::min(cols, largest.X); - const short visibleRows = std::min(rows, largest.Y); - - { - // Make the window small enough. We want the console frozen during - // this step so we don't accidentally move the window above the cursor. - m_console.setFrozen(true); - const auto info = m_consoleBuffer->bufferInfo(); - const auto &bufferSize = info.dwSize; - const int tmpWindowWidth = std::min(bufferSize.X, visibleCols); - const int tmpWindowHeight = std::min(bufferSize.Y, visibleRows); - SmallRect tmpWindowRect( - 0, - std::min(bufferSize.Y - tmpWindowHeight, - info.windowRect().Top), - tmpWindowWidth, - tmpWindowHeight); - if (cursorInWindow(info)) { - tmpWindowRect = tmpWindowRect.ensureLineIncluded( - info.cursorPosition().Y); - } - m_consoleBuffer->moveWindow(tmpWindowRect); - } - - { - // Resize the buffer to the final desired size. - m_console.setFrozen(false); - m_consoleBuffer->resizeBufferRange(finalBufferSize); - } - - { - // Expand the window to its full size. - m_console.setFrozen(true); - const ConsoleScreenBufferInfo info = m_consoleBuffer->bufferInfo(); - - SmallRect finalWindowRect( - 0, - std::min(info.bufferSize().Y - visibleRows, - info.windowRect().Top), - visibleCols, - visibleRows); - - // - // Once a line in the screen buffer is "dirty", it should stay visible - // in the console window, so that we continue to update its content in - // the terminal. This code is particularly (only?) necessary on - // Windows 10, where making the buffer wider can rewrap lines and move - // the console window upward. - // - if (!m_directMode && m_dirtyLineCount > finalWindowRect.Bottom + 1) { - // In theory, we avoid ensureLineIncluded, because, a massive - // amount of output could have occurred while the console was - // unfrozen, so that the *top* of the window is now below the - // dirtiest tracked line. - finalWindowRect = SmallRect( - 0, m_dirtyLineCount - visibleRows, - visibleCols, visibleRows); - } - - // Highest priority constraint: ensure that the cursor remains visible. - if (cursorInWindow(info)) { - finalWindowRect = finalWindowRect.ensureLineIncluded( - info.cursorPosition().Y); - } - - m_consoleBuffer->moveWindow(finalWindowRect); - m_dirtyWindowTop = finalWindowRect.Top; - } - - ASSERT(m_console.frozen()); -} - -void Scraper::syncConsoleContentAndSize( - bool forceResize, - ConsoleScreenBufferInfo &finalInfoOut) -{ - // We'll try to avoid freezing the console by reading large chunks (or - // all!) of the screen buffer without otherwise attempting to synchronize - // with the console application. We can only do this on Windows 10 and up - // because: - // - Prior to Windows 8, the size of a ReadConsoleOutputW call was limited - // by the ~32KB RPC buffer. - // - Prior to Windows 10, an out-of-range read region crashes the caller. - // (See misc/WindowsBugCrashReader.cc.) - // - if (!m_console.isNewW10() || forceResize) { - m_console.setFrozen(true); - } - - const ConsoleScreenBufferInfo info = m_consoleBuffer->bufferInfo(); - bool cursorVisible = true; - CONSOLE_CURSOR_INFO cursorInfo = {}; - if (!GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo)) { - trace("GetConsoleCursorInfo failed"); - } else { - cursorVisible = cursorInfo.bVisible != 0; - } - - // If an app resizes the buffer height, then we enter "direct mode", where - // we stop trying to track incremental console changes. - const bool newDirectMode = (info.bufferSize().Y != BUFFER_LINE_COUNT); - if (newDirectMode != m_directMode) { - trace("Entering %s mode", newDirectMode ? "direct" : "scrolling"); - resetConsoleTracking(Terminal::SendClear, - newDirectMode ? 0 : info.windowRect().top()); - m_directMode = newDirectMode; - - // When we switch from direct->scrolling mode, make sure the console is - // the right size. - if (!m_directMode) { - m_console.setFrozen(true); - forceResize = true; - } - } - - if (m_directMode) { - // In direct-mode, resizing the console redraws the terminal, so do it - // before scraping. - if (forceResize) { - resizeImpl(info); - } - directScrapeOutput(info, cursorVisible); - } else { - if (!m_console.frozen()) { - if (!scrollingScrapeOutput(info, cursorVisible, true)) { - m_console.setFrozen(true); - } - } - if (m_console.frozen()) { - scrollingScrapeOutput(info, cursorVisible, false); - } - // In scrolling mode, we want to scrape before resizing, because we'll - // erase everything in the console buffer up to the top of the console - // window. - if (forceResize) { - resizeImpl(info); - } - } - - finalInfoOut = forceResize ? m_consoleBuffer->bufferInfo() : info; -} - -// Try to match Windows' behavior w.r.t. to the LVB attribute flags. In some -// situations, Windows ignores the LVB flags on a character cell because of -// backwards compatibility -- apparently some programs set the flags without -// intending to enable reverse-video or underscores. -// -// [rprichard 2017-01-15] I haven't actually noticed any old programs that need -// this treatment -- the motivation for this function comes from the MSDN -// documentation for SetConsoleMode and ENABLE_LVB_GRID_WORLDWIDE. -WORD Scraper::attributesMask() -{ - const auto WINPTY_ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4u; - const auto WINPTY_ENABLE_LVB_GRID_WORLDWIDE = 0x10u; - const auto WINPTY_COMMON_LVB_REVERSE_VIDEO = 0x4000u; - const auto WINPTY_COMMON_LVB_UNDERSCORE = 0x8000u; - - const auto cp = GetConsoleOutputCP(); - const auto isCjk = (cp == 932 || cp == 936 || cp == 949 || cp == 950); - - const DWORD outputMode = [this]{ - ASSERT(this->m_consoleBuffer != nullptr); - DWORD mode = 0; - if (!GetConsoleMode(this->m_consoleBuffer->conout(), &mode)) { - mode = 0; - } - return mode; - }(); - const bool hasEnableLvbGridWorldwide = - (outputMode & WINPTY_ENABLE_LVB_GRID_WORLDWIDE) != 0; - const bool hasEnableVtProcessing = - (outputMode & WINPTY_ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0; - - // The new Windows 10 console (as of 14393) seems to respect - // COMMON_LVB_REVERSE_VIDEO even in CP437 w/o the other enabling modes, so - // try to match that behavior. - const auto isReverseSupported = - isCjk || hasEnableLvbGridWorldwide || hasEnableVtProcessing || m_console.isNewW10(); - const auto isUnderscoreSupported = - isCjk || hasEnableLvbGridWorldwide || hasEnableVtProcessing; - - WORD mask = ~0; - if (!isReverseSupported) { mask &= ~WINPTY_COMMON_LVB_REVERSE_VIDEO; } - if (!isUnderscoreSupported) { mask &= ~WINPTY_COMMON_LVB_UNDERSCORE; } - return mask; -} - -void Scraper::directScrapeOutput(const ConsoleScreenBufferInfo &info, - bool consoleCursorVisible) -{ - const SmallRect windowRect = info.windowRect(); - - const SmallRect scrapeRect( - windowRect.left(), windowRect.top(), - std::min(std::min(windowRect.width(), m_ptySize.X), - MAX_CONSOLE_WIDTH), - std::min(std::min(windowRect.height(), m_ptySize.Y), - BUFFER_LINE_COUNT)); - const int w = scrapeRect.width(); - const int h = scrapeRect.height(); - - const Coord cursor = info.cursorPosition(); - const bool showTerminalCursor = - consoleCursorVisible && scrapeRect.contains(cursor); - const int cursorColumn = !showTerminalCursor ? -1 : cursor.X - scrapeRect.Left; - const int cursorLine = !showTerminalCursor ? -1 : cursor.Y - scrapeRect.Top; - - if (!showTerminalCursor) { - m_terminal->hideTerminalCursor(); - } - - largeConsoleRead(m_readBuffer, *m_consoleBuffer, scrapeRect, attributesMask()); - - for (int line = 0; line < h; ++line) { - const CHAR_INFO *const curLine = - m_readBuffer.lineData(scrapeRect.top() + line); - ConsoleLine &bufLine = m_bufferData[line]; - if (bufLine.detectChangeAndSetLine(curLine, w)) { - const int lineCursorColumn = - line == cursorLine ? cursorColumn : -1; - m_terminal->sendLine(line, curLine, w, lineCursorColumn); - } - } - - if (showTerminalCursor) { - m_terminal->showTerminalCursor(cursorColumn, cursorLine); - } -} - -bool Scraper::scrollingScrapeOutput(const ConsoleScreenBufferInfo &info, - bool consoleCursorVisible, - bool tentative) -{ - const Coord cursor = info.cursorPosition(); - const SmallRect windowRect = info.windowRect(); - - if (m_syncRow != -1) { - // If a synchronizing marker was placed into the history, look for it - // and adjust the scroll count. - const int markerRow = findSyncMarker(); - if (markerRow == -1) { - if (tentative) { - // I *think* it's possible to keep going, but it's simple to - // bail out. - return false; - } - // Something has happened. Reset the terminal. - trace("Sync marker has disappeared -- resetting the terminal" - " (m_syncCounter=%u)", - m_syncCounter); - resetConsoleTracking(Terminal::SendClear, windowRect.top()); - } else if (markerRow != m_syncRow) { - ASSERT(markerRow < m_syncRow); - m_scrolledCount += (m_syncRow - markerRow); - m_syncRow = markerRow; - // If the buffer has scrolled, then the entire window is dirty. - markEntireWindowDirty(windowRect); - } - } - - // Creating a new sync row requires clearing part of the console buffer, so - // avoid doing it if there's already a sync row that's good enough. - const int newSyncRow = - static_cast(windowRect.top()) - SYNC_MARKER_LEN - SYNC_MARKER_MARGIN; - const bool shouldCreateSyncRow = - newSyncRow >= m_syncRow + SYNC_MARKER_LEN + SYNC_MARKER_MARGIN; - if (tentative && shouldCreateSyncRow) { - // It's difficult even in principle to put down a new marker if the - // console can scroll an arbitrarily amount while we're writing. - return false; - } - - // Update the dirty line count: - // - If the window has moved, the entire window is dirty. - // - Everything up to the cursor is dirty. - // - All lines above the window are dirty. - // - Any non-blank lines are dirty. - if (m_dirtyWindowTop != -1) { - if (windowRect.top() > m_dirtyWindowTop) { - // The window has moved down, presumably as a result of scrolling. - markEntireWindowDirty(windowRect); - } else if (windowRect.top() < m_dirtyWindowTop) { - if (tentative) { - // I *think* it's possible to keep going, but it's simple to - // bail out. - return false; - } - // The window has moved upward. This is generally not expected to - // happen, but the CMD/PowerShell CLS command will move the window - // to the top as part of clearing everything else in the console. - trace("Window moved upward -- resetting the terminal" - " (m_syncCounter=%u)", - m_syncCounter); - resetConsoleTracking(Terminal::SendClear, windowRect.top()); - } - } - m_dirtyWindowTop = windowRect.top(); - m_dirtyLineCount = std::max(m_dirtyLineCount, cursor.Y + 1); - m_dirtyLineCount = std::max(m_dirtyLineCount, (int)windowRect.top()); - - // There will be at least one dirty line, because there is a cursor. - ASSERT(m_dirtyLineCount >= 1); - - // The first line to scrape, in virtual line coordinates. - const int64_t firstVirtLine = std::min(m_scrapedLineCount, - windowRect.top() + m_scrolledCount); - - // Read all the data we will need from the console. Start reading with the - // first line to scrape, but adjust the the read area upward to account for - // scanForDirtyLines' need to read the previous attribute. Read to the - // bottom of the window. (It's not clear to me whether the - // m_dirtyLineCount adjustment here is strictly necessary. It isn't - // necessary so long as the cursor is inside the current window.) - const int firstReadLine = std::min(firstVirtLine - m_scrolledCount, - m_dirtyLineCount - 1); - const int stopReadLine = std::max(windowRect.top() + windowRect.height(), - m_dirtyLineCount); - ASSERT(firstReadLine >= 0 && stopReadLine > firstReadLine); - largeConsoleRead(m_readBuffer, - *m_consoleBuffer, - SmallRect(0, firstReadLine, - std::min(info.bufferSize().X, - MAX_CONSOLE_WIDTH), - stopReadLine - firstReadLine), - attributesMask()); - - // If we're scraping the buffer without freezing it, we have to query the - // buffer position data separately from the buffer content, so the two - // could easily be out-of-sync. If they *are* out-of-sync, abort the - // scrape operation and restart it frozen. (We may have updated the - // dirty-line high-water-mark, but that should be OK.) - if (tentative) { - const auto infoCheck = m_consoleBuffer->bufferInfo(); - if (info.bufferSize() != infoCheck.bufferSize() || - info.windowRect() != infoCheck.windowRect() || - info.cursorPosition() != infoCheck.cursorPosition()) { - return false; - } - if (m_syncRow != -1 && m_syncRow != findSyncMarker()) { - return false; - } - } - - if (shouldCreateSyncRow) { - ASSERT(!tentative); - createSyncMarker(newSyncRow); - } - - // At this point, we're finished interacting (reading or writing) the - // console, and we just need to convert our collected data into terminal - // output. - - scanForDirtyLines(windowRect); - - // Note that it's possible for all the lines on the current window to - // be non-dirty. - - // The line to stop scraping at, in virtual line coordinates. - const int64_t stopVirtLine = - std::min(m_dirtyLineCount, windowRect.top() + windowRect.height()) + - m_scrolledCount; - - const bool showTerminalCursor = - consoleCursorVisible && windowRect.contains(cursor); - const int64_t cursorLine = !showTerminalCursor ? -1 : cursor.Y + m_scrolledCount; - const int cursorColumn = !showTerminalCursor ? -1 : cursor.X; - - if (!showTerminalCursor) { - m_terminal->hideTerminalCursor(); - } - - bool sawModifiedLine = false; - - const int w = m_readBuffer.rect().width(); - for (int64_t line = firstVirtLine; line < stopVirtLine; ++line) { - const CHAR_INFO *curLine = - m_readBuffer.lineData(line - m_scrolledCount); - ConsoleLine &bufLine = m_bufferData[line % BUFFER_LINE_COUNT]; - if (line > m_maxBufferedLine) { - m_maxBufferedLine = line; - sawModifiedLine = true; - } - if (sawModifiedLine) { - bufLine.setLine(curLine, w); - } else { - sawModifiedLine = bufLine.detectChangeAndSetLine(curLine, w); - } - if (sawModifiedLine) { - const int lineCursorColumn = - line == cursorLine ? cursorColumn : -1; - m_terminal->sendLine(line, curLine, w, lineCursorColumn); - } - } - - m_scrapedLineCount = windowRect.top() + m_scrolledCount; - - if (showTerminalCursor) { - m_terminal->showTerminalCursor(cursorColumn, cursorLine); - } - - return true; -} - -void Scraper::syncMarkerText(CHAR_INFO (&output)[SYNC_MARKER_LEN]) -{ - // XXX: The marker text generated here could easily collide with ordinary - // console output. Does it make sense to try to avoid the collision? - char str[SYNC_MARKER_LEN + 1]; - winpty_snprintf(str, "S*Y*N*C*%08x", m_syncCounter); - for (int i = 0; i < SYNC_MARKER_LEN; ++i) { - output[i].Char.UnicodeChar = str[i]; - output[i].Attributes = 7; - } -} - -int Scraper::findSyncMarker() -{ - ASSERT(m_syncRow >= 0); - CHAR_INFO marker[SYNC_MARKER_LEN]; - CHAR_INFO column[BUFFER_LINE_COUNT]; - syncMarkerText(marker); - SmallRect rect(0, 0, 1, m_syncRow + SYNC_MARKER_LEN); - m_consoleBuffer->read(rect, column); - int i; - for (i = m_syncRow; i >= 0; --i) { - int j; - for (j = 0; j < SYNC_MARKER_LEN; ++j) { - if (column[i + j].Char.UnicodeChar != marker[j].Char.UnicodeChar) - break; - } - if (j == SYNC_MARKER_LEN) - return i; - } - return -1; -} - -void Scraper::createSyncMarker(int row) -{ - ASSERT(row >= 1); - - // Clear the lines around the marker to ensure that Windows 10's rewrapping - // does not affect the marker. - m_consoleBuffer->clearLines(row - 1, SYNC_MARKER_LEN + 1, - m_consoleBuffer->bufferInfo()); - - // Write a new marker. - m_syncCounter++; - CHAR_INFO marker[SYNC_MARKER_LEN]; - syncMarkerText(marker); - m_syncRow = row; - SmallRect markerRect(0, m_syncRow, 1, SYNC_MARKER_LEN); - m_consoleBuffer->write(markerRect, marker); -} diff --git a/deps/winpty/src/agent/Scraper.h b/deps/winpty/src/agent/Scraper.h deleted file mode 100644 index 9c10d80ae..000000000 --- a/deps/winpty/src/agent/Scraper.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_SCRAPER_H -#define AGENT_SCRAPER_H - -#include - -#include - -#include -#include - -#include "ConsoleLine.h" -#include "Coord.h" -#include "LargeConsoleRead.h" -#include "SmallRect.h" -#include "Terminal.h" - -class ConsoleScreenBufferInfo; -class Win32Console; -class Win32ConsoleBuffer; - -// We must be able to issue a single ReadConsoleOutputW call of -// MAX_CONSOLE_WIDTH characters, and a single read of approximately several -// hundred fewer characters than BUFFER_LINE_COUNT. -const int BUFFER_LINE_COUNT = 3000; -const int MAX_CONSOLE_WIDTH = 2500; -const int MAX_CONSOLE_HEIGHT = 2000; -const int SYNC_MARKER_LEN = 16; -const int SYNC_MARKER_MARGIN = 200; - -class Scraper { -public: - Scraper( - Win32Console &console, - Win32ConsoleBuffer &buffer, - std::unique_ptr terminal, - Coord initialSize); - ~Scraper(); - void resizeWindow(Win32ConsoleBuffer &buffer, - Coord newSize, - ConsoleScreenBufferInfo &finalInfoOut); - void scrapeBuffer(Win32ConsoleBuffer &buffer, - ConsoleScreenBufferInfo &finalInfoOut); - Terminal &terminal() { return *m_terminal; } - -private: - void resetConsoleTracking( - Terminal::SendClearFlag sendClear, int64_t scrapedLineCount); - void markEntireWindowDirty(const SmallRect &windowRect); - void scanForDirtyLines(const SmallRect &windowRect); - void clearBufferLines(int firstRow, int count); - void resizeImpl(const ConsoleScreenBufferInfo &origInfo); - void syncConsoleContentAndSize(bool forceResize, - ConsoleScreenBufferInfo &finalInfoOut); - WORD attributesMask(); - void directScrapeOutput(const ConsoleScreenBufferInfo &info, - bool consoleCursorVisible); - bool scrollingScrapeOutput(const ConsoleScreenBufferInfo &info, - bool consoleCursorVisible, - bool tentative); - void syncMarkerText(CHAR_INFO (&output)[SYNC_MARKER_LEN]); - int findSyncMarker(); - void createSyncMarker(int row); - -private: - Win32Console &m_console; - Win32ConsoleBuffer *m_consoleBuffer = nullptr; - std::unique_ptr m_terminal; - - int m_syncRow = -1; - unsigned int m_syncCounter = 0; - - bool m_directMode = false; - Coord m_ptySize; - int64_t m_scrapedLineCount = 0; - int64_t m_scrolledCount = 0; - int64_t m_maxBufferedLine = -1; - LargeConsoleReadBuffer m_readBuffer; - std::vector m_bufferData; - int m_dirtyWindowTop = -1; - int m_dirtyLineCount = 0; -}; - -#endif // AGENT_SCRAPER_H diff --git a/deps/winpty/src/agent/SimplePool.h b/deps/winpty/src/agent/SimplePool.h deleted file mode 100644 index 41ff94a90..000000000 --- a/deps/winpty/src/agent/SimplePool.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef SIMPLE_POOL_H -#define SIMPLE_POOL_H - -#include - -#include - -#include "../shared/WinptyAssert.h" - -template -class SimplePool { -public: - ~SimplePool(); - T *alloc(); - void clear(); -private: - struct Chunk { - size_t count; - T *data; - }; - std::vector m_chunks; -}; - -template -SimplePool::~SimplePool() { - clear(); -} - -template -void SimplePool::clear() { - for (size_t ci = 0; ci < m_chunks.size(); ++ci) { - Chunk &chunk = m_chunks[ci]; - for (size_t ti = 0; ti < chunk.count; ++ti) { - chunk.data[ti].~T(); - } - free(chunk.data); - } - m_chunks.clear(); -} - -template -T *SimplePool::alloc() { - if (m_chunks.empty() || m_chunks.back().count == chunkSize) { - T *newData = reinterpret_cast(malloc(sizeof(T) * chunkSize)); - ASSERT(newData != NULL); - Chunk newChunk = { 0, newData }; - m_chunks.push_back(newChunk); - } - Chunk &chunk = m_chunks.back(); - T *ret = &chunk.data[chunk.count++]; - new (ret) T(); - return ret; -} - -#endif // SIMPLE_POOL_H diff --git a/deps/winpty/src/agent/SmallRect.h b/deps/winpty/src/agent/SmallRect.h deleted file mode 100644 index bad0b8868..000000000 --- a/deps/winpty/src/agent/SmallRect.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef SMALLRECT_H -#define SMALLRECT_H - -#include - -#include -#include - -#include "../shared/winpty_snprintf.h" -#include "Coord.h" - -struct SmallRect : SMALL_RECT -{ - SmallRect() - { - Left = Right = Top = Bottom = 0; - } - - SmallRect(SHORT x, SHORT y, SHORT width, SHORT height) - { - Left = x; - Top = y; - Right = x + width - 1; - Bottom = y + height - 1; - } - - SmallRect(const COORD &topLeft, const COORD &size) - { - Left = topLeft.X; - Top = topLeft.Y; - Right = Left + size.X - 1; - Bottom = Top + size.Y - 1; - } - - SmallRect(const SMALL_RECT &other) - { - *(SMALL_RECT*)this = other; - } - - SmallRect(const SmallRect &other) - { - *(SMALL_RECT*)this = *(const SMALL_RECT*)&other; - } - - SmallRect &operator=(const SmallRect &other) - { - *(SMALL_RECT*)this = *(const SMALL_RECT*)&other; - return *this; - } - - bool contains(const SmallRect &other) const - { - return other.Left >= Left && - other.Right <= Right && - other.Top >= Top && - other.Bottom <= Bottom; - } - - bool contains(const Coord &other) const - { - return other.X >= Left && - other.X <= Right && - other.Y >= Top && - other.Y <= Bottom; - } - - SmallRect intersected(const SmallRect &other) const - { - int x1 = std::max(Left, other.Left); - int x2 = std::min(Right, other.Right); - int y1 = std::max(Top, other.Top); - int y2 = std::min(Bottom, other.Bottom); - return SmallRect(x1, - y1, - std::max(0, x2 - x1 + 1), - std::max(0, y2 - y1 + 1)); - } - - SmallRect ensureLineIncluded(SHORT line) const - { - const SHORT h = height(); - if (line < Top) { - return SmallRect(Left, line, width(), h); - } else if (line > Bottom) { - return SmallRect(Left, line - h + 1, width(), h); - } else { - return *this; - } - } - - SHORT top() const { return Top; } - SHORT left() const { return Left; } - SHORT width() const { return Right - Left + 1; } - SHORT height() const { return Bottom - Top + 1; } - void setTop(SHORT top) { Top = top; } - void setLeft(SHORT left) { Left = left; } - void setWidth(SHORT width) { Right = Left + width - 1; } - void setHeight(SHORT height) { Bottom = Top + height - 1; } - Coord size() const { return Coord(width(), height()); } - - bool operator==(const SmallRect &other) const - { - return Left == other.Left && - Right == other.Right && - Top == other.Top && - Bottom == other.Bottom; - } - - bool operator!=(const SmallRect &other) const - { - return !(*this == other); - } - - std::string toString() const - { - char ret[64]; - winpty_snprintf(ret, "(x=%d,y=%d,w=%d,h=%d)", - Left, Top, width(), height()); - return std::string(ret); - } -}; - -#endif // SMALLRECT_H diff --git a/deps/winpty/src/agent/Terminal.cc b/deps/winpty/src/agent/Terminal.cc deleted file mode 100644 index afa0a3626..000000000 --- a/deps/winpty/src/agent/Terminal.cc +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Terminal.h" - -#include -#include -#include - -#include - -#include "NamedPipe.h" -#include "UnicodeEncoding.h" -#include "../shared/DebugClient.h" -#include "../shared/WinptyAssert.h" -#include "../shared/winpty_snprintf.h" - -#define CSI "\x1b[" - -// Work around the old MinGW, which lacks COMMON_LVB_LEADING_BYTE and -// COMMON_LVB_TRAILING_BYTE. -const int WINPTY_COMMON_LVB_LEADING_BYTE = 0x100; -const int WINPTY_COMMON_LVB_TRAILING_BYTE = 0x200; -const int WINPTY_COMMON_LVB_REVERSE_VIDEO = 0x4000; -const int WINPTY_COMMON_LVB_UNDERSCORE = 0x8000; - -const int COLOR_ATTRIBUTE_MASK = - FOREGROUND_BLUE | - FOREGROUND_GREEN | - FOREGROUND_RED | - FOREGROUND_INTENSITY | - BACKGROUND_BLUE | - BACKGROUND_GREEN | - BACKGROUND_RED | - BACKGROUND_INTENSITY | - WINPTY_COMMON_LVB_REVERSE_VIDEO | - WINPTY_COMMON_LVB_UNDERSCORE; - -const int FLAG_RED = 1; -const int FLAG_GREEN = 2; -const int FLAG_BLUE = 4; -const int FLAG_BRIGHT = 8; - -const int BLACK = 0; -const int DKGRAY = BLACK | FLAG_BRIGHT; -const int LTGRAY = FLAG_RED | FLAG_GREEN | FLAG_BLUE; -const int WHITE = LTGRAY | FLAG_BRIGHT; - -// SGR parameters (Select Graphic Rendition) -const int SGR_FORE = 30; -const int SGR_FORE_HI = 90; -const int SGR_BACK = 40; -const int SGR_BACK_HI = 100; - -namespace { - -static void outUInt(std::string &out, unsigned int n) -{ - char buf[32]; - char *pbuf = &buf[32]; - *(--pbuf) = '\0'; - do { - *(--pbuf) = '0' + n % 10; - n /= 10; - } while (n != 0); - out.append(pbuf); -} - -static void outputSetColorSgrParams(std::string &out, bool isFore, int color) -{ - out.push_back(';'); - const int sgrBase = isFore ? SGR_FORE : SGR_BACK; - if (color & FLAG_BRIGHT) { - // Some terminals don't support the 9X/10X "intensive" color parameters - // (e.g. the Eclipse TM terminal as of this writing). Those terminals - // will quietly ignore a 9X/10X code, and the other terminals will - // ignore a 3X/4X code if it's followed by a 9X/10X code. Therefore, - // output a 3X/4X code as a fallback, then override it. - const int colorBase = color & ~FLAG_BRIGHT; - outUInt(out, sgrBase + colorBase); - out.push_back(';'); - outUInt(out, sgrBase + (SGR_FORE_HI - SGR_FORE) + colorBase); - } else { - outUInt(out, sgrBase + color); - } -} - -static void outputSetColor(std::string &out, int color) -{ - int fore = 0; - int back = 0; - if (color & FOREGROUND_RED) fore |= FLAG_RED; - if (color & FOREGROUND_GREEN) fore |= FLAG_GREEN; - if (color & FOREGROUND_BLUE) fore |= FLAG_BLUE; - if (color & FOREGROUND_INTENSITY) fore |= FLAG_BRIGHT; - if (color & BACKGROUND_RED) back |= FLAG_RED; - if (color & BACKGROUND_GREEN) back |= FLAG_GREEN; - if (color & BACKGROUND_BLUE) back |= FLAG_BLUE; - if (color & BACKGROUND_INTENSITY) back |= FLAG_BRIGHT; - - if (color & WINPTY_COMMON_LVB_REVERSE_VIDEO) { - // n.b.: The COMMON_LVB_REVERSE_VIDEO flag also swaps - // FOREGROUND_INTENSITY and BACKGROUND_INTENSITY. Tested on - // Windows 10 v14393. - std::swap(fore, back); - } - - // Translate the fore/back colors into terminal escape codes using - // a heuristic that works OK with common white-on-black or - // black-on-white color schemes. We don't know which color scheme - // the terminal is using. It is ugly to force white-on-black text - // on a black-on-white terminal, and it's even ugly to force the - // matching scheme. It's probably relevant that the default - // fore/back terminal colors frequently do not match any of the 16 - // palette colors. - - // Typical default terminal color schemes (according to palette, - // when possible): - // - mintty: LtGray-on-Black(A) - // - putty: LtGray-on-Black(A) - // - xterm: LtGray-on-Black(A) - // - Konsole: LtGray-on-Black(A) - // - JediTerm/JetBrains: Black-on-White(B) - // - rxvt: Black-on-White(B) - - // If the background is the default color (black), then it will - // map to Black(A) or White(B). If we translate White to White, - // then a Black background and a White background in the console - // are both White with (B). Therefore, we should translate White - // using SGR 7 (Invert). The typical finished mapping table for - // background grayscale colors is: - // - // (A) White => LtGray(fore) - // (A) Black => Black(back) - // (A) LtGray => LtGray - // (A) DkGray => DkGray - // - // (B) White => Black(fore) - // (B) Black => White(back) - // (B) LtGray => LtGray - // (B) DkGray => DkGray - // - - out.append(CSI "0"); - if (back == BLACK) { - if (fore == LTGRAY) { - // The "default" foreground color. Use the terminal's - // default colors. - } else if (fore == WHITE) { - // Sending the literal color white would behave poorly if - // the terminal were black-on-white. Sending Bold is not - // guaranteed to alter the color, but it will make the text - // visually distinct, so do that instead. - out.append(";1"); - } else if (fore == DKGRAY) { - // Set the foreground color to DkGray(90) with a fallback - // of LtGray(37) for terminals that don't handle the 9X SGR - // parameters (e.g. Eclipse's TM Terminal as of this - // writing). - out.append(";37;90"); - } else { - outputSetColorSgrParams(out, true, fore); - } - } else if (back == WHITE) { - // Set the background color using Invert on the default - // foreground color, and set the foreground color by setting a - // background color. - - // Use the terminal's inverted colors. - out.append(";7"); - if (fore == LTGRAY || fore == BLACK) { - // We're likely mapping Console White to terminal LtGray or - // Black. If they are the Console foreground color, then - // don't set a terminal foreground color to avoid creating - // invisible text. - } else { - outputSetColorSgrParams(out, false, fore); - } - } else { - // Set the foreground and background to match exactly that in - // the Windows console. - outputSetColorSgrParams(out, true, fore); - outputSetColorSgrParams(out, false, back); - } - if (fore == back) { - // The foreground and background colors are exactly equal, so - // attempt to hide the text using the Conceal SGR parameter, - // which some terminals support. - out.append(";8"); - } - if (color & WINPTY_COMMON_LVB_UNDERSCORE) { - out.append(";4"); - } - out.push_back('m'); -} - -static inline unsigned int fixSpecialCharacters(unsigned int ch) -{ - if (ch <= 0x1b) { - switch (ch) { - // The Windows Console has a popup window (e.g. that appears with - // F7) that is sometimes bordered with box-drawing characters. - // With the Japanese and Korean system locales (CP932 and CP949), - // the UnicodeChar values for the box-drawing characters are 1 - // through 6. Detect this and map the values to the correct - // Unicode values. - // - // N.B. In the English locale, the UnicodeChar values are correct, - // and they identify single-line characters rather than - // double-line. In the Chinese Simplified and Traditional locales, - // the popups use ASCII characters instead. - case 1: return 0x2554; // BOX DRAWINGS DOUBLE DOWN AND RIGHT - case 2: return 0x2557; // BOX DRAWINGS DOUBLE DOWN AND LEFT - case 3: return 0x255A; // BOX DRAWINGS DOUBLE UP AND RIGHT - case 4: return 0x255D; // BOX DRAWINGS DOUBLE UP AND LEFT - case 5: return 0x2551; // BOX DRAWINGS DOUBLE VERTICAL - case 6: return 0x2550; // BOX DRAWINGS DOUBLE HORIZONTAL - - // Convert an escape character to some other character. This - // conversion only applies to console cells containing an escape - // character. In newer versions of Windows 10 (e.g. 10.0.10586), - // the non-legacy console recognizes escape sequences in - // WriteConsole and interprets them without writing them to the - // cells of the screen buffer. In that case, the conversion here - // does not apply. - case 0x1b: return '?'; - } - } - return ch; -} - -static inline bool isFullWidthCharacter(const CHAR_INFO *data, int width) -{ - if (width < 2) { - return false; - } - return - (data[0].Attributes & WINPTY_COMMON_LVB_LEADING_BYTE) && - (data[1].Attributes & WINPTY_COMMON_LVB_TRAILING_BYTE) && - data[0].Char.UnicodeChar == data[1].Char.UnicodeChar; -} - -// Scan to find a single Unicode Scalar Value. Full-width characters occupy -// two console cells, and this code also tries to handle UTF-16 surrogate -// pairs. -// -// Windows expands at least some wide characters outside the Basic -// Multilingual Plane into four cells, such as U+20000: -// 1. 0xD840, attr=0x107 -// 2. 0xD840, attr=0x207 -// 3. 0xDC00, attr=0x107 -// 4. 0xDC00, attr=0x207 -// Even in the Traditional Chinese locale on Windows 10, this text is rendered -// as two boxes, but if those boxes are copied-and-pasted, the character is -// copied correctly. -static inline void scanUnicodeScalarValue( - const CHAR_INFO *data, int width, - int &outCellCount, unsigned int &outCharValue) -{ - ASSERT(width >= 1); - - const int w1 = isFullWidthCharacter(data, width) ? 2 : 1; - const wchar_t c1 = data[0].Char.UnicodeChar; - - if ((c1 & 0xF800) == 0xD800) { - // The first cell is either a leading or trailing surrogate pair. - if ((c1 & 0xFC00) != 0xD800 || - width <= w1 || - ((data[w1].Char.UnicodeChar & 0xFC00) != 0xDC00)) { - // Invalid surrogate pair - outCellCount = w1; - outCharValue = '?'; - } else { - // Valid surrogate pair - outCellCount = w1 + (isFullWidthCharacter(&data[w1], width - w1) ? 2 : 1); - outCharValue = decodeSurrogatePair(c1, data[w1].Char.UnicodeChar); - } - } else { - outCellCount = w1; - outCharValue = c1; - } -} - -} // anonymous namespace - -void Terminal::reset(SendClearFlag sendClearFirst, int64_t newLine) -{ - if (sendClearFirst == SendClear && !m_plainMode) { - // 0m ==> reset SGR parameters - // 1;1H ==> move cursor to top-left position - // 2J ==> clear the entire screen - m_output.write(CSI "0m" CSI "1;1H" CSI "2J"); - } - m_remoteLine = newLine; - m_remoteColumn = 0; - m_lineData.clear(); - m_cursorHidden = false; - m_remoteColor = -1; -} - -void Terminal::sendLine(int64_t line, const CHAR_INFO *lineData, int width, - int cursorColumn) -{ - ASSERT(width >= 1); - - moveTerminalToLine(line); - - // If possible, see if we can append to what we've already output for this - // line. - if (m_lineDataValid) { - ASSERT(m_lineData.size() == static_cast(m_remoteColumn)); - if (m_remoteColumn > 0) { - // In normal mode, if m_lineData.size() equals `width`, then we - // will have trouble outputing the "erase rest of line" command, - // which must be output before reaching the end of the line. In - // plain mode, we don't output that command, so we're OK with a - // full line. - bool okWidth = false; - if (m_plainMode) { - okWidth = static_cast(width) >= m_lineData.size(); - } else { - okWidth = static_cast(width) > m_lineData.size(); - } - if (!okWidth || - memcmp(m_lineData.data(), lineData, - sizeof(CHAR_INFO) * m_lineData.size()) != 0) { - m_lineDataValid = false; - } - } - } - if (!m_lineDataValid) { - // We can't reuse, so we must reset this line. - hideTerminalCursor(); - if (m_plainMode) { - // We can't backtrack, so repeat this line. - m_output.write("\r\n"); - } else { - m_output.write("\r"); - } - m_lineDataValid = true; - m_lineData.clear(); - m_remoteColumn = 0; - } - - std::string &termLine = m_termLineWorkingBuffer; - termLine.clear(); - size_t trimmedLineLength = 0; - int trimmedCellCount = m_lineData.size(); - bool alreadyErasedLine = false; - - int cellCount = 1; - for (int i = m_lineData.size(); i < width; i += cellCount) { - if (m_outputColor) { - int color = lineData[i].Attributes & COLOR_ATTRIBUTE_MASK; - if (color != m_remoteColor) { - outputSetColor(termLine, color); - trimmedLineLength = termLine.size(); - m_remoteColor = color; - - // All the cells just up to this color change will be output. - trimmedCellCount = i; - } - } - unsigned int ch; - scanUnicodeScalarValue(&lineData[i], width - i, cellCount, ch); - if (ch == ' ') { - // Tentatively add this space character. We'll only output it if - // we see something interesting after it. - termLine.push_back(' '); - } else { - if (i + cellCount == width) { - // We'd like to erase the line after outputting all non-blank - // characters, but this doesn't work if the last cell in the - // line is non-blank. At the point, the cursor is positioned - // just past the end of the line, but in many terminals, - // issuing a CSI 0K at that point also erases the last cell in - // the line. Work around this behavior by issuing the erase - // one character early in that case. - if (!m_plainMode) { - termLine.append(CSI "0K"); // Erase from cursor to EOL - } - alreadyErasedLine = true; - } - ch = fixSpecialCharacters(ch); - char enc[4]; - int enclen = encodeUtf8(enc, ch); - if (enclen == 0) { - enc[0] = '?'; - enclen = 1; - } - termLine.append(enc, enclen); - trimmedLineLength = termLine.size(); - - // All the cells up to and including this cell will be output. - trimmedCellCount = i + cellCount; - } - } - - if (cursorColumn != -1 && trimmedCellCount > cursorColumn) { - // The line content would run past the cursor, so hide it before we - // output. - hideTerminalCursor(); - } - - m_output.write(termLine.data(), trimmedLineLength); - if (!alreadyErasedLine && !m_plainMode) { - m_output.write(CSI "0K"); // Erase from cursor to EOL - } - - ASSERT(trimmedCellCount <= width); - m_lineData.insert(m_lineData.end(), - &lineData[m_lineData.size()], - &lineData[trimmedCellCount]); - m_remoteColumn = trimmedCellCount; -} - -void Terminal::showTerminalCursor(int column, int64_t line) -{ - moveTerminalToLine(line); - if (!m_plainMode) { - if (m_remoteColumn != column) { - char buffer[32]; - winpty_snprintf(buffer, CSI "%dG", column + 1); - m_output.write(buffer); - m_lineDataValid = (column == 0); - m_lineData.clear(); - m_remoteColumn = column; - } - if (m_cursorHidden) { - m_output.write(CSI "?25h"); - m_cursorHidden = false; - } - } -} - -void Terminal::hideTerminalCursor() -{ - if (!m_plainMode) { - if (m_cursorHidden) { - return; - } - m_output.write(CSI "?25l"); - m_cursorHidden = true; - } -} - -void Terminal::moveTerminalToLine(int64_t line) -{ - if (line == m_remoteLine) { - return; - } - - // Do not use CPL or CNL. Konsole 2.5.4 does not support Cursor Previous - // Line (CPL) -- there are "Undecodable sequence" errors. gnome-terminal - // 2.32.0 does handle it. Cursor Next Line (CNL) does nothing if the - // cursor is on the last line already. - - hideTerminalCursor(); - - if (line < m_remoteLine) { - if (m_plainMode) { - // We can't backtrack, so instead repeat the lines again. - m_output.write("\r\n"); - m_remoteLine = line; - } else { - // Backtrack and overwrite previous lines. - // CUrsor Up (CUU) - char buffer[32]; - winpty_snprintf(buffer, "\r" CSI "%uA", - static_cast(m_remoteLine - line)); - m_output.write(buffer); - m_remoteLine = line; - } - } else if (line > m_remoteLine) { - while (line > m_remoteLine) { - m_output.write("\r\n"); - m_remoteLine++; - } - } - - m_lineDataValid = true; - m_lineData.clear(); - m_remoteColumn = 0; -} - -void Terminal::enableMouseMode(bool enabled) -{ - if (m_mouseModeEnabled == enabled || m_plainMode) { - return; - } - m_mouseModeEnabled = enabled; - if (enabled) { - // Start by disabling UTF-8 coordinate mode (1005), just in case we - // have a terminal that does not support 1006/1015 modes, and 1005 - // happens to be enabled. The UTF-8 coordinates can't be unambiguously - // decoded. - // - // Enable basic mouse support first (1000), then try to switch to - // button-move mode (1002), then try full mouse-move mode (1003). - // Terminals that don't support a mode will be stuck at the highest - // mode they do support. - // - // Enable encoding mode 1015 first, then try to switch to 1006. On - // some terminals, both modes will be enabled, but 1006 will have - // priority. On other terminals, 1006 wins because it's listed last. - // - // See misc/MouseInputNotes.txt for details. - m_output.write( - CSI "?1005l" - CSI "?1000h" CSI "?1002h" CSI "?1003h" CSI "?1015h" CSI "?1006h"); - } else { - // Resetting both encoding modes (1006 and 1015) is necessary, but - // apparently we only need to use reset on one of the 100[023] modes. - // Doing both doesn't hurt. - m_output.write( - CSI "?1006l" CSI "?1015l" CSI "?1003l" CSI "?1002l" CSI "?1000l"); - } -} diff --git a/deps/winpty/src/agent/Terminal.h b/deps/winpty/src/agent/Terminal.h deleted file mode 100644 index 058eb2650..000000000 --- a/deps/winpty/src/agent/Terminal.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef TERMINAL_H -#define TERMINAL_H - -#include -#include - -#include -#include - -#include "Coord.h" - -class NamedPipe; - -class Terminal -{ -public: - explicit Terminal(NamedPipe &output, bool plainMode, bool outputColor) - : m_output(output), m_plainMode(plainMode), m_outputColor(outputColor) - { - } - - enum SendClearFlag { OmitClear, SendClear }; - void reset(SendClearFlag sendClearFirst, int64_t newLine); - void sendLine(int64_t line, const CHAR_INFO *lineData, int width, - int cursorColumn); - void showTerminalCursor(int column, int64_t line); - void hideTerminalCursor(); - -private: - void moveTerminalToLine(int64_t line); - -public: - void enableMouseMode(bool enabled); - -private: - NamedPipe &m_output; - int64_t m_remoteLine = 0; - int m_remoteColumn = 0; - bool m_lineDataValid = true; - std::vector m_lineData; - bool m_cursorHidden = false; - int m_remoteColor = -1; - std::string m_termLineWorkingBuffer; - bool m_plainMode = false; - bool m_outputColor = true; - bool m_mouseModeEnabled = false; -}; - -#endif // TERMINAL_H diff --git a/deps/winpty/src/agent/UnicodeEncoding.h b/deps/winpty/src/agent/UnicodeEncoding.h deleted file mode 100644 index 6b0de3eff..000000000 --- a/deps/winpty/src/agent/UnicodeEncoding.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNICODE_ENCODING_H -#define UNICODE_ENCODING_H - -#include - -// Encode the Unicode codepoint with UTF-8. The buffer must be at least 4 -// bytes in size. -static inline int encodeUtf8(char *out, uint32_t code) { - if (code < 0x80) { - out[0] = code; - return 1; - } else if (code < 0x800) { - out[0] = ((code >> 6) & 0x1F) | 0xC0; - out[1] = ((code >> 0) & 0x3F) | 0x80; - return 2; - } else if (code < 0x10000) { - if (code >= 0xD800 && code <= 0xDFFF) { - // The code points 0xD800 to 0xDFFF are reserved for UTF-16 - // surrogate pairs and do not have an encoding in UTF-8. - return 0; - } - out[0] = ((code >> 12) & 0x0F) | 0xE0; - out[1] = ((code >> 6) & 0x3F) | 0x80; - out[2] = ((code >> 0) & 0x3F) | 0x80; - return 3; - } else if (code < 0x110000) { - out[0] = ((code >> 18) & 0x07) | 0xF0; - out[1] = ((code >> 12) & 0x3F) | 0x80; - out[2] = ((code >> 6) & 0x3F) | 0x80; - out[3] = ((code >> 0) & 0x3F) | 0x80; - return 4; - } else { - // Encoding error - return 0; - } -} - -// Encode the Unicode codepoint with UTF-16. The buffer must be large enough -// to hold the output -- either 1 or 2 elements. -static inline int encodeUtf16(wchar_t *out, uint32_t code) { - if (code < 0x10000) { - if (code >= 0xD800 && code <= 0xDFFF) { - // The code points 0xD800 to 0xDFFF are reserved for UTF-16 - // surrogate pairs and do not have an encoding in UTF-16. - return 0; - } - out[0] = code; - return 1; - } else if (code < 0x110000) { - code -= 0x10000; - out[0] = 0xD800 | (code >> 10); - out[1] = 0xDC00 | (code & 0x3FF); - return 2; - } else { - // Encoding error - return 0; - } -} - -// Return the byte size of a UTF-8 character using the value of the first -// byte. -static inline int utf8CharLength(char firstByte) { - // This code would probably be faster if it used __builtin_clz. - if ((firstByte & 0x80) == 0) { - return 1; - } else if ((firstByte & 0xE0) == 0xC0) { - return 2; - } else if ((firstByte & 0xF0) == 0xE0) { - return 3; - } else if ((firstByte & 0xF8) == 0xF0) { - return 4; - } else { - // Malformed UTF-8. - return 0; - } -} - -// The pointer must point to 1-4 bytes, as indicated by the first byte. -// Returns -1 on decoding error. -static inline uint32_t decodeUtf8(const char *in) { - const uint32_t kInvalid = static_cast(-1); - switch (utf8CharLength(in[0])) { - case 1: { - return in[0]; - } - case 2: { - if ((in[1] & 0xC0) != 0x80) { - return kInvalid; - } - uint32_t tmp = 0; - tmp = (in[0] & 0x1F) << 6; - tmp |= (in[1] & 0x3F); - return tmp <= 0x7F ? kInvalid : tmp; - } - case 3: { - if ((in[1] & 0xC0) != 0x80 || - (in[2] & 0xC0) != 0x80) { - return kInvalid; - } - uint32_t tmp = 0; - tmp = (in[0] & 0x0F) << 12; - tmp |= (in[1] & 0x3F) << 6; - tmp |= (in[2] & 0x3F); - if (tmp <= 0x07FF || (tmp >= 0xD800 && tmp <= 0xDFFF)) { - return kInvalid; - } else { - return tmp; - } - } - case 4: { - if ((in[1] & 0xC0) != 0x80 || - (in[2] & 0xC0) != 0x80 || - (in[3] & 0xC0) != 0x80) { - return kInvalid; - } - uint32_t tmp = 0; - tmp = (in[0] & 0x07) << 18; - tmp |= (in[1] & 0x3F) << 12; - tmp |= (in[2] & 0x3F) << 6; - tmp |= (in[3] & 0x3F); - if (tmp <= 0xFFFF || tmp > 0x10FFFF) { - return kInvalid; - } else { - return tmp; - } - } - default: { - return kInvalid; - } - } -} - -static inline uint32_t decodeSurrogatePair(wchar_t ch1, wchar_t ch2) { - return ((ch1 - 0xD800) << 10) + (ch2 - 0xDC00) + 0x10000; -} - -#endif // UNICODE_ENCODING_H diff --git a/deps/winpty/src/agent/UnicodeEncodingTest.cc b/deps/winpty/src/agent/UnicodeEncodingTest.cc deleted file mode 100644 index cd4abeb19..000000000 --- a/deps/winpty/src/agent/UnicodeEncodingTest.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// Encode every code-point using this module and verify that it matches the -// encoding generated using Windows WideCharToMultiByte. - -#include "UnicodeEncoding.h" - -#include -#include -#include -#include -#include - -static void correctnessByCode() -{ - char mbstr1[4]; - char mbstr2[4]; - wchar_t wch[2]; - for (unsigned int code = 0; code < 0x110000; ++code) { - - // Surrogate pair reserved region. - const bool isReserved = (code >= 0xD800 && code <= 0xDFFF); - - int mblen1 = encodeUtf8(mbstr1, code); - if (isReserved ? mblen1 != 0 : mblen1 <= 0) { - printf("Error: 0x%04X: mblen1=%d\n", code, mblen1); - continue; - } - - int wlen = encodeUtf16(wch, code); - if (isReserved ? wlen != 0 : wlen <= 0) { - printf("Error: 0x%04X: wlen=%d\n", code, wlen); - continue; - } - - if (isReserved) { - continue; - } - - if (mblen1 != utf8CharLength(mbstr1[0])) { - printf("Error: 0x%04X: mblen1=%d, utf8CharLength(mbstr1[0])=%d\n", - code, mblen1, utf8CharLength(mbstr1[0])); - continue; - } - - if (code != decodeUtf8(mbstr1)) { - printf("Error: 0x%04X: decodeUtf8(mbstr1)=%u\n", - code, decodeUtf8(mbstr1)); - continue; - } - - int mblen2 = WideCharToMultiByte(CP_UTF8, 0, wch, wlen, mbstr2, 4, NULL, NULL); - if (mblen1 != mblen2) { - printf("Error: 0x%04X: mblen1=%d, mblen2=%d\n", code, mblen1, mblen2); - continue; - } - - if (memcmp(mbstr1, mbstr2, mblen1) != 0) { - printf("Error: 0x%04x: encodings are different\n", code); - continue; - } - } -} - -static const char *encodingStr(char (&output)[128], char (&buf)[4]) -{ - sprintf(output, "Encoding %02X %02X %02X %02X", - static_cast(buf[0]), - static_cast(buf[1]), - static_cast(buf[2]), - static_cast(buf[3])); - return output; -} - -// This test can take a couple of minutes to run. -static void correctnessByUtf8Encoding() -{ - for (uint64_t encoding = 0; encoding <= 0xFFFFFFFF; ++encoding) { - - char mb[4]; - mb[0] = encoding; - mb[1] = encoding >> 8; - mb[2] = encoding >> 16; - mb[3] = encoding >> 24; - - const int mblen = utf8CharLength(mb[0]); - if (mblen == 0) { - continue; - } - - // Test this module. - const uint32_t code1 = decodeUtf8(mb); - wchar_t ws1[2] = {}; - const int wslen1 = encodeUtf16(ws1, code1); - - // Test using Windows. We can't decode a codepoint directly; we have - // to do UTF8->UTF16, then decode the surrogate pair. - wchar_t ws2[2] = {}; - const int wslen2 = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, mb, mblen, ws2, 2); - const uint32_t code2 = - (wslen2 == 1 ? ws2[0] : - wslen2 == 2 ? decodeSurrogatePair(ws2[0], ws2[1]) : - static_cast(-1)); - - // Verify that the two implementations match. - char prefix[128]; - if (code1 != code2) { - printf("%s: code1=0x%04x code2=0x%04x\n", - encodingStr(prefix, mb), - code1, code2); - continue; - } - if (wslen1 != wslen2) { - printf("%s: wslen1=%d wslen2=%d\n", - encodingStr(prefix, mb), - wslen1, wslen2); - continue; - } - if (memcmp(ws1, ws2, wslen1 * sizeof(wchar_t)) != 0) { - printf("%s: ws1 != ws2\n", encodingStr(prefix, mb)); - continue; - } - } -} - -wchar_t g_wch_TEST[] = { 0xD840, 0xDC00 }; -char g_ch_TEST[4]; -wchar_t *volatile g_pwch = g_wch_TEST; -char *volatile g_pch = g_ch_TEST; -unsigned int volatile g_code = 0xA2000; - -static void performance() -{ - { - clock_t start = clock(); - for (long long i = 0; i < 250000000LL; ++i) { - int mblen = WideCharToMultiByte(CP_UTF8, 0, g_pwch, 2, g_pch, 4, NULL, NULL); - assert(mblen == 4); - } - clock_t stop = clock(); - printf("%.3fns per char\n", (double)(stop - start) / CLOCKS_PER_SEC * 4.0); - } - - { - clock_t start = clock(); - for (long long i = 0; i < 3000000000LL; ++i) { - int mblen = encodeUtf8(g_pch, g_code); - assert(mblen == 4); - } - clock_t stop = clock(); - printf("%.3fns per char\n", (double)(stop - start) / CLOCKS_PER_SEC / 3.0); - } -} - -int main() -{ - printf("Testing correctnessByCode...\n"); - fflush(stdout); - correctnessByCode(); - - printf("Testing correctnessByUtf8Encoding... (may take a couple minutes)\n"); - fflush(stdout); - correctnessByUtf8Encoding(); - - printf("Testing performance...\n"); - fflush(stdout); - performance(); - - return 0; -} diff --git a/deps/winpty/src/agent/Win32Console.cc b/deps/winpty/src/agent/Win32Console.cc deleted file mode 100644 index d53de021f..000000000 --- a/deps/winpty/src/agent/Win32Console.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Win32Console.h" - -#include -#include - -#include - -#include "../shared/DebugClient.h" -#include "../shared/WinptyAssert.h" - -Win32Console::Win32Console() : m_titleWorkBuf(16) -{ - // The console window must be non-NULL. It is used for two purposes: - // (1) "Freezing" the console to detect the exact number of lines that - // have scrolled. - // (2) Killing processes attached to the console, by posting a WM_CLOSE - // message to the console window. - m_hwnd = GetConsoleWindow(); - ASSERT(m_hwnd != nullptr); -} - -std::wstring Win32Console::title() -{ - while (true) { - // Calling GetConsoleTitleW is tricky, because its behavior changed - // from XP->Vista, then again from Win7->Win8. The Vista+Win7 behavior - // is especially broken. - // - // The MSDN documentation documents nSize as the "size of the buffer - // pointed to by the lpConsoleTitle parameter, in characters" and the - // successful return value as "the length of the console window's - // title, in characters." - // - // On XP, the function returns the title length, AFTER truncation - // (excluding the NUL terminator). If the title is blank, the API - // returns 0 and does not NUL-terminate the buffer. To accommodate - // XP, the function must: - // * Terminate the buffer itself. - // * Double the size of the title buffer in a loop. - // - // On Vista and up, the function returns the non-truncated title - // length (excluding the NUL terminator). - // - // On Vista and Windows 7, there is a bug where the buffer size is - // interpreted as a byte count rather than a wchar_t count. To - // work around this, we must pass GetConsoleTitleW a buffer that is - // twice as large as what is actually needed. - // - // See misc/*/Test_GetConsoleTitleW.cc for tests demonstrating Windows' - // behavior. - - DWORD count = GetConsoleTitleW(m_titleWorkBuf.data(), - m_titleWorkBuf.size()); - const size_t needed = (count + 1) * sizeof(wchar_t); - if (m_titleWorkBuf.size() < needed) { - m_titleWorkBuf.resize(needed); - continue; - } - m_titleWorkBuf[count] = L'\0'; - return m_titleWorkBuf.data(); - } -} - -void Win32Console::setTitle(const std::wstring &title) -{ - if (!SetConsoleTitleW(title.c_str())) { - trace("SetConsoleTitleW failed"); - } -} - -void Win32Console::setFrozen(bool frozen) { - const int SC_CONSOLE_MARK = 0xFFF2; - const int SC_CONSOLE_SELECT_ALL = 0xFFF5; - if (frozen == m_frozen) { - // Do nothing. - } else if (frozen) { - // Enter selection mode by activating either Mark or SelectAll. - const int command = m_freezeUsesMark ? SC_CONSOLE_MARK - : SC_CONSOLE_SELECT_ALL; - SendMessage(m_hwnd, WM_SYSCOMMAND, command, 0); - m_frozen = true; - } else { - // Send Escape to cancel the selection. - SendMessage(m_hwnd, WM_CHAR, 27, 0x00010001); - m_frozen = false; - } -} diff --git a/deps/winpty/src/agent/Win32Console.h b/deps/winpty/src/agent/Win32Console.h deleted file mode 100644 index ed83877e9..000000000 --- a/deps/winpty/src/agent/Win32Console.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_WIN32_CONSOLE_H -#define AGENT_WIN32_CONSOLE_H - -#include - -#include -#include - -class Win32Console -{ -public: - class FreezeGuard { - public: - FreezeGuard(Win32Console &console, bool frozen) : - m_console(console), m_previous(console.frozen()) { - m_console.setFrozen(frozen); - } - ~FreezeGuard() { - m_console.setFrozen(m_previous); - } - FreezeGuard(const FreezeGuard &other) = delete; - FreezeGuard &operator=(const FreezeGuard &other) = delete; - private: - Win32Console &m_console; - bool m_previous; - }; - - Win32Console(); - - HWND hwnd() { return m_hwnd; } - std::wstring title(); - void setTitle(const std::wstring &title); - void setFreezeUsesMark(bool useMark) { m_freezeUsesMark = useMark; } - void setNewW10(bool isNewW10) { m_isNewW10 = isNewW10; } - bool isNewW10() { return m_isNewW10; } - void setFrozen(bool frozen=true); - bool frozen() { return m_frozen; } - -private: - HWND m_hwnd = nullptr; - bool m_frozen = false; - bool m_freezeUsesMark = false; - bool m_isNewW10 = false; - std::vector m_titleWorkBuf; -}; - -#endif // AGENT_WIN32_CONSOLE_H diff --git a/deps/winpty/src/agent/Win32ConsoleBuffer.cc b/deps/winpty/src/agent/Win32ConsoleBuffer.cc deleted file mode 100644 index ed93f4081..000000000 --- a/deps/winpty/src/agent/Win32ConsoleBuffer.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Win32ConsoleBuffer.h" - -#include - -#include "../shared/DebugClient.h" -#include "../shared/StringBuilder.h" -#include "../shared/WinptyAssert.h" - -std::unique_ptr Win32ConsoleBuffer::openStdout() { - return std::unique_ptr( - new Win32ConsoleBuffer(GetStdHandle(STD_OUTPUT_HANDLE), false)); -} - -std::unique_ptr Win32ConsoleBuffer::openConout() { - const HANDLE conout = CreateFileW(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - ASSERT(conout != INVALID_HANDLE_VALUE); - return std::unique_ptr( - new Win32ConsoleBuffer(conout, true)); -} - -std::unique_ptr Win32ConsoleBuffer::createErrorBuffer() { - SECURITY_ATTRIBUTES sa = {}; - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - const HANDLE conout = - CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - CONSOLE_TEXTMODE_BUFFER, - nullptr); - ASSERT(conout != INVALID_HANDLE_VALUE); - return std::unique_ptr( - new Win32ConsoleBuffer(conout, true)); -} - -HANDLE Win32ConsoleBuffer::conout() { - return m_conout; -} - -void Win32ConsoleBuffer::clearLines( - int row, - int count, - const ConsoleScreenBufferInfo &info) { - // TODO: error handling - const int width = info.bufferSize().X; - DWORD actual = 0; - if (!FillConsoleOutputCharacterW( - m_conout, L' ', width * count, Coord(0, row), - &actual) || static_cast(actual) != width * count) { - trace("FillConsoleOutputCharacterW failed"); - } - if (!FillConsoleOutputAttribute( - m_conout, kDefaultAttributes, width * count, Coord(0, row), - &actual) || static_cast(actual) != width * count) { - trace("FillConsoleOutputAttribute failed"); - } -} - -void Win32ConsoleBuffer::clearAllLines(const ConsoleScreenBufferInfo &info) { - clearLines(0, info.bufferSize().Y, info); -} - -ConsoleScreenBufferInfo Win32ConsoleBuffer::bufferInfo() { - // TODO: error handling - ConsoleScreenBufferInfo info; - if (!GetConsoleScreenBufferInfo(m_conout, &info)) { - trace("GetConsoleScreenBufferInfo failed"); - } - return info; -} - -Coord Win32ConsoleBuffer::bufferSize() { - return bufferInfo().bufferSize(); -} - -SmallRect Win32ConsoleBuffer::windowRect() { - return bufferInfo().windowRect(); -} - -bool Win32ConsoleBuffer::resizeBufferRange(const Coord &initialSize, - Coord &finalSize) { - if (SetConsoleScreenBufferSize(m_conout, initialSize)) { - finalSize = initialSize; - return true; - } - // The font might be too small to accommodate a very narrow console window. - // In that case, rather than simply give up, it's better to try wider - // buffer sizes until the call succeeds. - Coord size = initialSize; - while (size.X < 20) { - size.X++; - if (SetConsoleScreenBufferSize(m_conout, size)) { - finalSize = size; - trace("SetConsoleScreenBufferSize: initial size (%d,%d) failed, " - "but wider size (%d,%d) succeeded", - initialSize.X, initialSize.Y, - finalSize.X, finalSize.Y); - return true; - } - } - trace("SetConsoleScreenBufferSize failed: " - "tried (%d,%d) through (%d,%d)", - initialSize.X, initialSize.Y, - size.X, size.Y); - return false; -} - -void Win32ConsoleBuffer::resizeBuffer(const Coord &size) { - // TODO: error handling - if (!SetConsoleScreenBufferSize(m_conout, size)) { - trace("SetConsoleScreenBufferSize failed: size=(%d,%d)", - size.X, size.Y); - } -} - -void Win32ConsoleBuffer::moveWindow(const SmallRect &rect) { - // TODO: error handling - if (!SetConsoleWindowInfo(m_conout, TRUE, &rect)) { - trace("SetConsoleWindowInfo failed"); - } -} - -Coord Win32ConsoleBuffer::cursorPosition() { - return bufferInfo().dwCursorPosition; -} - -void Win32ConsoleBuffer::setCursorPosition(const Coord &coord) { - // TODO: error handling - if (!SetConsoleCursorPosition(m_conout, coord)) { - trace("SetConsoleCursorPosition failed"); - } -} - -void Win32ConsoleBuffer::read(const SmallRect &rect, CHAR_INFO *data) { - // TODO: error handling - SmallRect tmp(rect); - if (!ReadConsoleOutputW(m_conout, data, rect.size(), Coord(), &tmp) && - isTracingEnabled()) { - StringBuilder sb(256); - auto outStruct = [&](const SMALL_RECT &sr) { - sb << "{L=" << sr.Left << ",T=" << sr.Top - << ",R=" << sr.Right << ",B=" << sr.Bottom << '}'; - }; - sb << "Win32ConsoleBuffer::read: ReadConsoleOutput failed: readRegion="; - outStruct(rect); - CONSOLE_SCREEN_BUFFER_INFO info = {}; - if (GetConsoleScreenBufferInfo(m_conout, &info)) { - sb << ", dwSize=(" << info.dwSize.X << ',' << info.dwSize.Y - << "), srWindow="; - outStruct(info.srWindow); - } else { - sb << ", GetConsoleScreenBufferInfo also failed"; - } - trace("%s", sb.c_str()); - } -} - -void Win32ConsoleBuffer::write(const SmallRect &rect, const CHAR_INFO *data) { - // TODO: error handling - SmallRect tmp(rect); - if (!WriteConsoleOutputW(m_conout, data, rect.size(), Coord(), &tmp)) { - trace("WriteConsoleOutput failed"); - } -} - -void Win32ConsoleBuffer::setTextAttribute(WORD attributes) { - if (!SetConsoleTextAttribute(m_conout, attributes)) { - trace("SetConsoleTextAttribute failed"); - } -} diff --git a/deps/winpty/src/agent/Win32ConsoleBuffer.h b/deps/winpty/src/agent/Win32ConsoleBuffer.h deleted file mode 100644 index a68d8d304..000000000 --- a/deps/winpty/src/agent/Win32ConsoleBuffer.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef AGENT_WIN32_CONSOLE_BUFFER_H -#define AGENT_WIN32_CONSOLE_BUFFER_H - -#include - -#include - -#include - -#include "Coord.h" -#include "SmallRect.h" - -class ConsoleScreenBufferInfo : public CONSOLE_SCREEN_BUFFER_INFO { -public: - ConsoleScreenBufferInfo() - { - memset(this, 0, sizeof(*this)); - } - - Coord bufferSize() const { return dwSize; } - SmallRect windowRect() const { return srWindow; } - Coord cursorPosition() const { return dwCursorPosition; } -}; - -class Win32ConsoleBuffer { -private: - Win32ConsoleBuffer(HANDLE conout, bool owned) : - m_conout(conout), m_owned(owned) - { - } - -public: - static const int kDefaultAttributes = 7; - - ~Win32ConsoleBuffer() { - if (m_owned) { - CloseHandle(m_conout); - } - } - - static std::unique_ptr openStdout(); - static std::unique_ptr openConout(); - static std::unique_ptr createErrorBuffer(); - - Win32ConsoleBuffer(const Win32ConsoleBuffer &other) = delete; - Win32ConsoleBuffer &operator=(const Win32ConsoleBuffer &other) = delete; - - HANDLE conout(); - void clearLines(int row, int count, const ConsoleScreenBufferInfo &info); - void clearAllLines(const ConsoleScreenBufferInfo &info); - - // Buffer and window sizes. - ConsoleScreenBufferInfo bufferInfo(); - Coord bufferSize(); - SmallRect windowRect(); - void resizeBuffer(const Coord &size); - bool resizeBufferRange(const Coord &initialSize, Coord &finalSize); - bool resizeBufferRange(const Coord &initialSize) { - Coord dummy; - return resizeBufferRange(initialSize, dummy); - } - void moveWindow(const SmallRect &rect); - - // Cursor. - Coord cursorPosition(); - void setCursorPosition(const Coord &point); - - // Screen content. - void read(const SmallRect &rect, CHAR_INFO *data); - void write(const SmallRect &rect, const CHAR_INFO *data); - - void setTextAttribute(WORD attributes); - -private: - HANDLE m_conout = nullptr; - bool m_owned = false; -}; - -#endif // AGENT_WIN32_CONSOLE_BUFFER_H diff --git a/deps/winpty/src/agent/main.cc b/deps/winpty/src/agent/main.cc deleted file mode 100644 index 2420fde4d..000000000 --- a/deps/winpty/src/agent/main.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include -#include -#include -#include - -#include "../shared/StringUtil.h" -#include "../shared/WindowsVersion.h" -#include "../shared/WinptyAssert.h" -#include "../shared/WinptyVersion.h" - -#include "Agent.h" -#include "AgentCreateDesktop.h" -#include "DebugShowInput.h" - -const char USAGE[] = -"Usage: %ls controlPipeName flags mouseMode cols rows\n" -"Usage: %ls controlPipeName --create-desktop\n" -"\n" -"Ordinarily, this program is launched by winpty.dll and is not directly\n" -"useful to winpty users. However, it also has options intended for\n" -"debugging winpty.\n" -"\n" -"Usage: %ls [options]\n" -"\n" -"Options:\n" -" --show-input [--with-mouse] [--escape-input]\n" -" Dump INPUT_RECORDs from the console input buffer\n" -" --with-mouse: Include MOUSE_INPUT_RECORDs in the dump\n" -" output\n" -" --escape-input: Direct the new Windows 10 console to use\n" -" escape sequences for input\n" -" --version Print the winpty version\n"; - -static uint64_t winpty_atoi64(const char *str) { - return strtoll(str, NULL, 10); -} - -int main() { - dumpWindowsVersion(); - dumpVersionToTrace(); - - // Technically, we should free the CommandLineToArgvW return value using - // a single call to LocalFree, but the call will never actually happen in - // the normal case. - int argc = 0; - wchar_t *cmdline = GetCommandLineW(); - ASSERT(cmdline != nullptr && "GetCommandLineW returned NULL"); - wchar_t **argv = CommandLineToArgvW(cmdline, &argc); - ASSERT(argv != nullptr && "CommandLineToArgvW returned NULL"); - - if (argc == 2 && !wcscmp(argv[1], L"--version")) { - dumpVersionToStdout(); - return 0; - } - - if (argc >= 2 && !wcscmp(argv[1], L"--show-input")) { - bool withMouse = false; - bool escapeInput = false; - for (int i = 2; i < argc; ++i) { - if (!wcscmp(argv[i], L"--with-mouse")) { - withMouse = true; - } else if (!wcscmp(argv[i], L"--escape-input")) { - escapeInput = true; - } else { - fprintf(stderr, "Unrecognized --show-input option: %ls\n", - argv[i]); - return 1; - } - } - debugShowInput(withMouse, escapeInput); - return 0; - } - - if (argc == 3 && !wcscmp(argv[2], L"--create-desktop")) { - handleCreateDesktop(argv[1]); - return 0; - } - - if (argc != 6) { - fprintf(stderr, USAGE, argv[0], argv[0], argv[0]); - return 1; - } - - Agent agent(argv[1], - winpty_atoi64(utf8FromWide(argv[2]).c_str()), - atoi(utf8FromWide(argv[3]).c_str()), - atoi(utf8FromWide(argv[4]).c_str()), - atoi(utf8FromWide(argv[5]).c_str())); - agent.run(); - - // The Agent destructor shouldn't return, but if it does, exit - // unsuccessfully. - return 1; -} diff --git a/deps/winpty/src/agent/subdir.mk b/deps/winpty/src/agent/subdir.mk deleted file mode 100644 index 1c7d37e3e..000000000 --- a/deps/winpty/src/agent/subdir.mk +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2011-2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -ALL_TARGETS += build/winpty-agent.exe - -$(eval $(call def_mingw_target,agent,-DWINPTY_AGENT_ASSERT)) - -AGENT_OBJECTS = \ - build/agent/agent/Agent.o \ - build/agent/agent/AgentCreateDesktop.o \ - build/agent/agent/ConsoleFont.o \ - build/agent/agent/ConsoleInput.o \ - build/agent/agent/ConsoleInputReencoding.o \ - build/agent/agent/ConsoleLine.o \ - build/agent/agent/DebugShowInput.o \ - build/agent/agent/DefaultInputMap.o \ - build/agent/agent/EventLoop.o \ - build/agent/agent/InputMap.o \ - build/agent/agent/LargeConsoleRead.o \ - build/agent/agent/NamedPipe.o \ - build/agent/agent/Scraper.o \ - build/agent/agent/Terminal.o \ - build/agent/agent/Win32Console.o \ - build/agent/agent/Win32ConsoleBuffer.o \ - build/agent/agent/main.o \ - build/agent/shared/BackgroundDesktop.o \ - build/agent/shared/Buffer.o \ - build/agent/shared/DebugClient.o \ - build/agent/shared/GenRandom.o \ - build/agent/shared/OwnedHandle.o \ - build/agent/shared/StringUtil.o \ - build/agent/shared/WindowsSecurity.o \ - build/agent/shared/WindowsVersion.o \ - build/agent/shared/WinptyAssert.o \ - build/agent/shared/WinptyException.o \ - build/agent/shared/WinptyVersion.o - -build/agent/shared/WinptyVersion.o : build/gen/GenVersion.h - -build/winpty-agent.exe : $(AGENT_OBJECTS) - $(info Linking $@) - @$(MINGW_CXX) $(MINGW_LDFLAGS) -o $@ $^ - --include $(AGENT_OBJECTS:.o=.d) diff --git a/deps/winpty/src/configurations.gypi b/deps/winpty/src/configurations.gypi deleted file mode 100644 index e990a6033..000000000 --- a/deps/winpty/src/configurations.gypi +++ /dev/null @@ -1,60 +0,0 @@ -# By default gyp/msbuild build for 32-bit Windows. This gyp include file -# defines configurations for both 32-bit and 64-bit Windows. To use it, run: -# -# C:\...\winpty\src>gyp -I configurations.gypi -# -# This command generates Visual Studio project files with a Release -# configuration and two Platforms--Win32 and x64. Both can be built: -# -# C:\...\winpty\src>msbuild winpty.sln /p:Platform=Win32 -# C:\...\winpty\src>msbuild winpty.sln /p:Platform=x64 -# -# The output is placed in: -# -# C:\...\winpty\src\Release\Win32 -# C:\...\winpty\src\Release\x64 -# -# Windows XP note: By default, the project files will use the default "toolset" -# for the given MSVC version. For MSVC 2013 and MSVC 2015, the default toolset -# generates binaries that do not run on Windows XP. To target Windows XP, -# select the XP-specific toolset by passing -# -D WINPTY_MSBUILD_TOOLSET={v120_xp,v140_xp} to gyp (v120_xp == MSVC 2013, -# v140_xp == MSVC 2015). Unfortunately, it isn't possible to have a single -# project file with configurations for both XP and post-XP. This seems to be a -# limitation of the MSVC project file format. -# -# This file is not included by default, because I suspect it would interfere -# with node-gyp, which has a different system for building 32-vs-64-bit -# binaries. It uses a common.gypi, and the project files it generates can only -# build a single architecture, the output paths are not differentiated by -# architecture. - -{ - 'variables': { - 'WINPTY_MSBUILD_TOOLSET%': '', - }, - 'target_defaults': { - 'default_configuration': 'Release_Win32', - 'configurations': { - 'Release_Win32': { - 'msvs_configuration_platform': 'Win32', - }, - 'Release_x64': { - 'msvs_configuration_platform': 'x64', - }, - }, - 'msvs_configuration_attributes': { - 'OutputDirectory': '$(SolutionDir)$(ConfigurationName)\\$(Platform)', - 'IntermediateDirectory': '$(ConfigurationName)\\$(Platform)\\obj\\$(ProjectName)', - }, - 'msvs_settings': { - 'VCLinkerTool': { - 'SubSystem': '1', # /SUBSYSTEM:CONSOLE - }, - 'VCCLCompilerTool': { - 'RuntimeLibrary': '0', # MultiThreaded (/MT) - }, - }, - 'msbuild_toolset' : '<(WINPTY_MSBUILD_TOOLSET)', - } -} diff --git a/deps/winpty/src/debugserver/DebugServer.cc b/deps/winpty/src/debugserver/DebugServer.cc deleted file mode 100644 index 353d31c1c..000000000 --- a/deps/winpty/src/debugserver/DebugServer.cc +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include -#include - -#include - -#include "../shared/WindowsSecurity.h" -#include "../shared/WinptyException.h" - -const wchar_t *kPipeName = L"\\\\.\\pipe\\DebugServer"; - -// A message may not be larger than this size. -const int MSG_SIZE = 4096; - -static void usage(const char *program, int code) { - printf("Usage: %s [--everyone]\n" - "\n" - "Creates the named pipe %ls and reads messages. Prints each\n" - "message to stdout. By default, only the current user can send messages.\n" - "Pass --everyone to let anyone send a message.\n" - "\n" - "Use the WINPTY_DEBUG environment variable to enable winpty trace output.\n" - "(e.g. WINPTY_DEBUG=trace for the default trace output.) Set WINPTYDBG=1\n" - "to enable trace with older winpty versions.\n", - program, kPipeName); - exit(code); -} - -int main(int argc, char *argv[]) { - bool everyone = false; - for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - if (arg == "--everyone") { - everyone = true; - } else if (arg == "-h" || arg == "--help") { - usage(argv[0], 0); - } else { - usage(argv[0], 1); - } - } - - SecurityDescriptor sd; - PSECURITY_ATTRIBUTES psa = nullptr; - SECURITY_ATTRIBUTES sa = {}; - if (everyone) { - try { - sd = createPipeSecurityDescriptorOwnerFullControlEveryoneWrite(); - } catch (const WinptyException &e) { - fprintf(stderr, - "error creating security descriptor: %ls\n", e.what()); - exit(1); - } - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = sd.get(); - psa = &sa; - } - - HANDLE serverPipe = CreateNamedPipeW( - kPipeName, - /*dwOpenMode=*/PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, - /*dwPipeMode=*/PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | - rejectRemoteClientsPipeFlag(), - /*nMaxInstances=*/1, - /*nOutBufferSize=*/MSG_SIZE, - /*nInBufferSize=*/MSG_SIZE, - /*nDefaultTimeOut=*/10 * 1000, - psa); - - if (serverPipe == INVALID_HANDLE_VALUE) { - fprintf(stderr, "error: could not create %ls pipe: error %u\n", - kPipeName, static_cast(GetLastError())); - exit(1); - } - - char msgBuffer[MSG_SIZE + 1]; - - while (true) { - if (!ConnectNamedPipe(serverPipe, nullptr)) { - fprintf(stderr, "error: ConnectNamedPipe failed\n"); - fflush(stderr); - exit(1); - } - DWORD bytesRead = 0; - if (!ReadFile(serverPipe, msgBuffer, MSG_SIZE, &bytesRead, nullptr)) { - fprintf(stderr, "error: ReadFile on pipe failed\n"); - fflush(stderr); - DisconnectNamedPipe(serverPipe); - continue; - } - msgBuffer[bytesRead] = '\n'; - fwrite(msgBuffer, 1, bytesRead + 1, stdout); - fflush(stdout); - - DWORD bytesWritten = 0; - WriteFile(serverPipe, "OK", 2, &bytesWritten, nullptr); - DisconnectNamedPipe(serverPipe); - } -} diff --git a/deps/winpty/src/debugserver/subdir.mk b/deps/winpty/src/debugserver/subdir.mk deleted file mode 100644 index beed1bd59..000000000 --- a/deps/winpty/src/debugserver/subdir.mk +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -ALL_TARGETS += build/winpty-debugserver.exe - -$(eval $(call def_mingw_target,debugserver,)) - -DEBUGSERVER_OBJECTS = \ - build/debugserver/debugserver/DebugServer.o \ - build/debugserver/shared/DebugClient.o \ - build/debugserver/shared/OwnedHandle.o \ - build/debugserver/shared/StringUtil.o \ - build/debugserver/shared/WindowsSecurity.o \ - build/debugserver/shared/WindowsVersion.o \ - build/debugserver/shared/WinptyAssert.o \ - build/debugserver/shared/WinptyException.o - -build/debugserver/shared/WindowsVersion.o : build/gen/GenVersion.h - -build/winpty-debugserver.exe : $(DEBUGSERVER_OBJECTS) - $(info Linking $@) - @$(MINGW_CXX) $(MINGW_LDFLAGS) -o $@ $^ - --include $(DEBUGSERVER_OBJECTS:.o=.d) diff --git a/deps/winpty/src/include/winpty.h b/deps/winpty/src/include/winpty.h deleted file mode 100644 index fdfe4bca2..000000000 --- a/deps/winpty/src/include/winpty.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2011-2016 Ryan Prichard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef WINPTY_H -#define WINPTY_H - -#include - -#include "winpty_constants.h" - -/* On 32-bit Windows, winpty functions have the default __cdecl (not __stdcall) - * calling convention. (64-bit Windows has only a single calling convention.) - * When compiled with __declspec(dllexport), with either MinGW or MSVC, the - * winpty functions are unadorned--no underscore prefix or '@nn' suffix--so - * GetProcAddress can be used easily. */ -#ifdef COMPILING_WINPTY_DLL -#define WINPTY_API __declspec(dllexport) -#else -#define WINPTY_API __declspec(dllimport) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* The winpty API uses wide characters, instead of UTF-8, to avoid conversion - * complications related to surrogates. Windows generally tolerates unpaired - * surrogates in text, which makes conversion to and from UTF-8 ambiguous and - * complicated. (There are different UTF-8 variants that deal with UTF-16 - * surrogates differently.) */ - - - -/***************************************************************************** - * Error handling. */ - -/* All the APIs have an optional winpty_error_t output parameter. If a - * non-NULL argument is specified, then either the API writes NULL to the - * value (on success) or writes a newly allocated winpty_error_t object. The - * object must be freed using winpty_error_free. */ - -/* An error object. */ -typedef struct winpty_error_s winpty_error_t; -typedef winpty_error_t *winpty_error_ptr_t; - -/* An error code -- one of WINPTY_ERROR_xxx. */ -typedef DWORD winpty_result_t; - -/* Gets the error code from the error object. */ -WINPTY_API winpty_result_t winpty_error_code(winpty_error_ptr_t err); - -/* Returns a textual representation of the error. The string is freed when - * the error is freed. */ -WINPTY_API LPCWSTR winpty_error_msg(winpty_error_ptr_t err); - -/* Free the error object. Every error returned from the winpty API must be - * freed. */ -WINPTY_API void winpty_error_free(winpty_error_ptr_t err); - - - -/***************************************************************************** - * Configuration of a new agent. */ - -/* The winpty_config_t object is not thread-safe. */ -typedef struct winpty_config_s winpty_config_t; - -/* Allocate a winpty_config_t value. Returns NULL on error. There are no - * required settings -- the object may immediately be used. agentFlags is a - * set of zero or more WINPTY_FLAG_xxx values. An unrecognized flag results - * in an assertion failure. */ -WINPTY_API winpty_config_t * -winpty_config_new(UINT64 agentFlags, winpty_error_ptr_t *err /*OPTIONAL*/); - -/* Free the cfg object after passing it to winpty_open. */ -WINPTY_API void winpty_config_free(winpty_config_t *cfg); - -WINPTY_API void -winpty_config_set_initial_size(winpty_config_t *cfg, int cols, int rows); - -/* Set the mouse mode to one of the WINPTY_MOUSE_MODE_xxx constants. */ -WINPTY_API void -winpty_config_set_mouse_mode(winpty_config_t *cfg, int mouseMode); - -/* Amount of time to wait for the agent to startup and to wait for any given - * agent RPC request. Must be greater than 0. Can be INFINITE. */ -WINPTY_API void -winpty_config_set_agent_timeout(winpty_config_t *cfg, DWORD timeoutMs); - - - -/***************************************************************************** - * Start the agent. */ - -/* The winpty_t object is thread-safe. */ -typedef struct winpty_s winpty_t; - -/* Starts the agent. Returns NULL on error. This process will connect to the - * agent over a control pipe, and the agent will open data pipes (e.g. CONIN - * and CONOUT). */ -WINPTY_API winpty_t * -winpty_open(const winpty_config_t *cfg, - winpty_error_ptr_t *err /*OPTIONAL*/); - -/* A handle to the agent process. This value is valid for the lifetime of the - * winpty_t object. Do not close it. */ -WINPTY_API HANDLE winpty_agent_process(winpty_t *wp); - - - -/***************************************************************************** - * I/O pipes. */ - -/* Returns the names of named pipes used for terminal I/O. Each input or - * output direction uses a different half-duplex pipe. The agent creates - * these pipes, and the client can connect to them using ordinary I/O methods. - * The strings are freed when the winpty_t object is freed. - * - * winpty_conerr_name returns NULL unless WINPTY_FLAG_CONERR is specified. - * - * N.B.: CreateFile does not block when connecting to a local server pipe. If - * the server pipe does not exist or is already connected, then it fails - * instantly. */ -WINPTY_API LPCWSTR winpty_conin_name(winpty_t *wp); -WINPTY_API LPCWSTR winpty_conout_name(winpty_t *wp); -WINPTY_API LPCWSTR winpty_conerr_name(winpty_t *wp); - - - -/***************************************************************************** - * winpty agent RPC call: process creation. */ - -/* The winpty_spawn_config_t object is not thread-safe. */ -typedef struct winpty_spawn_config_s winpty_spawn_config_t; - -/* winpty_spawn_config strings do not need to live as long as the config - * object. They are copied. Returns NULL on error. spawnFlags is a set of - * zero or more WINPTY_SPAWN_FLAG_xxx values. An unrecognized flag results in - * an assertion failure. - * - * env is a a pointer to an environment block like that passed to - * CreateProcess--a contiguous array of NUL-terminated "VAR=VAL" strings - * followed by a final NUL terminator. - * - * N.B.: If you want to gather all of the child's output, you may want the - * WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN flag. - */ -WINPTY_API winpty_spawn_config_t * -winpty_spawn_config_new(UINT64 spawnFlags, - LPCWSTR appname /*OPTIONAL*/, - LPCWSTR cmdline /*OPTIONAL*/, - LPCWSTR cwd /*OPTIONAL*/, - LPCWSTR env /*OPTIONAL*/, - winpty_error_ptr_t *err /*OPTIONAL*/); - -/* Free the cfg object after passing it to winpty_spawn. */ -WINPTY_API void winpty_spawn_config_free(winpty_spawn_config_t *cfg); - -/* - * Spawns the new process. - * - * The function initializes all output parameters to zero or NULL. - * - * On success, the function returns TRUE. For each of process_handle and - * thread_handle that is non-NULL, the HANDLE returned from CreateProcess is - * duplicated from the agent and returned to the winpty client. The client is - * responsible for closing these HANDLES. - * - * On failure, the function returns FALSE, and if err is non-NULL, then *err - * is set to an error object. - * - * If the agent's CreateProcess call failed, then *create_process_error is set - * to GetLastError(), and the WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED error - * is returned. - * - * winpty_spawn can only be called once per winpty_t object. If it is called - * before the output data pipe(s) is/are connected, then collected output is - * buffered until the pipes are connected, rather than being discarded. - * - * N.B.: GetProcessId works even if the process has exited. The PID is not - * recycled until the NT process object is freed. - * (https://blogs.msdn.microsoft.com/oldnewthing/20110107-00/?p=11803) - */ -WINPTY_API BOOL -winpty_spawn(winpty_t *wp, - const winpty_spawn_config_t *cfg, - HANDLE *process_handle /*OPTIONAL*/, - HANDLE *thread_handle /*OPTIONAL*/, - DWORD *create_process_error /*OPTIONAL*/, - winpty_error_ptr_t *err /*OPTIONAL*/); - - - -/***************************************************************************** - * winpty agent RPC calls: everything else */ - -/* Change the size of the Windows console window. */ -WINPTY_API BOOL -winpty_set_size(winpty_t *wp, int cols, int rows, - winpty_error_ptr_t *err /*OPTIONAL*/); - -/* Gets a list of processes attached to the console. */ -WINPTY_API int -winpty_get_console_process_list(winpty_t *wp, int *processList, const int processCount, - winpty_error_ptr_t *err /*OPTIONAL*/); - -/* Frees the winpty_t object and the OS resources contained in it. This - * call breaks the connection with the agent, which should then close its - * console, terminating the processes attached to it. - * - * This function must not be called if any other threads are using the - * winpty_t object. Undefined behavior results. */ -WINPTY_API void winpty_free(winpty_t *wp); - - - -/****************************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* WINPTY_H */ diff --git a/deps/winpty/src/include/winpty_constants.h b/deps/winpty/src/include/winpty_constants.h deleted file mode 100644 index 11e34cf17..000000000 --- a/deps/winpty/src/include/winpty_constants.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2016 Ryan Prichard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef WINPTY_CONSTANTS_H -#define WINPTY_CONSTANTS_H - -/* - * You may want to include winpty.h instead, which includes this header. - * - * This file is split out from winpty.h so that the agent can access the - * winpty flags without also declaring the libwinpty APIs. - */ - -/***************************************************************************** - * Error codes. */ - -#define WINPTY_ERROR_SUCCESS 0 -#define WINPTY_ERROR_OUT_OF_MEMORY 1 -#define WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED 2 -#define WINPTY_ERROR_LOST_CONNECTION 3 -#define WINPTY_ERROR_AGENT_EXE_MISSING 4 -#define WINPTY_ERROR_UNSPECIFIED 5 -#define WINPTY_ERROR_AGENT_DIED 6 -#define WINPTY_ERROR_AGENT_TIMEOUT 7 -#define WINPTY_ERROR_AGENT_CREATION_FAILED 8 - - - -/***************************************************************************** - * Configuration of a new agent. */ - -/* Create a new screen buffer (connected to the "conerr" terminal pipe) and - * pass it to child processes as the STDERR handle. This flag also prevents - * the agent from reopening CONOUT$ when it polls -- regardless of whether the - * active screen buffer changes, winpty continues to monitor the original - * primary screen buffer. */ -#define WINPTY_FLAG_CONERR 0x1ull - -/* Don't output escape sequences. */ -#define WINPTY_FLAG_PLAIN_OUTPUT 0x2ull - -/* Do output color escape sequences. These escapes are output by default, but - * are suppressed with WINPTY_FLAG_PLAIN_OUTPUT. Use this flag to reenable - * them. */ -#define WINPTY_FLAG_COLOR_ESCAPES 0x4ull - -/* On XP and Vista, winpty needs to put the hidden console on a desktop in a - * service window station so that its polling does not interfere with other - * (visible) console windows. To create this desktop, it must change the - * process' window station (i.e. SetProcessWindowStation) for the duration of - * the winpty_open call. In theory, this change could interfere with the - * winpty client (e.g. other threads, spawning children), so winpty by default - * spawns a special agent process to create the hidden desktop. Spawning - * processes on Windows is slow, though, so if - * WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION is set, winpty changes this - * process' window station instead. - * See https://github.com/rprichard/winpty/issues/58. */ -#define WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION 0x8ull - -#define WINPTY_FLAG_MASK (0ull \ - | WINPTY_FLAG_CONERR \ - | WINPTY_FLAG_PLAIN_OUTPUT \ - | WINPTY_FLAG_COLOR_ESCAPES \ - | WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION \ -) - -/* QuickEdit mode is initially disabled, and the agent does not send mouse - * mode sequences to the terminal. If it receives mouse input, though, it - * still writes MOUSE_EVENT_RECORD values into CONIN. */ -#define WINPTY_MOUSE_MODE_NONE 0 - -/* QuickEdit mode is initially enabled. As CONIN enters or leaves mouse - * input mode (i.e. where ENABLE_MOUSE_INPUT is on and ENABLE_QUICK_EDIT_MODE - * is off), the agent enables or disables mouse input on the terminal. - * - * This is the default mode. */ -#define WINPTY_MOUSE_MODE_AUTO 1 - -/* QuickEdit mode is initially disabled, and the agent enables the terminal's - * mouse input mode. It does not disable terminal mouse mode (until exit). */ -#define WINPTY_MOUSE_MODE_FORCE 2 - - - -/***************************************************************************** - * winpty agent RPC call: process creation. */ - -/* If the spawn is marked "auto-shutdown", then the agent shuts down console - * output once the process exits. The agent stops polling for new console - * output, and once all pending data has been written to the output pipe, the - * agent closes the pipe. (At that point, the pipe may still have data in it, - * which the client may read. Once all the data has been read, further reads - * return EOF.) */ -#define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ull - -/* After the agent shuts down output, and after all output has been written - * into the pipe(s), exit the agent by closing the console. If there any - * surviving processes still attached to the console, they are killed. - * - * Note: With this flag, an RPC call (e.g. winpty_set_size) issued after the - * agent exits will fail with an I/O or dead-agent error. */ -#define WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN 2ull - -/* All the spawn flags. */ -#define WINPTY_SPAWN_FLAG_MASK (0ull \ - | WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN \ - | WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN \ -) - - - -#endif /* WINPTY_CONSTANTS_H */ diff --git a/deps/winpty/src/libwinpty/AgentLocation.cc b/deps/winpty/src/libwinpty/AgentLocation.cc deleted file mode 100644 index 82d00b2da..000000000 --- a/deps/winpty/src/libwinpty/AgentLocation.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "AgentLocation.h" - -#include - -#include - -#include "../shared/WinptyAssert.h" - -#include "LibWinptyException.h" - -#define AGENT_EXE L"winpty-agent.exe" - -static HMODULE getCurrentModule() { - HMODULE module; - if (!GetModuleHandleExW( - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - reinterpret_cast(getCurrentModule), - &module)) { - ASSERT(false && "GetModuleHandleEx failed"); - } - return module; -} - -static std::wstring getModuleFileName(HMODULE module) { - const int bufsize = 4096; - wchar_t path[bufsize]; - int size = GetModuleFileNameW(module, path, bufsize); - ASSERT(size != 0 && size != bufsize); - return std::wstring(path); -} - -static std::wstring dirname(const std::wstring &path) { - std::wstring::size_type pos = path.find_last_of(L"\\/"); - if (pos == std::wstring::npos) { - return L""; - } else { - return path.substr(0, pos); - } -} - -static bool pathExists(const std::wstring &path) { - return GetFileAttributesW(path.c_str()) != 0xFFFFFFFF; -} - -std::wstring findAgentProgram() { - std::wstring progDir = dirname(getModuleFileName(getCurrentModule())); - std::wstring ret = progDir + (L"\\" AGENT_EXE); - if (!pathExists(ret)) { - throw LibWinptyException( - WINPTY_ERROR_AGENT_EXE_MISSING, - (L"agent executable does not exist: '" + ret + L"'").c_str()); - } - return ret; -} diff --git a/deps/winpty/src/libwinpty/AgentLocation.h b/deps/winpty/src/libwinpty/AgentLocation.h deleted file mode 100644 index a96b854cd..000000000 --- a/deps/winpty/src/libwinpty/AgentLocation.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef LIBWINPTY_AGENT_LOCATION_H -#define LIBWINPTY_AGENT_LOCATION_H - -#include - -std::wstring findAgentProgram(); - -#endif // LIBWINPTY_AGENT_LOCATION_H diff --git a/deps/winpty/src/libwinpty/LibWinptyException.h b/deps/winpty/src/libwinpty/LibWinptyException.h deleted file mode 100644 index 2274798d2..000000000 --- a/deps/winpty/src/libwinpty/LibWinptyException.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef LIB_WINPTY_EXCEPTION_H -#define LIB_WINPTY_EXCEPTION_H - -#include "../include/winpty.h" - -#include "../shared/WinptyException.h" - -#include -#include - -class LibWinptyException : public WinptyException { -public: - LibWinptyException(winpty_result_t code, const wchar_t *what) : - m_code(code), m_what(std::make_shared(what)) {} - - winpty_result_t code() const WINPTY_NOEXCEPT { - return m_code; - } - - const wchar_t *what() const WINPTY_NOEXCEPT override { - return m_what->c_str(); - } - - std::shared_ptr whatSharedStr() const WINPTY_NOEXCEPT { - return m_what; - } - -private: - winpty_result_t m_code; - // Using a shared_ptr ensures that copying the object raises no exception. - std::shared_ptr m_what; -}; - -#endif // LIB_WINPTY_EXCEPTION_H diff --git a/deps/winpty/src/libwinpty/WinptyInternal.h b/deps/winpty/src/libwinpty/WinptyInternal.h deleted file mode 100644 index 93e992d5c..000000000 --- a/deps/winpty/src/libwinpty/WinptyInternal.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef LIBWINPTY_WINPTY_INTERNAL_H -#define LIBWINPTY_WINPTY_INTERNAL_H - -#include -#include - -#include "../include/winpty.h" - -#include "../shared/Mutex.h" -#include "../shared/OwnedHandle.h" - -// The structures in this header are not intended to be accessed directly by -// client programs. - -struct winpty_error_s { - winpty_result_t code; - const wchar_t *msgStatic; - // Use a pointer to a std::shared_ptr so that the struct remains simple - // enough to statically initialize, for the benefit of static error - // objects like kOutOfMemory. - std::shared_ptr *msgDynamic; -}; - -struct winpty_config_s { - uint64_t flags = 0; - int cols = 80; - int rows = 25; - int mouseMode = WINPTY_MOUSE_MODE_AUTO; - DWORD timeoutMs = 30000; -}; - -struct winpty_s { - Mutex mutex; - OwnedHandle agentProcess; - OwnedHandle controlPipe; - DWORD agentTimeoutMs = 0; - OwnedHandle ioEvent; - std::wstring spawnDesktopName; - std::wstring coninPipeName; - std::wstring conoutPipeName; - std::wstring conerrPipeName; -}; - -struct winpty_spawn_config_s { - uint64_t winptyFlags = 0; - std::wstring appname; - std::wstring cmdline; - std::wstring cwd; - std::wstring env; -}; - -#endif // LIBWINPTY_WINPTY_INTERNAL_H diff --git a/deps/winpty/src/libwinpty/subdir.mk b/deps/winpty/src/libwinpty/subdir.mk deleted file mode 100644 index ba32bad6e..000000000 --- a/deps/winpty/src/libwinpty/subdir.mk +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2011-2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -ALL_TARGETS += build/winpty.dll - -$(eval $(call def_mingw_target,libwinpty,-DCOMPILING_WINPTY_DLL)) - -LIBWINPTY_OBJECTS = \ - build/libwinpty/libwinpty/AgentLocation.o \ - build/libwinpty/libwinpty/winpty.o \ - build/libwinpty/shared/BackgroundDesktop.o \ - build/libwinpty/shared/Buffer.o \ - build/libwinpty/shared/DebugClient.o \ - build/libwinpty/shared/GenRandom.o \ - build/libwinpty/shared/OwnedHandle.o \ - build/libwinpty/shared/StringUtil.o \ - build/libwinpty/shared/WindowsSecurity.o \ - build/libwinpty/shared/WindowsVersion.o \ - build/libwinpty/shared/WinptyAssert.o \ - build/libwinpty/shared/WinptyException.o \ - build/libwinpty/shared/WinptyVersion.o - -build/libwinpty/shared/WinptyVersion.o : build/gen/GenVersion.h - -build/winpty.dll : $(LIBWINPTY_OBJECTS) - $(info Linking $@) - @$(MINGW_CXX) $(MINGW_LDFLAGS) -shared -o $@ $^ -Wl,--out-implib,build/winpty.lib - --include $(LIBWINPTY_OBJECTS:.o=.d) diff --git a/deps/winpty/src/libwinpty/winpty.cc b/deps/winpty/src/libwinpty/winpty.cc deleted file mode 100644 index 3d977498e..000000000 --- a/deps/winpty/src/libwinpty/winpty.cc +++ /dev/null @@ -1,970 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include - -#include -#include -#include - -#include -#include -#include - -#include "../include/winpty.h" - -#include "../shared/AgentMsg.h" -#include "../shared/BackgroundDesktop.h" -#include "../shared/Buffer.h" -#include "../shared/DebugClient.h" -#include "../shared/GenRandom.h" -#include "../shared/OwnedHandle.h" -#include "../shared/StringBuilder.h" -#include "../shared/StringUtil.h" -#include "../shared/WindowsSecurity.h" -#include "../shared/WindowsVersion.h" -#include "../shared/WinptyAssert.h" -#include "../shared/WinptyException.h" -#include "../shared/WinptyVersion.h" - -#include "AgentLocation.h" -#include "LibWinptyException.h" -#include "WinptyInternal.h" - - - -/***************************************************************************** - * Error handling -- translate C++ exceptions to an optional error object - * output and log the result. */ - -static const winpty_error_s kOutOfMemory = { - WINPTY_ERROR_OUT_OF_MEMORY, - L"Out of memory", - nullptr -}; - -static const winpty_error_s kBadRpcPacket = { - WINPTY_ERROR_UNSPECIFIED, - L"Bad RPC packet", - nullptr -}; - -static const winpty_error_s kUncaughtException = { - WINPTY_ERROR_UNSPECIFIED, - L"Uncaught C++ exception", - nullptr -}; - -/* Gets the error code from the error object. */ -WINPTY_API winpty_result_t winpty_error_code(winpty_error_ptr_t err) { - return err != nullptr ? err->code : WINPTY_ERROR_SUCCESS; -} - -/* Returns a textual representation of the error. The string is freed when - * the error is freed. */ -WINPTY_API LPCWSTR winpty_error_msg(winpty_error_ptr_t err) { - if (err != nullptr) { - if (err->msgStatic != nullptr) { - return err->msgStatic; - } else { - ASSERT(err->msgDynamic != nullptr); - std::wstring *msgPtr = err->msgDynamic->get(); - ASSERT(msgPtr != nullptr); - return msgPtr->c_str(); - } - } else { - return L"Success"; - } -} - -/* Free the error object. Every error returned from the winpty API must be - * freed. */ -WINPTY_API void winpty_error_free(winpty_error_ptr_t err) { - if (err != nullptr && err->msgDynamic != nullptr) { - delete err->msgDynamic; - delete err; - } -} - -static void translateException(winpty_error_ptr_t *&err) { - winpty_error_ptr_t ret = nullptr; - try { - try { - throw; - } catch (const ReadBuffer::DecodeError&) { - ret = const_cast(&kBadRpcPacket); - } catch (const LibWinptyException &e) { - std::unique_ptr obj(new winpty_error_t); - obj->code = e.code(); - obj->msgStatic = nullptr; - obj->msgDynamic = - new std::shared_ptr(e.whatSharedStr()); - ret = obj.release(); - } catch (const WinptyException &e) { - std::unique_ptr obj(new winpty_error_t); - std::shared_ptr msg(new std::wstring(e.what())); - obj->code = WINPTY_ERROR_UNSPECIFIED; - obj->msgStatic = nullptr; - obj->msgDynamic = new std::shared_ptr(msg); - ret = obj.release(); - } - } catch (const std::bad_alloc&) { - ret = const_cast(&kOutOfMemory); - } catch (...) { - ret = const_cast(&kUncaughtException); - } - trace("libwinpty error: code=%u msg='%s'", - static_cast(ret->code), - utf8FromWide(winpty_error_msg(ret)).c_str()); - if (err != nullptr) { - *err = ret; - } else { - winpty_error_free(ret); - } -} - -#define API_TRY \ - if (err != nullptr) { *err = nullptr; } \ - try - -#define API_CATCH(ret) \ - catch (...) { translateException(err); return (ret); } - - - -/***************************************************************************** - * Configuration of a new agent. */ - -WINPTY_API winpty_config_t * -winpty_config_new(UINT64 flags, winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT((flags & WINPTY_FLAG_MASK) == flags); - std::unique_ptr ret(new winpty_config_t); - ret->flags = flags; - return ret.release(); - } API_CATCH(nullptr) -} - -WINPTY_API void winpty_config_free(winpty_config_t *cfg) { - delete cfg; -} - -WINPTY_API void -winpty_config_set_initial_size(winpty_config_t *cfg, int cols, int rows) { - ASSERT(cfg != nullptr && cols > 0 && rows > 0); - cfg->cols = cols; - cfg->rows = rows; -} - -WINPTY_API void -winpty_config_set_mouse_mode(winpty_config_t *cfg, int mouseMode) { - ASSERT(cfg != nullptr && - mouseMode >= WINPTY_MOUSE_MODE_NONE && - mouseMode <= WINPTY_MOUSE_MODE_FORCE); - cfg->mouseMode = mouseMode; -} - -WINPTY_API void -winpty_config_set_agent_timeout(winpty_config_t *cfg, DWORD timeoutMs) { - ASSERT(cfg != nullptr && timeoutMs > 0); - cfg->timeoutMs = timeoutMs; -} - - - -/***************************************************************************** - * Agent I/O. */ - -namespace { - -// Once an I/O operation fails with ERROR_IO_PENDING, the caller *must* wait -// for it to complete, even after calling CancelIo on it! See -// https://blogs.msdn.microsoft.com/oldnewthing/20110202-00/?p=11613. This -// class enforces that requirement. -class PendingIo { - HANDLE m_file; - OVERLAPPED &m_over; - bool m_finished; -public: - // The file handle and OVERLAPPED object must live as long as the PendingIo - // object. - PendingIo(HANDLE file, OVERLAPPED &over) : - m_file(file), m_over(over), m_finished(false) {} - ~PendingIo() { - if (!m_finished) { - // We're not usually that interested in CancelIo's return value. - // In any case, we must not throw an exception in this dtor. - CancelIo(m_file); - waitForCompletion(); - } - } - std::tuple waitForCompletion(DWORD &actual) WINPTY_NOEXCEPT { - m_finished = true; - const BOOL success = - GetOverlappedResult(m_file, &m_over, &actual, TRUE); - return std::make_tuple(success, GetLastError()); - } - std::tuple waitForCompletion() WINPTY_NOEXCEPT { - DWORD actual = 0; - return waitForCompletion(actual); - } -}; - -} // anonymous namespace - -static void handlePendingIo(winpty_t &wp, OVERLAPPED &over, BOOL &success, - DWORD &lastError, DWORD &actual) { - if (!success && lastError == ERROR_IO_PENDING) { - PendingIo io(wp.controlPipe.get(), over); - const HANDLE waitHandles[2] = { wp.ioEvent.get(), - wp.agentProcess.get() }; - DWORD waitRet = WaitForMultipleObjects( - 2, waitHandles, FALSE, wp.agentTimeoutMs); - if (waitRet != WAIT_OBJECT_0) { - // The I/O is still pending. Cancel it, close the I/O event, and - // throw an exception. - if (waitRet == WAIT_OBJECT_0 + 1) { - throw LibWinptyException(WINPTY_ERROR_AGENT_DIED, L"agent died"); - } else if (waitRet == WAIT_TIMEOUT) { - throw LibWinptyException(WINPTY_ERROR_AGENT_TIMEOUT, - L"agent timed out"); - } else if (waitRet == WAIT_FAILED) { - throwWindowsError(L"WaitForMultipleObjects failed"); - } else { - ASSERT(false && - "unexpected WaitForMultipleObjects return value"); - } - } - std::tie(success, lastError) = io.waitForCompletion(actual); - } -} - -static void handlePendingIo(winpty_t &wp, OVERLAPPED &over, BOOL &success, - DWORD &lastError) { - DWORD actual = 0; - handlePendingIo(wp, over, success, lastError, actual); -} - -static void handleReadWriteErrors(winpty_t &wp, BOOL success, DWORD lastError, - const wchar_t *genericErrMsg) { - if (!success) { - // If the pipe connection is broken after it's been connected, then - // later I/O operations fail with ERROR_BROKEN_PIPE (reads) or - // ERROR_NO_DATA (writes). With Wine, they may also fail with - // ERROR_PIPE_NOT_CONNECTED. See this gist[1]. - // - // [1] https://gist.github.com/rprichard/8dd8ca134b39534b7da2733994aa07ba - if (lastError == ERROR_BROKEN_PIPE || lastError == ERROR_NO_DATA || - lastError == ERROR_PIPE_NOT_CONNECTED) { - throw LibWinptyException(WINPTY_ERROR_LOST_CONNECTION, - L"lost connection to agent"); - } else { - throwWindowsError(genericErrMsg, lastError); - } - } -} - -// Calls ConnectNamedPipe to wait until the agent connects to the control pipe. -static void -connectControlPipe(winpty_t &wp) { - OVERLAPPED over = {}; - over.hEvent = wp.ioEvent.get(); - BOOL success = ConnectNamedPipe(wp.controlPipe.get(), &over); - DWORD lastError = GetLastError(); - handlePendingIo(wp, over, success, lastError); - if (!success && lastError == ERROR_PIPE_CONNECTED) { - success = TRUE; - } - if (!success) { - throwWindowsError(L"ConnectNamedPipe failed", lastError); - } -} - -static void writeData(winpty_t &wp, const void *data, size_t amount) { - // Perform a single pipe write. - DWORD actual = 0; - OVERLAPPED over = {}; - over.hEvent = wp.ioEvent.get(); - BOOL success = WriteFile(wp.controlPipe.get(), data, amount, - &actual, &over); - DWORD lastError = GetLastError(); - if (!success) { - handlePendingIo(wp, over, success, lastError, actual); - handleReadWriteErrors(wp, success, lastError, L"WriteFile failed"); - ASSERT(success); - } - // TODO: Can a partial write actually happen somehow? - ASSERT(actual == amount && "WriteFile wrote fewer bytes than requested"); -} - -static inline WriteBuffer newPacket() { - WriteBuffer packet; - packet.putRawValue(0); // Reserve space for size. - return packet; -} - -static void writePacket(winpty_t &wp, WriteBuffer &packet) { - const auto &buf = packet.buf(); - packet.replaceRawValue(0, buf.size()); - writeData(wp, buf.data(), buf.size()); -} - -static size_t readData(winpty_t &wp, void *data, size_t amount) { - DWORD actual = 0; - OVERLAPPED over = {}; - over.hEvent = wp.ioEvent.get(); - BOOL success = ReadFile(wp.controlPipe.get(), data, amount, - &actual, &over); - DWORD lastError = GetLastError(); - if (!success) { - handlePendingIo(wp, over, success, lastError, actual); - handleReadWriteErrors(wp, success, lastError, L"ReadFile failed"); - } - return actual; -} - -static void readAll(winpty_t &wp, void *data, size_t amount) { - while (amount > 0) { - const size_t chunk = readData(wp, data, amount); - ASSERT(chunk <= amount && "readData result is larger than amount"); - data = reinterpret_cast(data) + chunk; - amount -= chunk; - } -} - -static uint64_t readUInt64(winpty_t &wp) { - uint64_t ret = 0; - readAll(wp, &ret, sizeof(ret)); - return ret; -} - -// Returns a reply packet's payload. -static ReadBuffer readPacket(winpty_t &wp) { - const uint64_t packetSize = readUInt64(wp); - if (packetSize < sizeof(packetSize) || packetSize > SIZE_MAX) { - throwWinptyException(L"Agent RPC error: invalid packet size"); - } - const size_t payloadSize = packetSize - sizeof(packetSize); - std::vector bytes(payloadSize); - readAll(wp, bytes.data(), bytes.size()); - return ReadBuffer(std::move(bytes)); -} - -static OwnedHandle createControlPipe(const std::wstring &name) { - const auto sd = createPipeSecurityDescriptorOwnerFullControl(); - if (!sd) { - throwWinptyException( - L"could not create the control pipe's SECURITY_DESCRIPTOR"); - } - SECURITY_ATTRIBUTES sa = {}; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = sd.get(); - HANDLE ret = CreateNamedPipeW(name.c_str(), - /*dwOpenMode=*/ - PIPE_ACCESS_DUPLEX | - FILE_FLAG_FIRST_PIPE_INSTANCE | - FILE_FLAG_OVERLAPPED, - /*dwPipeMode=*/rejectRemoteClientsPipeFlag(), - /*nMaxInstances=*/1, - /*nOutBufferSize=*/8192, - /*nInBufferSize=*/256, - /*nDefaultTimeOut=*/30000, - &sa); - if (ret == INVALID_HANDLE_VALUE) { - throwWindowsError(L"CreateNamedPipeW failed"); - } - return OwnedHandle(ret); -} - - - -/***************************************************************************** - * Start the agent. */ - -static OwnedHandle createEvent() { - // manual reset, initially unset - HANDLE h = CreateEventW(nullptr, TRUE, FALSE, nullptr); - if (h == nullptr) { - throwWindowsError(L"CreateEventW failed"); - } - return OwnedHandle(h); -} - -// For debugging purposes, provide a way to keep the console on the main window -// station, visible. -static bool shouldShowConsoleWindow() { - char buf[32]; - return GetEnvironmentVariableA("WINPTY_SHOW_CONSOLE", buf, sizeof(buf)) > 0; -} - -static bool shouldCreateBackgroundDesktop(bool &createUsingAgent) { - // Prior to Windows 7, winpty's repeated selection-deselection loop - // prevented the user from interacting with their *visible* console - // windows, unless we placed the console onto a background desktop. - // The SetProcessWindowStation call interferes with the clipboard and - // isn't thread-safe, though[1]. The call should perhaps occur in a - // special agent subprocess. Spawning a process in a background desktop - // also breaks ConEmu, but marking the process SW_HIDE seems to correct - // that[2]. - // - // Windows 7 moved a lot of console handling out of csrss.exe and into - // a per-console conhost.exe process, which may explain why it isn't - // affected. - // - // This is a somewhat risky change, so there are low-level flags to - // assist in debugging if there are issues. - // - // [1] https://github.com/rprichard/winpty/issues/58 - // [2] https://github.com/rprichard/winpty/issues/70 - bool ret = !shouldShowConsoleWindow() && !isAtLeastWindows7(); - const bool force = hasDebugFlag("force_desktop"); - const bool force_spawn = hasDebugFlag("force_desktop_spawn"); - const bool force_curproc = hasDebugFlag("force_desktop_curproc"); - const bool suppress = hasDebugFlag("no_desktop"); - if (force + force_spawn + force_curproc + suppress > 1) { - trace("error: Only one of force_desktop, force_desktop_spawn, " - "force_desktop_curproc, and no_desktop may be set"); - } else if (force) { - ret = true; - } else if (force_spawn) { - ret = true; - createUsingAgent = true; - } else if (force_curproc) { - ret = true; - createUsingAgent = false; - } else if (suppress) { - ret = false; - } - return ret; -} - -static bool shouldSpecifyHideFlag() { - const bool force = hasDebugFlag("force_sw_hide"); - const bool suppress = hasDebugFlag("no_sw_hide"); - bool ret = !shouldShowConsoleWindow(); - if (force && suppress) { - trace("error: Both the force_sw_hide and no_sw_hide flags are set"); - } else if (force) { - ret = true; - } else if (suppress) { - ret = false; - } - return ret; -} - -static OwnedHandle startAgentProcess( - const std::wstring &desktop, - const std::wstring &controlPipeName, - const std::wstring ¶ms, - DWORD creationFlags, - DWORD &agentPid) { - const std::wstring exePath = findAgentProgram(); - const std::wstring cmdline = - (WStringBuilder(256) - << L"\"" << exePath << L"\" " - << controlPipeName << L' ' - << params).str_moved(); - - auto cmdlineV = vectorWithNulFromString(cmdline); - auto desktopV = vectorWithNulFromString(desktop); - - // Start the agent. - STARTUPINFOW sui = {}; - sui.cb = sizeof(sui); - sui.lpDesktop = desktop.empty() ? nullptr : desktopV.data(); - - if (shouldSpecifyHideFlag()) { - sui.dwFlags |= STARTF_USESHOWWINDOW; - sui.wShowWindow = SW_HIDE; - } - PROCESS_INFORMATION pi = {}; - const BOOL success = - CreateProcessW(exePath.c_str(), - cmdlineV.data(), - nullptr, nullptr, - /*bInheritHandles=*/FALSE, - /*dwCreationFlags=*/creationFlags, - nullptr, nullptr, - &sui, &pi); - if (!success) { - const DWORD lastError = GetLastError(); - const auto errStr = - (WStringBuilder(256) - << L"winpty-agent CreateProcess failed: cmdline='" << cmdline - << L"' err=0x" << whexOfInt(lastError)).str_moved(); - throw LibWinptyException( - WINPTY_ERROR_AGENT_CREATION_FAILED, errStr.c_str()); - } - CloseHandle(pi.hThread); - TRACE("Created agent successfully, pid=%u, cmdline=%s", - static_cast(pi.dwProcessId), - utf8FromWide(cmdline).c_str()); - agentPid = pi.dwProcessId; - return OwnedHandle(pi.hProcess); -} - -static void verifyPipeClientPid(HANDLE serverPipe, DWORD agentPid) { - const auto client = getNamedPipeClientProcessId(serverPipe); - const auto success = std::get<0>(client); - const auto lastError = std::get<2>(client); - if (success == GetNamedPipeClientProcessId_Result::Success) { - const auto clientPid = std::get<1>(client); - if (clientPid != agentPid) { - WStringBuilder errMsg; - errMsg << L"Security check failed: pipe client pid (" << clientPid - << L") does not match agent pid (" << agentPid << L")"; - throwWinptyException(errMsg.c_str()); - } - } else if (success == GetNamedPipeClientProcessId_Result::UnsupportedOs) { - trace("Pipe client PID security check skipped: " - "GetNamedPipeClientProcessId unsupported on this OS version"); - } else { - throwWindowsError(L"GetNamedPipeClientProcessId failed", lastError); - } -} - -static std::unique_ptr -createAgentSession(const winpty_config_t *cfg, - const std::wstring &desktop, - const std::wstring ¶ms, - DWORD creationFlags) { - std::unique_ptr wp(new winpty_t); - wp->agentTimeoutMs = cfg->timeoutMs; - wp->ioEvent = createEvent(); - - // Create control server pipe. - const auto pipeName = - L"\\\\.\\pipe\\winpty-control-" + GenRandom().uniqueName(); - wp->controlPipe = createControlPipe(pipeName); - - DWORD agentPid = 0; - wp->agentProcess = startAgentProcess( - desktop, pipeName, params, creationFlags, agentPid); - connectControlPipe(*wp.get()); - verifyPipeClientPid(wp->controlPipe.get(), agentPid); - - return std::move(wp); -} - -namespace { - -class AgentDesktop { -public: - virtual std::wstring name() = 0; - virtual ~AgentDesktop() {} -}; - -class AgentDesktopDirect : public AgentDesktop { -public: - AgentDesktopDirect(BackgroundDesktop &&desktop) : - m_desktop(std::move(desktop)) - { - } - std::wstring name() override { return m_desktop.desktopName(); } -private: - BackgroundDesktop m_desktop; -}; - -class AgentDesktopIndirect : public AgentDesktop { -public: - AgentDesktopIndirect(std::unique_ptr &&wp, - std::wstring &&desktopName) : - m_wp(std::move(wp)), - m_desktopName(std::move(desktopName)) - { - } - std::wstring name() override { return m_desktopName; } -private: - std::unique_ptr m_wp; - std::wstring m_desktopName; -}; - -} // anonymous namespace - -std::unique_ptr -setupBackgroundDesktop(const winpty_config_t *cfg) { - bool useDesktopAgent = - !(cfg->flags & WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION); - const bool useDesktop = shouldCreateBackgroundDesktop(useDesktopAgent); - - if (!useDesktop) { - return std::unique_ptr(); - } - - if (useDesktopAgent) { - auto wp = createAgentSession( - cfg, std::wstring(), L"--create-desktop", DETACHED_PROCESS); - - // Read the desktop name. - auto packet = readPacket(*wp.get()); - auto desktopName = packet.getWString(); - packet.assertEof(); - - if (desktopName.empty()) { - return std::unique_ptr(); - } else { - return std::unique_ptr( - new AgentDesktopIndirect(std::move(wp), - std::move(desktopName))); - } - } else { - try { - BackgroundDesktop desktop; - return std::unique_ptr(new AgentDesktopDirect( - std::move(desktop))); - } catch (const WinptyException &e) { - trace("Error: failed to create background desktop, " - "using original desktop instead: %s", - utf8FromWide(e.what()).c_str()); - return std::unique_ptr(); - } - } -} - -WINPTY_API winpty_t * -winpty_open(const winpty_config_t *cfg, - winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT(cfg != nullptr); - dumpWindowsVersion(); - dumpVersionToTrace(); - - // Setup a background desktop for the agent. - auto desktop = setupBackgroundDesktop(cfg); - const auto desktopName = desktop ? desktop->name() : std::wstring(); - - // Start the primary agent session. - const auto params = - (WStringBuilder(128) - << cfg->flags << L' ' - << cfg->mouseMode << L' ' - << cfg->cols << L' ' - << cfg->rows).str_moved(); - auto wp = createAgentSession(cfg, desktopName, params, - CREATE_NEW_CONSOLE); - - // Close handles to the background desktop and restore the original - // window station. This must wait until we know the agent is running - // -- if we close these handles too soon, then the desktop and - // windowstation will be destroyed before the agent can connect with - // them. - // - // If we used a separate agent process to create the desktop, we - // disconnect from that process here, allowing it to exit. - desktop.reset(); - - // If we ran the agent process on a background desktop, then when we - // spawn a child process from the agent, it will need to be explicitly - // placed back onto the original desktop. - if (!desktopName.empty()) { - wp->spawnDesktopName = getCurrentDesktopName(); - } - - // Get the CONIN/CONOUT pipe names. - auto packet = readPacket(*wp.get()); - wp->coninPipeName = packet.getWString(); - wp->conoutPipeName = packet.getWString(); - if (cfg->flags & WINPTY_FLAG_CONERR) { - wp->conerrPipeName = packet.getWString(); - } - packet.assertEof(); - - return wp.release(); - } API_CATCH(nullptr) -} - -WINPTY_API HANDLE winpty_agent_process(winpty_t *wp) { - ASSERT(wp != nullptr); - return wp->agentProcess.get(); -} - - - -/***************************************************************************** - * I/O pipes. */ - -static const wchar_t *cstrFromWStringOrNull(const std::wstring &str) { - try { - return str.c_str(); - } catch (const std::bad_alloc&) { - return nullptr; - } -} - -WINPTY_API LPCWSTR winpty_conin_name(winpty_t *wp) { - ASSERT(wp != nullptr); - return cstrFromWStringOrNull(wp->coninPipeName); -} - -WINPTY_API LPCWSTR winpty_conout_name(winpty_t *wp) { - ASSERT(wp != nullptr); - return cstrFromWStringOrNull(wp->conoutPipeName); -} - -WINPTY_API LPCWSTR winpty_conerr_name(winpty_t *wp) { - ASSERT(wp != nullptr); - if (wp->conerrPipeName.empty()) { - return nullptr; - } else { - return cstrFromWStringOrNull(wp->conerrPipeName); - } -} - - - -/***************************************************************************** - * winpty agent RPC calls. */ - -namespace { - -// Close the control pipe if something goes wrong with the pipe communication, -// which could leave the control pipe in an inconsistent state. -class RpcOperation { -public: - RpcOperation(winpty_t &wp) : m_wp(wp) { - if (m_wp.controlPipe.get() == nullptr) { - throwWinptyException(L"Agent shutdown due to RPC failure"); - } - } - ~RpcOperation() { - if (!m_success) { - trace("~RpcOperation: Closing control pipe"); - m_wp.controlPipe.dispose(true); - } - } - void success() { m_success = true; } -private: - winpty_t &m_wp; - bool m_success = false; -}; - -} // anonymous namespace - - - -/***************************************************************************** - * winpty agent RPC call: process creation. */ - -// Return a std::wstring containing every character of the environment block. -// Typically, the block is non-empty, so the std::wstring returned ends with -// two NUL terminators. (These two terminators are counted in size(), so -// calling c_str() produces a triply-terminated string.) -static std::wstring wstringFromEnvBlock(const wchar_t *env) { - std::wstring envStr; - if (env != NULL) { - const wchar_t *p = env; - while (*p != L'\0') { - p += wcslen(p) + 1; - } - p++; - envStr.assign(env, p); - - // Assuming the environment was non-empty, envStr now ends with two NUL - // terminators. - // - // If the environment were empty, though, then envStr would only be - // singly terminated, but the MSDN documentation thinks an env block is - // always doubly-terminated, so add an extra NUL just in case it - // matters. - const auto envStrSz = envStr.size(); - if (envStrSz == 1) { - ASSERT(envStr[0] == L'\0'); - envStr.push_back(L'\0'); - } else { - ASSERT(envStrSz >= 3); - ASSERT(envStr[envStrSz - 3] != L'\0'); - ASSERT(envStr[envStrSz - 2] == L'\0'); - ASSERT(envStr[envStrSz - 1] == L'\0'); - } - } - return envStr; -} - -WINPTY_API winpty_spawn_config_t * -winpty_spawn_config_new(UINT64 winptyFlags, - LPCWSTR appname /*OPTIONAL*/, - LPCWSTR cmdline /*OPTIONAL*/, - LPCWSTR cwd /*OPTIONAL*/, - LPCWSTR env /*OPTIONAL*/, - winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT((winptyFlags & WINPTY_SPAWN_FLAG_MASK) == winptyFlags); - std::unique_ptr cfg(new winpty_spawn_config_t); - cfg->winptyFlags = winptyFlags; - if (appname != nullptr) { cfg->appname = appname; } - if (cmdline != nullptr) { cfg->cmdline = cmdline; } - if (cwd != nullptr) { cfg->cwd = cwd; } - if (env != nullptr) { cfg->env = wstringFromEnvBlock(env); } - return cfg.release(); - } API_CATCH(nullptr) -} - -WINPTY_API void winpty_spawn_config_free(winpty_spawn_config_t *cfg) { - delete cfg; -} - -// It's safe to truncate a handle from 64-bits to 32-bits, or to sign-extend it -// back to 64-bits. See the MSDN article, "Interprocess Communication Between -// 32-bit and 64-bit Applications". -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203.aspx -static inline HANDLE handleFromInt64(int64_t i) { - return reinterpret_cast(static_cast(i)); -} - -// Given a process and a handle in that process, duplicate the handle into the -// current process and close it in the originating process. -static inline OwnedHandle stealHandle(HANDLE process, HANDLE handle) { - HANDLE result = nullptr; - if (!DuplicateHandle(process, handle, - GetCurrentProcess(), - &result, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - throwWindowsError(L"DuplicateHandle of process handle"); - } - return OwnedHandle(result); -} - -WINPTY_API BOOL -winpty_spawn(winpty_t *wp, - const winpty_spawn_config_t *cfg, - HANDLE *process_handle /*OPTIONAL*/, - HANDLE *thread_handle /*OPTIONAL*/, - DWORD *create_process_error /*OPTIONAL*/, - winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT(wp != nullptr && cfg != nullptr); - - if (process_handle != nullptr) { *process_handle = nullptr; } - if (thread_handle != nullptr) { *thread_handle = nullptr; } - if (create_process_error != nullptr) { *create_process_error = 0; } - - LockGuard lock(wp->mutex); - RpcOperation rpc(*wp); - - // Send spawn request. - auto packet = newPacket(); - packet.putInt32(AgentMsg::StartProcess); - packet.putInt64(cfg->winptyFlags); - packet.putInt32(process_handle != nullptr); - packet.putInt32(thread_handle != nullptr); - packet.putWString(cfg->appname); - packet.putWString(cfg->cmdline); - packet.putWString(cfg->cwd); - packet.putWString(cfg->env); - packet.putWString(wp->spawnDesktopName); - writePacket(*wp, packet); - - // Receive reply. - auto reply = readPacket(*wp); - const auto result = static_cast(reply.getInt32()); - if (result == StartProcessResult::CreateProcessFailed) { - const DWORD lastError = reply.getInt32(); - reply.assertEof(); - if (create_process_error != nullptr) { - *create_process_error = lastError; - } - rpc.success(); - throw LibWinptyException(WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED, - L"CreateProcess failed"); - } else if (result == StartProcessResult::ProcessCreated) { - const HANDLE remoteProcess = handleFromInt64(reply.getInt64()); - const HANDLE remoteThread = handleFromInt64(reply.getInt64()); - reply.assertEof(); - OwnedHandle localProcess; - OwnedHandle localThread; - if (remoteProcess != nullptr) { - localProcess = - stealHandle(wp->agentProcess.get(), remoteProcess); - } - if (remoteThread != nullptr) { - localThread = - stealHandle(wp->agentProcess.get(), remoteThread); - } - if (process_handle != nullptr) { - *process_handle = localProcess.release(); - } - if (thread_handle != nullptr) { - *thread_handle = localThread.release(); - } - rpc.success(); - } else { - throwWinptyException( - L"Agent RPC error: invalid StartProcessResult"); - } - return TRUE; - } API_CATCH(FALSE) -} - - - -/***************************************************************************** - * winpty agent RPC calls: everything else */ - -WINPTY_API BOOL -winpty_set_size(winpty_t *wp, int cols, int rows, - winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT(wp != nullptr && cols > 0 && rows > 0); - LockGuard lock(wp->mutex); - RpcOperation rpc(*wp); - auto packet = newPacket(); - packet.putInt32(AgentMsg::SetSize); - packet.putInt32(cols); - packet.putInt32(rows); - writePacket(*wp, packet); - readPacket(*wp).assertEof(); - rpc.success(); - return TRUE; - } API_CATCH(FALSE) -} - -WINPTY_API int -winpty_get_console_process_list(winpty_t *wp, int *processList, const int processCount, - winpty_error_ptr_t *err /*OPTIONAL*/) { - API_TRY { - ASSERT(wp != nullptr); - ASSERT(processList != nullptr); - LockGuard lock(wp->mutex); - RpcOperation rpc(*wp); - auto packet = newPacket(); - packet.putInt32(AgentMsg::GetConsoleProcessList); - writePacket(*wp, packet); - auto reply = readPacket(*wp); - - auto actualProcessCount = reply.getInt32(); - - if (actualProcessCount <= processCount) { - for (auto i = 0; i < actualProcessCount; i++) { - processList[i] = reply.getInt32(); - } - } - - reply.assertEof(); - rpc.success(); - return actualProcessCount; - } API_CATCH(0) -} - -WINPTY_API void winpty_free(winpty_t *wp) { - // At least in principle, CloseHandle can fail, so this deletion can - // fail. It won't throw an exception, but maybe there's an error that - // should be propagated? - delete wp; -} diff --git a/deps/winpty/src/shared/AgentMsg.h b/deps/winpty/src/shared/AgentMsg.h deleted file mode 100644 index ab60c6b96..000000000 --- a/deps/winpty/src/shared/AgentMsg.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_AGENT_MSG_H -#define WINPTY_SHARED_AGENT_MSG_H - -struct AgentMsg -{ - enum Type { - StartProcess, - SetSize, - GetConsoleProcessList, - }; -}; - -enum class StartProcessResult { - CreateProcessFailed, - ProcessCreated, -}; - -#endif // WINPTY_SHARED_AGENT_MSG_H diff --git a/deps/winpty/src/shared/BackgroundDesktop.cc b/deps/winpty/src/shared/BackgroundDesktop.cc deleted file mode 100644 index 1bea7e53d..000000000 --- a/deps/winpty/src/shared/BackgroundDesktop.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "BackgroundDesktop.h" - -#include - -#include "DebugClient.h" -#include "StringUtil.h" -#include "WinptyException.h" - -namespace { - -static std::wstring getObjectName(HANDLE object) { - BOOL success; - DWORD lengthNeeded = 0; - GetUserObjectInformationW(object, UOI_NAME, - nullptr, 0, - &lengthNeeded); - ASSERT(lengthNeeded % sizeof(wchar_t) == 0); - std::unique_ptr tmp( - new wchar_t[lengthNeeded / sizeof(wchar_t)]); - success = GetUserObjectInformationW(object, UOI_NAME, - tmp.get(), lengthNeeded, - nullptr); - if (!success) { - throwWindowsError(L"GetUserObjectInformationW failed"); - } - return std::wstring(tmp.get()); -} - -static std::wstring getDesktopName(HWINSTA winsta, HDESK desk) { - return getObjectName(winsta) + L"\\" + getObjectName(desk); -} - -} // anonymous namespace - -// Get a non-interactive window station for the agent. -// TODO: review security w.r.t. windowstation and desktop. -BackgroundDesktop::BackgroundDesktop() { - try { - m_originalStation = GetProcessWindowStation(); - if (m_originalStation == nullptr) { - throwWindowsError( - L"BackgroundDesktop ctor: " - L"GetProcessWindowStation returned NULL"); - } - m_newStation = - CreateWindowStationW(nullptr, 0, WINSTA_ALL_ACCESS, nullptr); - if (m_newStation == nullptr) { - throwWindowsError( - L"BackgroundDesktop ctor: CreateWindowStationW returned NULL"); - } - if (!SetProcessWindowStation(m_newStation)) { - throwWindowsError( - L"BackgroundDesktop ctor: SetProcessWindowStation failed"); - } - m_newDesktop = CreateDesktopW( - L"Default", nullptr, nullptr, 0, GENERIC_ALL, nullptr); - if (m_newDesktop == nullptr) { - throwWindowsError( - L"BackgroundDesktop ctor: CreateDesktopW failed"); - } - m_newDesktopName = getDesktopName(m_newStation, m_newDesktop); - TRACE("Created background desktop: %s", - utf8FromWide(m_newDesktopName).c_str()); - } catch (...) { - dispose(); - throw; - } -} - -void BackgroundDesktop::dispose() WINPTY_NOEXCEPT { - if (m_originalStation != nullptr) { - SetProcessWindowStation(m_originalStation); - m_originalStation = nullptr; - } - if (m_newDesktop != nullptr) { - CloseDesktop(m_newDesktop); - m_newDesktop = nullptr; - } - if (m_newStation != nullptr) { - CloseWindowStation(m_newStation); - m_newStation = nullptr; - } -} - -std::wstring getCurrentDesktopName() { - // MSDN says that the handles returned by GetProcessWindowStation and - // GetThreadDesktop do not need to be passed to CloseWindowStation and - // CloseDesktop, respectively. - const HWINSTA winsta = GetProcessWindowStation(); - if (winsta == nullptr) { - throwWindowsError( - L"getCurrentDesktopName: " - L"GetProcessWindowStation returned NULL"); - } - const HDESK desk = GetThreadDesktop(GetCurrentThreadId()); - if (desk == nullptr) { - throwWindowsError( - L"getCurrentDesktopName: " - L"GetThreadDesktop returned NULL"); - } - return getDesktopName(winsta, desk); -} diff --git a/deps/winpty/src/shared/BackgroundDesktop.h b/deps/winpty/src/shared/BackgroundDesktop.h deleted file mode 100644 index c692e57dc..000000000 --- a/deps/winpty/src/shared/BackgroundDesktop.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_BACKGROUND_DESKTOP_H -#define WINPTY_SHARED_BACKGROUND_DESKTOP_H - -#include - -#include - -#include "WinptyException.h" - -class BackgroundDesktop { -public: - BackgroundDesktop(); - ~BackgroundDesktop() { dispose(); } - void dispose() WINPTY_NOEXCEPT; - const std::wstring &desktopName() const { return m_newDesktopName; } - - BackgroundDesktop(const BackgroundDesktop &other) = delete; - BackgroundDesktop &operator=(const BackgroundDesktop &other) = delete; - - // We can't default the move constructor and assignment operator with - // MSVC 2013. We *could* if we required at least MSVC 2015 to build. - - BackgroundDesktop(BackgroundDesktop &&other) : - m_originalStation(other.m_originalStation), - m_newStation(other.m_newStation), - m_newDesktop(other.m_newDesktop), - m_newDesktopName(std::move(other.m_newDesktopName)) { - other.m_originalStation = nullptr; - other.m_newStation = nullptr; - other.m_newDesktop = nullptr; - } - BackgroundDesktop &operator=(BackgroundDesktop &&other) { - dispose(); - m_originalStation = other.m_originalStation; - m_newStation = other.m_newStation; - m_newDesktop = other.m_newDesktop; - m_newDesktopName = std::move(other.m_newDesktopName); - other.m_originalStation = nullptr; - other.m_newStation = nullptr; - other.m_newDesktop = nullptr; - return *this; - } - -private: - HWINSTA m_originalStation = nullptr; - HWINSTA m_newStation = nullptr; - HDESK m_newDesktop = nullptr; - std::wstring m_newDesktopName; -}; - -std::wstring getCurrentDesktopName(); - -#endif // WINPTY_SHARED_BACKGROUND_DESKTOP_H diff --git a/deps/winpty/src/shared/Buffer.cc b/deps/winpty/src/shared/Buffer.cc deleted file mode 100644 index 158a629d5..000000000 --- a/deps/winpty/src/shared/Buffer.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Buffer.h" - -#include - -#include "DebugClient.h" -#include "WinptyAssert.h" - -// Define the READ_BUFFER_CHECK() macro. It *must* evaluate its condition, -// exactly once. -#define READ_BUFFER_CHECK(cond) \ - do { \ - if (!(cond)) { \ - trace("decode error: %s", #cond); \ - throw DecodeError(); \ - } \ - } while (false) - -enum class Piece : uint8_t { Int32, Int64, WString }; - -void WriteBuffer::putRawData(const void *data, size_t len) { - const auto p = reinterpret_cast(data); - m_buf.insert(m_buf.end(), p, p + len); -} - -void WriteBuffer::replaceRawData(size_t pos, const void *data, size_t len) { - ASSERT(pos <= m_buf.size() && len <= m_buf.size() - pos); - const auto p = reinterpret_cast(data); - std::copy(p, p + len, &m_buf[pos]); -} - -void WriteBuffer::putInt32(int32_t i) { - putRawValue(Piece::Int32); - putRawValue(i); -} - -void WriteBuffer::putInt64(int64_t i) { - putRawValue(Piece::Int64); - putRawValue(i); -} - -// len is in characters, excluding NUL, i.e. the number of wchar_t elements -void WriteBuffer::putWString(const wchar_t *str, size_t len) { - putRawValue(Piece::WString); - putRawValue(static_cast(len)); - putRawData(str, sizeof(wchar_t) * len); -} - -void ReadBuffer::getRawData(void *data, size_t len) { - ASSERT(m_off <= m_buf.size()); - READ_BUFFER_CHECK(len <= m_buf.size() - m_off); - const char *const inp = &m_buf[m_off]; - std::copy(inp, inp + len, reinterpret_cast(data)); - m_off += len; -} - -int32_t ReadBuffer::getInt32() { - READ_BUFFER_CHECK(getRawValue() == Piece::Int32); - return getRawValue(); -} - -int64_t ReadBuffer::getInt64() { - READ_BUFFER_CHECK(getRawValue() == Piece::Int64); - return getRawValue(); -} - -std::wstring ReadBuffer::getWString() { - READ_BUFFER_CHECK(getRawValue() == Piece::WString); - const uint64_t charLen = getRawValue(); - READ_BUFFER_CHECK(charLen <= SIZE_MAX / sizeof(wchar_t)); - // To be strictly conforming, we can't use the convenient wstring - // constructor, because the string in m_buf mightn't be aligned. - std::wstring ret; - if (charLen > 0) { - const size_t byteLen = charLen * sizeof(wchar_t); - ret.resize(charLen); - getRawData(&ret[0], byteLen); - } - return ret; -} - -void ReadBuffer::assertEof() { - READ_BUFFER_CHECK(m_off == m_buf.size()); -} diff --git a/deps/winpty/src/shared/Buffer.h b/deps/winpty/src/shared/Buffer.h deleted file mode 100644 index c2dd382e5..000000000 --- a/deps/winpty/src/shared/Buffer.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_BUFFER_H -#define WINPTY_SHARED_BUFFER_H - -#include -#include - -#include -#include -#include -#include - -#include "WinptyException.h" - -class WriteBuffer { -private: - std::vector m_buf; - -public: - WriteBuffer() {} - - template void putRawValue(const T &t) { - putRawData(&t, sizeof(t)); - } - template void replaceRawValue(size_t pos, const T &t) { - replaceRawData(pos, &t, sizeof(t)); - } - - void putRawData(const void *data, size_t len); - void replaceRawData(size_t pos, const void *data, size_t len); - void putInt32(int32_t i); - void putInt64(int64_t i); - void putWString(const wchar_t *str, size_t len); - void putWString(const wchar_t *str) { putWString(str, wcslen(str)); } - void putWString(const std::wstring &str) { putWString(str.data(), str.size()); } - std::vector &buf() { return m_buf; } - - // MSVC 2013 does not generate these automatically, so help it out. - WriteBuffer(WriteBuffer &&other) : m_buf(std::move(other.m_buf)) {} - WriteBuffer &operator=(WriteBuffer &&other) { - m_buf = std::move(other.m_buf); - return *this; - } -}; - -class ReadBuffer { -public: - class DecodeError : public WinptyException { - virtual const wchar_t *what() const WINPTY_NOEXCEPT override { - return L"DecodeError: RPC message decoding error"; - } - }; - -private: - std::vector m_buf; - size_t m_off = 0; - -public: - explicit ReadBuffer(std::vector &&buf) : m_buf(std::move(buf)) {} - - template T getRawValue() { - T ret = {}; - getRawData(&ret, sizeof(ret)); - return ret; - } - - void getRawData(void *data, size_t len); - int32_t getInt32(); - int64_t getInt64(); - std::wstring getWString(); - void assertEof(); - - // MSVC 2013 does not generate these automatically, so help it out. - ReadBuffer(ReadBuffer &&other) : - m_buf(std::move(other.m_buf)), m_off(other.m_off) {} - ReadBuffer &operator=(ReadBuffer &&other) { - m_buf = std::move(other.m_buf); - m_off = other.m_off; - return *this; - } -}; - -#endif // WINPTY_SHARED_BUFFER_H diff --git a/deps/winpty/src/shared/DebugClient.cc b/deps/winpty/src/shared/DebugClient.cc deleted file mode 100644 index bafe0c895..000000000 --- a/deps/winpty/src/shared/DebugClient.cc +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "DebugClient.h" - -#include -#include -#include -#include - -#include -#include - -#include "winpty_snprintf.h" - -const wchar_t *const kPipeName = L"\\\\.\\pipe\\DebugServer"; - -void *volatile g_debugConfig; - -namespace { - -// It would be easy to accidentally trample on the Windows LastError value -// by adding logging/debugging code. Ensure that can't happen by saving and -// restoring the value. This saving and restoring doesn't happen along the -// fast path. -class PreserveLastError { -public: - PreserveLastError() : m_lastError(GetLastError()) {} - ~PreserveLastError() { SetLastError(m_lastError); } -private: - DWORD m_lastError; -}; - -} // anonymous namespace - -static void sendToDebugServer(const char *message) -{ - HANDLE tracePipe = INVALID_HANDLE_VALUE; - - do { - // The default impersonation level is SECURITY_IMPERSONATION, which allows - // a sufficiently authorized named pipe server to impersonate the client. - // There's no need for impersonation in this debugging system, so reduce - // the impersonation level to SECURITY_IDENTIFICATION, which allows a - // server to merely identify us. - tracePipe = CreateFileW( - kPipeName, - GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, - SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, - NULL); - } while (tracePipe == INVALID_HANDLE_VALUE && - GetLastError() == ERROR_PIPE_BUSY && - WaitNamedPipeW(kPipeName, NMPWAIT_WAIT_FOREVER)); - - if (tracePipe != INVALID_HANDLE_VALUE) { - DWORD newMode = PIPE_READMODE_MESSAGE; - SetNamedPipeHandleState(tracePipe, &newMode, NULL, NULL); - char response[16]; - DWORD actual = 0; - TransactNamedPipe(tracePipe, - const_cast(message), strlen(message), - response, sizeof(response), &actual, NULL); - CloseHandle(tracePipe); - } -} - -// Get the current UTC time as milliseconds from the epoch (ignoring leap -// seconds). Use the Unix epoch for consistency with DebugClient.py. There -// are 134774 days between 1601-01-01 (the Win32 epoch) and 1970-01-01 (the -// Unix epoch). -static long long unixTimeMillis() -{ - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - long long msTime = (((long long)fileTime.dwHighDateTime << 32) + - fileTime.dwLowDateTime) / 10000; - return msTime - 134774LL * 24 * 3600 * 1000; -} - -static const char *getDebugConfig() -{ - if (g_debugConfig == NULL) { - PreserveLastError preserve; - const int bufSize = 256; - char buf[bufSize]; - DWORD actualSize = - GetEnvironmentVariableA("WINPTY_DEBUG", buf, bufSize); - if (actualSize == 0 || actualSize >= static_cast(bufSize)) { - buf[0] = '\0'; - } - const size_t len = strlen(buf) + 1; - char *newConfig = new char[len]; - std::copy(buf, buf + len, newConfig); - void *oldValue = InterlockedCompareExchangePointer( - &g_debugConfig, newConfig, NULL); - if (oldValue != NULL) { - delete [] newConfig; - } - } - return static_cast(g_debugConfig); -} - -bool isTracingEnabled() -{ - static bool disabled, enabled; - if (disabled) { - return false; - } else if (enabled) { - return true; - } else { - // Recognize WINPTY_DEBUG=1 for backwards compatibility. - PreserveLastError preserve; - bool value = hasDebugFlag("trace") || hasDebugFlag("1"); - disabled = !value; - enabled = value; - return value; - } -} - -bool hasDebugFlag(const char *flag) -{ - if (strchr(flag, ',') != NULL) { - trace("INTERNAL ERROR: hasDebugFlag flag has comma: '%s'", flag); - abort(); - } - const char *const configCStr = getDebugConfig(); - if (configCStr[0] == '\0') { - return false; - } - PreserveLastError preserve; - std::string config(configCStr); - std::string flagStr(flag); - config = "," + config + ","; - flagStr = "," + flagStr + ","; - return config.find(flagStr) != std::string::npos; -} - -void trace(const char *format, ...) -{ - if (!isTracingEnabled()) - return; - - PreserveLastError preserve; - char message[1024]; - - va_list ap; - va_start(ap, format); - winpty_vsnprintf(message, format, ap); - message[sizeof(message) - 1] = '\0'; - va_end(ap); - - const int currentTime = (int)(unixTimeMillis() % (100000 * 1000)); - - char moduleName[1024]; - moduleName[0] = '\0'; - GetModuleFileNameA(NULL, moduleName, sizeof(moduleName)); - const char *baseName = strrchr(moduleName, '\\'); - baseName = (baseName != NULL) ? baseName + 1 : moduleName; - - char fullMessage[1024]; - winpty_snprintf(fullMessage, - "[%05d.%03d %s,p%04d,t%04d]: %s", - currentTime / 1000, currentTime % 1000, - baseName, (int)GetCurrentProcessId(), (int)GetCurrentThreadId(), - message); - fullMessage[sizeof(fullMessage) - 1] = '\0'; - - sendToDebugServer(fullMessage); -} diff --git a/deps/winpty/src/shared/DebugClient.h b/deps/winpty/src/shared/DebugClient.h deleted file mode 100644 index b12607113..000000000 --- a/deps/winpty/src/shared/DebugClient.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011-2012 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef DEBUGCLIENT_H -#define DEBUGCLIENT_H - -#include "winpty_snprintf.h" - -bool isTracingEnabled(); -bool hasDebugFlag(const char *flag); -void trace(const char *format, ...) WINPTY_SNPRINTF_FORMAT(1, 2); - -// This macro calls trace without evaluating the arguments. -#define TRACE(format, ...) \ - do { \ - if (isTracingEnabled()) { \ - trace((format), ## __VA_ARGS__); \ - } \ - } while (false) - -#endif // DEBUGCLIENT_H diff --git a/deps/winpty/src/shared/GenRandom.cc b/deps/winpty/src/shared/GenRandom.cc deleted file mode 100644 index 6d7920643..000000000 --- a/deps/winpty/src/shared/GenRandom.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "GenRandom.h" - -#include -#include - -#include "DebugClient.h" -#include "StringBuilder.h" - -static volatile LONG g_pipeCounter; - -GenRandom::GenRandom() : m_advapi32(L"advapi32.dll") { - // First try to use the pseudo-documented RtlGenRandom function from - // advapi32.dll. Creating a CryptoAPI context is slow, and RtlGenRandom - // avoids the overhead. It's documented in this blog post[1] and on - // MSDN[2] with a disclaimer about future breakage. This technique is - // apparently built-in into the MSVC CRT, though, for the rand_s function, - // so perhaps it is stable enough. - // - // [1] http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx - // [2] https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx - // - // Both RtlGenRandom and the Crypto API functions exist in XP and up. - m_rtlGenRandom = reinterpret_cast( - m_advapi32.proc("SystemFunction036")); - // The OsModule class logs an error message if the proc is nullptr. - if (m_rtlGenRandom != nullptr) { - return; - } - - // Fall back to the crypto API. - m_cryptProvIsValid = - CryptAcquireContext(&m_cryptProv, nullptr, nullptr, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) != 0; - if (!m_cryptProvIsValid) { - trace("GenRandom: CryptAcquireContext failed: %u", - static_cast(GetLastError())); - } -} - -GenRandom::~GenRandom() { - if (m_cryptProvIsValid) { - CryptReleaseContext(m_cryptProv, 0); - } -} - -// Returns false if the context is invalid or the generation fails. -bool GenRandom::fillBuffer(void *buffer, size_t size) { - memset(buffer, 0, size); - bool success = false; - if (m_rtlGenRandom != nullptr) { - success = m_rtlGenRandom(buffer, size) != 0; - if (!success) { - trace("GenRandom: RtlGenRandom/SystemFunction036 failed: %u", - static_cast(GetLastError())); - } - } else if (m_cryptProvIsValid) { - success = - CryptGenRandom(m_cryptProv, size, - reinterpret_cast(buffer)) != 0; - if (!success) { - trace("GenRandom: CryptGenRandom failed, size=%d, lasterror=%u", - static_cast(size), - static_cast(GetLastError())); - } - } - return success; -} - -// Returns an empty string if either of CryptAcquireContext or CryptGenRandom -// fail. -std::string GenRandom::randomBytes(size_t numBytes) { - std::string ret(numBytes, '\0'); - if (!fillBuffer(&ret[0], numBytes)) { - return std::string(); - } - return ret; -} - -std::wstring GenRandom::randomHexString(size_t numBytes) { - const std::string bytes = randomBytes(numBytes); - std::wstring ret(bytes.size() * 2, L'\0'); - for (size_t i = 0; i < bytes.size(); ++i) { - static const wchar_t hex[] = L"0123456789abcdef"; - ret[i * 2] = hex[static_cast(bytes[i]) >> 4]; - ret[i * 2 + 1] = hex[static_cast(bytes[i]) & 0xF]; - } - return ret; -} - -// Returns a 64-bit value representing the number of 100-nanosecond intervals -// since January 1, 1601. -static uint64_t systemTimeAsUInt64() { - FILETIME monotonicTime = {}; - GetSystemTimeAsFileTime(&monotonicTime); - return (static_cast(monotonicTime.dwHighDateTime) << 32) | - static_cast(monotonicTime.dwLowDateTime); -} - -// Generates a unique and hard-to-guess case-insensitive string suitable for -// use in a pipe filename or a Windows object name. -std::wstring GenRandom::uniqueName() { - // First include enough information to avoid collisions assuming - // cooperative software. This code assumes that a process won't die and - // be replaced with a recycled PID within a single GetSystemTimeAsFileTime - // interval. - WStringBuilder sb(64); - sb << GetCurrentProcessId() - << L'-' << InterlockedIncrement(&g_pipeCounter) - << L'-' << whexOfInt(systemTimeAsUInt64()); - // It isn't clear to me how the crypto APIs would fail. It *probably* - // doesn't matter that much anyway? In principle, a predictable pipe name - // is subject to a local denial-of-service attack. - auto random = randomHexString(16); - if (!random.empty()) { - sb << L'-' << random; - } - return sb.str_moved(); -} diff --git a/deps/winpty/src/shared/GenRandom.h b/deps/winpty/src/shared/GenRandom.h deleted file mode 100644 index 746cb1ecf..000000000 --- a/deps/winpty/src/shared/GenRandom.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_GEN_RANDOM_H -#define WINPTY_GEN_RANDOM_H - -// The original MinGW requires that we include wincrypt.h. With MinGW-w64 and -// MSVC, including windows.h is sufficient. -#include -#include - -#include - -#include "OsModule.h" - -class GenRandom { - typedef BOOLEAN WINAPI RtlGenRandom_t(PVOID, ULONG); - - OsModule m_advapi32; - RtlGenRandom_t *m_rtlGenRandom = nullptr; - bool m_cryptProvIsValid = false; - HCRYPTPROV m_cryptProv = 0; - -public: - GenRandom(); - ~GenRandom(); - bool fillBuffer(void *buffer, size_t size); - std::string randomBytes(size_t numBytes); - std::wstring randomHexString(size_t numBytes); - std::wstring uniqueName(); - - // Return true if the crypto context was successfully initialized. - bool valid() const { - return m_rtlGenRandom != nullptr || m_cryptProvIsValid; - } -}; - -#endif // WINPTY_GEN_RANDOM_H diff --git a/deps/winpty/src/shared/GetCommitHash.bat b/deps/winpty/src/shared/GetCommitHash.bat deleted file mode 100644 index a9f8e9cef..000000000 --- a/deps/winpty/src/shared/GetCommitHash.bat +++ /dev/null @@ -1,13 +0,0 @@ -@echo off - -REM -- Echo the git commit hash. If git isn't available for some reason, -REM -- output nothing instead. - -git rev-parse HEAD >NUL 2>NUL && ( - git rev-parse HEAD -) || ( - echo none -) - -REM -- Set ERRORLEVEL to 0 using this cryptic syntax. -(call ) diff --git a/deps/winpty/src/shared/Mutex.h b/deps/winpty/src/shared/Mutex.h deleted file mode 100644 index 98215365a..000000000 --- a/deps/winpty/src/shared/Mutex.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// Recent 4.x MinGW and MinGW-w64 gcc compilers lack std::mutex and -// std::lock_guard. I have a 5.2.0 MinGW-w64 compiler packaged through MSYS2 -// that *is* new enough, but that's one compiler against several deficient -// ones. Wrap CRITICAL_SECTION instead. - -#ifndef WINPTY_SHARED_MUTEX_H -#define WINPTY_SHARED_MUTEX_H - -#include - -class Mutex { - CRITICAL_SECTION m_mutex; -public: - Mutex() { InitializeCriticalSection(&m_mutex); } - ~Mutex() { DeleteCriticalSection(&m_mutex); } - void lock() { EnterCriticalSection(&m_mutex); } - void unlock() { LeaveCriticalSection(&m_mutex); } - - Mutex(const Mutex &other) = delete; - Mutex &operator=(const Mutex &other) = delete; -}; - -template -class LockGuard { - T &m_lock; -public: - LockGuard(T &lock) : m_lock(lock) { m_lock.lock(); } - ~LockGuard() { m_lock.unlock(); } - - LockGuard(const LockGuard &other) = delete; - LockGuard &operator=(const LockGuard &other) = delete; -}; - -#endif // WINPTY_SHARED_MUTEX_H diff --git a/deps/winpty/src/shared/OsModule.h b/deps/winpty/src/shared/OsModule.h deleted file mode 100644 index 9713fa2b2..000000000 --- a/deps/winpty/src/shared/OsModule.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_OS_MODULE_H -#define WINPTY_SHARED_OS_MODULE_H - -#include - -#include - -#include "DebugClient.h" -#include "WinptyAssert.h" -#include "WinptyException.h" - -class OsModule { - HMODULE m_module; -public: - enum class LoadErrorBehavior { Abort, Throw }; - OsModule(const wchar_t *fileName, - LoadErrorBehavior behavior=LoadErrorBehavior::Abort) { - m_module = LoadLibraryW(fileName); - if (behavior == LoadErrorBehavior::Abort) { - ASSERT(m_module != NULL); - } else { - if (m_module == nullptr) { - const auto err = GetLastError(); - throwWindowsError( - (L"LoadLibraryW error: " + std::wstring(fileName)).c_str(), - err); - } - } - } - ~OsModule() { - FreeLibrary(m_module); - } - HMODULE handle() const { return m_module; } - FARPROC proc(const char *funcName) { - FARPROC ret = GetProcAddress(m_module, funcName); - if (ret == NULL) { - trace("GetProcAddress: %s is missing", funcName); - } - return ret; - } -}; - -#endif // WINPTY_SHARED_OS_MODULE_H diff --git a/deps/winpty/src/shared/OwnedHandle.cc b/deps/winpty/src/shared/OwnedHandle.cc deleted file mode 100644 index 7b173536e..000000000 --- a/deps/winpty/src/shared/OwnedHandle.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "OwnedHandle.h" - -#include "DebugClient.h" -#include "WinptyException.h" - -void OwnedHandle::dispose(bool nothrow) { - if (m_h != nullptr && m_h != INVALID_HANDLE_VALUE) { - if (!CloseHandle(m_h)) { - trace("CloseHandle(%p) failed", m_h); - if (!nothrow) { - throwWindowsError(L"CloseHandle failed"); - } - } - } - m_h = nullptr; -} diff --git a/deps/winpty/src/shared/OwnedHandle.h b/deps/winpty/src/shared/OwnedHandle.h deleted file mode 100644 index 70a8d6163..000000000 --- a/deps/winpty/src/shared/OwnedHandle.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_OWNED_HANDLE_H -#define WINPTY_SHARED_OWNED_HANDLE_H - -#include - -class OwnedHandle { - HANDLE m_h; -public: - OwnedHandle() : m_h(nullptr) {} - explicit OwnedHandle(HANDLE h) : m_h(h) {} - ~OwnedHandle() { dispose(true); } - void dispose(bool nothrow=false); - HANDLE get() const { return m_h; } - HANDLE release() { HANDLE ret = m_h; m_h = nullptr; return ret; } - OwnedHandle(const OwnedHandle &other) = delete; - OwnedHandle(OwnedHandle &&other) : m_h(other.release()) {} - OwnedHandle &operator=(const OwnedHandle &other) = delete; - OwnedHandle &operator=(OwnedHandle &&other) { - dispose(); - m_h = other.release(); - return *this; - } -}; - -#endif // WINPTY_SHARED_OWNED_HANDLE_H diff --git a/deps/winpty/src/shared/PrecompiledHeader.h b/deps/winpty/src/shared/PrecompiledHeader.h deleted file mode 100644 index 7d9b8f8b4..000000000 --- a/deps/winpty/src/shared/PrecompiledHeader.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_PRECOMPILED_HEADER_H -#define WINPTY_PRECOMPILED_HEADER_H - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // WINPTY_PRECOMPILED_HEADER_H diff --git a/deps/winpty/src/shared/StringBuilder.h b/deps/winpty/src/shared/StringBuilder.h deleted file mode 100644 index f3155bdd2..000000000 --- a/deps/winpty/src/shared/StringBuilder.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// Efficient integer->string conversion and string concatenation. The -// hexadecimal conversion may optionally have leading zeros. Other ways to -// convert integers to strings in C++ suffer these drawbacks: -// -// * std::stringstream: Inefficient, even more so than stdio. -// -// * std::to_string: No hexadecimal output, tends to use heap allocation, not -// supported on Cygwin. -// -// * stdio routines: Requires parsing a format string (inefficient). The -// caller *must* know how large the content is for correctness. The -// string-printf functions are extremely inconsistent on Windows. In -// particular, 64-bit integers, wide strings, and return values are -// problem areas. -// -// StringBuilderTest.cc is a standalone program that tests this header. - -#ifndef WINPTY_STRING_BUILDER_H -#define WINPTY_STRING_BUILDER_H - -#include -#include -#include - -#ifdef STRING_BUILDER_TESTING -#include -#define STRING_BUILDER_CHECK(cond) assert(cond) -#else -#define STRING_BUILDER_CHECK(cond) -#endif // STRING_BUILDER_TESTING - -#include "WinptyAssert.h" - -template -struct ValueString { - std::array m_array; - size_t m_offset; - size_t m_size; - - const C *c_str() const { return m_array.data() + m_offset; } - const C *data() const { return m_array.data() + m_offset; } - size_t size() const { return m_size; } - std::basic_string str() const { - return std::basic_string(data(), m_size); - } -}; - -#ifdef _MSC_VER -// Disable an MSVC /SDL error that forbids unsigned negation. Signed negation -// invokes undefined behavior for INTxx_MIN, so unsigned negation is simpler to -// reason about. (We assume twos-complement in any case.) -#define STRING_BUILDER_ALLOW_UNSIGNED_NEGATE(x) \ - ( \ - __pragma(warning(push)) \ - __pragma(warning(disable:4146)) \ - (x) \ - __pragma(warning(pop)) \ - ) -#else -#define STRING_BUILDER_ALLOW_UNSIGNED_NEGATE(x) (x) -#endif - -// Formats an integer as decimal without leading zeros. -template -ValueString gdecOfInt(const I value) { - typedef typename std::make_unsigned::type U; - auto unsValue = static_cast(value); - const bool isNegative = (value < 0); - if (isNegative) { - unsValue = STRING_BUILDER_ALLOW_UNSIGNED_NEGATE(-unsValue); - } - decltype(gdecOfInt(value)) out; - auto &arr = out.m_array; - C *const endp = arr.data() + arr.size(); - C *outp = endp; - *(--outp) = '\0'; - STRING_BUILDER_CHECK(outp >= arr.data()); - do { - const int digit = unsValue % 10; - unsValue /= 10; - *(--outp) = '0' + digit; - STRING_BUILDER_CHECK(outp >= arr.data()); - } while (unsValue != 0); - if (isNegative) { - *(--outp) = '-'; - STRING_BUILDER_CHECK(outp >= arr.data()); - } - out.m_offset = outp - arr.data(); - out.m_size = endp - outp - 1; - return out; -} - -template decltype(gdecOfInt(0)) decOfInt(I i) { - return gdecOfInt(i); -} - -template decltype(gdecOfInt(0)) wdecOfInt(I i) { - return gdecOfInt(i); -} - -// Formats an integer as hexadecimal, with or without leading zeros. -template -ValueString ghexOfInt(const I value) { - typedef typename std::make_unsigned::type U; - const auto unsValue = static_cast(value); - static const C hex[16] = {'0','1','2','3','4','5','6','7', - '8','9','a','b','c','d','e','f'}; - decltype(ghexOfInt(value)) out; - auto &arr = out.m_array; - C *outp = arr.data(); - int inIndex = 0; - int shift = sizeof(I) * 8 - 4; - const int len = sizeof(I) * 2; - if (!leadingZeros) { - for (; inIndex < len - 1; ++inIndex, shift -= 4) { - STRING_BUILDER_CHECK(shift >= 0 && shift < sizeof(unsValue) * 8); - const int digit = (unsValue >> shift) & 0xF; - if (digit != 0) { - break; - } - } - } - for (; inIndex < len; ++inIndex, shift -= 4) { - const int digit = (unsValue >> shift) & 0xF; - *(outp++) = hex[digit]; - STRING_BUILDER_CHECK(outp <= arr.data() + arr.size()); - } - *(outp++) = '\0'; - STRING_BUILDER_CHECK(outp <= arr.data() + arr.size()); - out.m_offset = 0; - out.m_size = outp - arr.data() - 1; - return out; -} - -template -decltype(ghexOfInt(0)) hexOfInt(I i) { - return ghexOfInt(i); -} - -template -decltype(ghexOfInt(0)) whexOfInt(I i) { - return ghexOfInt(i); -} - -template -class GStringBuilder { -public: - typedef std::basic_string StringType; - - GStringBuilder() {} - GStringBuilder(size_t capacity) { - m_out.reserve(capacity); - } - - GStringBuilder &operator<<(C ch) { m_out.push_back(ch); return *this; } - GStringBuilder &operator<<(const C *str) { m_out.append(str); return *this; } - GStringBuilder &operator<<(const StringType &str) { m_out.append(str); return *this; } - - template - GStringBuilder &operator<<(const ValueString &str) { - m_out.append(str.data(), str.size()); - return *this; - } - -private: - // Forbid output of char/wchar_t for GStringBuilder if the type doesn't - // exactly match the builder element type. The code still allows - // signed char and unsigned char, but I'm a little worried about what - // happens if a user tries to output int8_t or uint8_t. - template - typename std::enable_if< - (std::is_same::value || std::is_same::value) && - !std::is_same::value, GStringBuilder&>::type - operator<<(P ch) { - ASSERT(false && "Method was not supposed to be reachable."); - return *this; - } - -public: - GStringBuilder &operator<<(short i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(unsigned short i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(int i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(unsigned int i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(long i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(unsigned long i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(long long i) { return *this << gdecOfInt(i); } - GStringBuilder &operator<<(unsigned long long i) { return *this << gdecOfInt(i); } - - GStringBuilder &operator<<(const void *p) { - m_out.push_back(static_cast('0')); - m_out.push_back(static_cast('x')); - *this << ghexOfInt(reinterpret_cast(p)); - return *this; - } - - StringType str() { return m_out; } - StringType str_moved() { return std::move(m_out); } - const C *c_str() const { return m_out.c_str(); } - -private: - StringType m_out; -}; - -typedef GStringBuilder StringBuilder; -typedef GStringBuilder WStringBuilder; - -#endif // WINPTY_STRING_BUILDER_H diff --git a/deps/winpty/src/shared/StringBuilderTest.cc b/deps/winpty/src/shared/StringBuilderTest.cc deleted file mode 100644 index e6c2d3138..000000000 --- a/deps/winpty/src/shared/StringBuilderTest.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#define STRING_BUILDER_TESTING - -#include "StringBuilder.h" - -#include -#include - -#include -#include - -void display(const std::string &str) { fprintf(stderr, "%s", str.c_str()); } -void display(const std::wstring &str) { fprintf(stderr, "%ls", str.c_str()); } - -#define CHECK_EQ(x, y) \ - do { \ - const auto xval = (x); \ - const auto yval = (y); \ - if (xval != yval) { \ - fprintf(stderr, "error: %s:%d: %s != %s: ", \ - __FILE__, __LINE__, #x, #y); \ - display(xval); \ - fprintf(stderr, " != "); \ - display(yval); \ - fprintf(stderr, "\n"); \ - } \ - } while(0) - -template -std::basic_string decOfIntSS(const I value) { - // std::to_string and std::to_wstring are missing in Cygwin as of this - // writing (early 2016). - std::basic_stringstream ss; - ss << +value; // We must promote char to print it as an integer. - return ss.str(); -} - - -template -std::basic_string hexOfIntSS(const I value) { - typedef typename std::make_unsigned::type U; - const unsigned long long u64Value = value & static_cast(~0); - std::basic_stringstream ss; - if (leadingZeros) { - ss << std::setfill(static_cast('0')) << std::setw(sizeof(I) * 2); - } - ss << std::hex << u64Value; - return ss.str(); -} - -template -void testValue(I value) { - CHECK_EQ(decOfInt(value).str(), (decOfIntSS(value))); - CHECK_EQ(wdecOfInt(value).str(), (decOfIntSS(value))); - CHECK_EQ((hexOfInt(value).str()), (hexOfIntSS(value))); - CHECK_EQ((hexOfInt(value).str()), (hexOfIntSS(value))); - CHECK_EQ((whexOfInt(value).str()), (hexOfIntSS(value))); - CHECK_EQ((whexOfInt(value).str()), (hexOfIntSS(value))); -} - -template -void testType() { - typedef typename std::make_unsigned::type U; - const U quarter = static_cast(1) << (sizeof(U) * 8 - 2); - for (unsigned quarterIndex = 0; quarterIndex < 4; ++quarterIndex) { - for (int offset = -18; offset <= 18; ++offset) { - const I value = quarter * quarterIndex + static_cast(offset); - testValue(value); - } - } - testValue(static_cast(42)); - testValue(static_cast(123456)); - testValue(static_cast(0xdeadfacecafebeefull)); -} - -int main() { - testType(); - - testType(); - testType(); - testType(); - testType(); - testType(); - - testType(); - testType(); - testType(); - testType(); - testType(); - - StringBuilder() << static_cast("TEST"); - WStringBuilder() << static_cast("TEST"); - - fprintf(stderr, "All tests completed!\n"); -} diff --git a/deps/winpty/src/shared/StringUtil.cc b/deps/winpty/src/shared/StringUtil.cc deleted file mode 100644 index 3a85a3ec9..000000000 --- a/deps/winpty/src/shared/StringUtil.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "StringUtil.h" - -#include - -#include "WinptyAssert.h" - -// Workaround. MinGW (from mingw.org) does not have wcsnlen. MinGW-w64 *does* -// have wcsnlen, but use this function for consistency. -size_t winpty_wcsnlen(const wchar_t *s, size_t maxlen) { - ASSERT(s != NULL); - for (size_t i = 0; i < maxlen; ++i) { - if (s[i] == L'\0') { - return i; - } - } - return maxlen; -} - -std::string utf8FromWide(const std::wstring &input) { - int mblen = WideCharToMultiByte( - CP_UTF8, 0, - input.data(), input.size(), - NULL, 0, NULL, NULL); - if (mblen <= 0) { - return std::string(); - } - std::vector tmp(mblen); - int mblen2 = WideCharToMultiByte( - CP_UTF8, 0, - input.data(), input.size(), - tmp.data(), tmp.size(), - NULL, NULL); - ASSERT(mblen2 == mblen); - return std::string(tmp.data(), tmp.size()); -} diff --git a/deps/winpty/src/shared/StringUtil.h b/deps/winpty/src/shared/StringUtil.h deleted file mode 100644 index e4bf3c912..000000000 --- a/deps/winpty/src/shared/StringUtil.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_STRING_UTIL_H -#define WINPTY_SHARED_STRING_UTIL_H - -#include -#include -#include - -#include -#include -#include - -#include "WinptyAssert.h" - -size_t winpty_wcsnlen(const wchar_t *s, size_t maxlen); -std::string utf8FromWide(const std::wstring &input); - -// Return a vector containing each character in the string. -template -std::vector vectorFromString(const std::basic_string &str) { - return std::vector(str.begin(), str.end()); -} - -// Return a vector containing each character in the string, followed by a -// NUL terminator. -template -std::vector vectorWithNulFromString(const std::basic_string &str) { - std::vector ret; - ret.reserve(str.size() + 1); - ret.insert(ret.begin(), str.begin(), str.end()); - ret.push_back('\0'); - return ret; -} - -// A safer(?) version of wcsncpy that is accepted by MSVC's /SDL mode. -template -wchar_t *winpty_wcsncpy(wchar_t (&d)[N], const wchar_t *s) { - ASSERT(s != nullptr); - size_t i = 0; - for (; i < N; ++i) { - if (s[i] == L'\0') { - break; - } - d[i] = s[i]; - } - for (; i < N; ++i) { - d[i] = L'\0'; - } - return d; -} - -// Like wcsncpy, but ensure that the destination buffer is NUL-terminated. -template -wchar_t *winpty_wcsncpy_nul(wchar_t (&d)[N], const wchar_t *s) { - static_assert(N > 0, "array cannot be 0-size"); - winpty_wcsncpy(d, s); - d[N - 1] = L'\0'; - return d; -} - -#endif // WINPTY_SHARED_STRING_UTIL_H diff --git a/deps/winpty/src/shared/TimeMeasurement.h b/deps/winpty/src/shared/TimeMeasurement.h deleted file mode 100644 index 716a027fc..000000000 --- a/deps/winpty/src/shared/TimeMeasurement.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// Convenience header library for using the high-resolution performance counter -// to measure how long some process takes. - -#ifndef TIME_MEASUREMENT_H -#define TIME_MEASUREMENT_H - -#include -#include -#include - -class TimeMeasurement { -public: - TimeMeasurement() { - static double freq = static_cast(getFrequency()); - m_freq = freq; - m_start = value(); - } - - double elapsed() { - uint64_t elapsedTicks = value() - m_start; - return static_cast(elapsedTicks) / m_freq; - } - -private: - uint64_t getFrequency() { - LARGE_INTEGER freq; - BOOL success = QueryPerformanceFrequency(&freq); - assert(success && "QueryPerformanceFrequency failed"); - return freq.QuadPart; - } - - uint64_t value() { - LARGE_INTEGER ret; - BOOL success = QueryPerformanceCounter(&ret); - assert(success && "QueryPerformanceCounter failed"); - return ret.QuadPart; - } - - uint64_t m_start; - double m_freq; -}; - -#endif // TIME_MEASUREMENT_H diff --git a/deps/winpty/src/shared/UnixCtrlChars.h b/deps/winpty/src/shared/UnixCtrlChars.h deleted file mode 100644 index 39dfa62ec..000000000 --- a/deps/winpty/src/shared/UnixCtrlChars.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNIX_CTRL_CHARS_H -#define UNIX_CTRL_CHARS_H - -inline char decodeUnixCtrlChar(char ch) { - const char ctrlKeys[] = { - /* 0x00 */ '@', /* 0x01 */ 'A', /* 0x02 */ 'B', /* 0x03 */ 'C', - /* 0x04 */ 'D', /* 0x05 */ 'E', /* 0x06 */ 'F', /* 0x07 */ 'G', - /* 0x08 */ 'H', /* 0x09 */ 'I', /* 0x0A */ 'J', /* 0x0B */ 'K', - /* 0x0C */ 'L', /* 0x0D */ 'M', /* 0x0E */ 'N', /* 0x0F */ 'O', - /* 0x10 */ 'P', /* 0x11 */ 'Q', /* 0x12 */ 'R', /* 0x13 */ 'S', - /* 0x14 */ 'T', /* 0x15 */ 'U', /* 0x16 */ 'V', /* 0x17 */ 'W', - /* 0x18 */ 'X', /* 0x19 */ 'Y', /* 0x1A */ 'Z', /* 0x1B */ '[', - /* 0x1C */ '\\', /* 0x1D */ ']', /* 0x1E */ '^', /* 0x1F */ '_', - }; - unsigned char uch = ch; - if (uch < 32) { - return ctrlKeys[uch]; - } else if (uch == 127) { - return '?'; - } else { - return '\0'; - } -} - -#endif // UNIX_CTRL_CHARS_H diff --git a/deps/winpty/src/shared/UpdateGenVersion.bat b/deps/winpty/src/shared/UpdateGenVersion.bat deleted file mode 100644 index ea2a7d64e..000000000 --- a/deps/winpty/src/shared/UpdateGenVersion.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off - -rem -- Echo the git commit hash. If git isn't available for some reason, -rem -- output nothing instead. - -mkdir ..\gen 2>nul - -set /p VERSION=<..\..\VERSION.txt -set COMMIT=%1 - -echo // AUTO-GENERATED BY %0 %*>..\gen\GenVersion.h -echo const char GenVersion_Version[] = "%VERSION%";>>..\gen\GenVersion.h -echo const char GenVersion_Commit[] = "%COMMIT%";>>..\gen\GenVersion.h - -rem -- The winpty.gyp file expects the script to output the include directory, -rem -- relative to src. -echo gen - -rem -- Set ERRORLEVEL to 0 using this cryptic syntax. -(call ) diff --git a/deps/winpty/src/shared/WindowsSecurity.cc b/deps/winpty/src/shared/WindowsSecurity.cc deleted file mode 100644 index 711a8637c..000000000 --- a/deps/winpty/src/shared/WindowsSecurity.cc +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WindowsSecurity.h" - -#include - -#include "DebugClient.h" -#include "OsModule.h" -#include "OwnedHandle.h" -#include "StringBuilder.h" -#include "WindowsVersion.h" -#include "WinptyAssert.h" -#include "WinptyException.h" - -namespace { - -struct LocalFreer { - void operator()(void *ptr) { - if (ptr != nullptr) { - LocalFree(reinterpret_cast(ptr)); - } - } -}; - -typedef std::unique_ptr PointerLocal; - -template -SecurityItem localItem(typename T::type v) { - typedef typename T::type P; - struct Impl : SecurityItem::Impl { - P m_v; - Impl(P v) : m_v(v) {} - virtual ~Impl() { - LocalFree(reinterpret_cast(m_v)); - } - }; - return SecurityItem(v, std::unique_ptr(new Impl { v })); -} - -Sid allocatedSid(PSID v) { - struct Impl : Sid::Impl { - PSID m_v; - Impl(PSID v) : m_v(v) {} - virtual ~Impl() { - if (m_v != nullptr) { - FreeSid(m_v); - } - } - }; - return Sid(v, std::unique_ptr(new Impl { v })); -} - -} // anonymous namespace - -// Returns a handle to the thread's effective security token. If the thread -// is impersonating another user, its token is returned, and otherwise, the -// process' security token is opened. The handle is opened with TOKEN_QUERY. -static OwnedHandle openSecurityTokenForQuery() { - HANDLE token = nullptr; - // It is unclear to me whether OpenAsSelf matters for winpty, or what the - // most appropriate value is. - if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, - /*OpenAsSelf=*/FALSE, &token)) { - if (GetLastError() != ERROR_NO_TOKEN) { - throwWindowsError(L"OpenThreadToken failed"); - } - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { - throwWindowsError(L"OpenProcessToken failed"); - } - } - ASSERT(token != nullptr && - "OpenThreadToken/OpenProcessToken token is NULL"); - return OwnedHandle(token); -} - -// Returns the TokenOwner of the thread's effective security token. -Sid getOwnerSid() { - struct Impl : Sid::Impl { - std::unique_ptr buffer; - }; - - OwnedHandle token = openSecurityTokenForQuery(); - DWORD actual = 0; - BOOL success; - success = GetTokenInformation(token.get(), TokenOwner, - nullptr, 0, &actual); - if (success) { - throwWinptyException(L"getOwnerSid: GetTokenInformation: " - L"expected ERROR_INSUFFICIENT_BUFFER"); - } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - throwWindowsError(L"getOwnerSid: GetTokenInformation: " - L"expected ERROR_INSUFFICIENT_BUFFER"); - } - std::unique_ptr impl(new Impl); - impl->buffer = std::unique_ptr(new char[actual]); - success = GetTokenInformation(token.get(), TokenOwner, - impl->buffer.get(), actual, &actual); - if (!success) { - throwWindowsError(L"getOwnerSid: GetTokenInformation"); - } - TOKEN_OWNER tmp; - ASSERT(actual >= sizeof(tmp)); - std::copy( - impl->buffer.get(), - impl->buffer.get() + sizeof(tmp), - reinterpret_cast(&tmp)); - return Sid(tmp.Owner, std::move(impl)); -} - -Sid wellKnownSid( - const wchar_t *debuggingName, - SID_IDENTIFIER_AUTHORITY authority, - BYTE authorityCount, - DWORD subAuthority0/*=0*/, - DWORD subAuthority1/*=0*/) { - PSID psid = nullptr; - if (!AllocateAndInitializeSid(&authority, authorityCount, - subAuthority0, - subAuthority1, - 0, 0, 0, 0, 0, 0, - &psid)) { - const auto err = GetLastError(); - const auto msg = - std::wstring(L"wellKnownSid: error getting ") + - debuggingName + L" SID"; - throwWindowsError(msg.c_str(), err); - } - return allocatedSid(psid); -} - -Sid builtinAdminsSid() { - // S-1-5-32-544 - SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY }; - return wellKnownSid(L"BUILTIN\\Administrators group", - authority, 2, - SECURITY_BUILTIN_DOMAIN_RID, // 32 - DOMAIN_ALIAS_RID_ADMINS); // 544 -} - -Sid localSystemSid() { - // S-1-5-18 - SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY }; - return wellKnownSid(L"LocalSystem account", - authority, 1, - SECURITY_LOCAL_SYSTEM_RID); // 18 -} - -Sid everyoneSid() { - // S-1-1-0 - SID_IDENTIFIER_AUTHORITY authority = { SECURITY_WORLD_SID_AUTHORITY }; - return wellKnownSid(L"Everyone account", - authority, 1, - SECURITY_WORLD_RID); // 0 -} - -static SecurityDescriptor finishSecurityDescriptor( - size_t daclEntryCount, - EXPLICIT_ACCESSW *daclEntries, - Acl &outAcl) { - { - PACL aclRaw = nullptr; - DWORD aclError = - SetEntriesInAclW(daclEntryCount, - daclEntries, - nullptr, &aclRaw); - if (aclError != ERROR_SUCCESS) { - WStringBuilder sb(64); - sb << L"finishSecurityDescriptor: " - << L"SetEntriesInAcl failed: " << aclError; - throwWinptyException(sb.c_str()); - } - outAcl = localItem(aclRaw); - } - - const PSECURITY_DESCRIPTOR sdRaw = - reinterpret_cast( - LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH)); - if (sdRaw == nullptr) { - throwWinptyException(L"finishSecurityDescriptor: LocalAlloc failed"); - } - SecurityDescriptor sd = localItem(sdRaw); - if (!InitializeSecurityDescriptor(sdRaw, SECURITY_DESCRIPTOR_REVISION)) { - throwWindowsError( - L"finishSecurityDescriptor: InitializeSecurityDescriptor"); - } - if (!SetSecurityDescriptorDacl(sdRaw, TRUE, outAcl.get(), FALSE)) { - throwWindowsError( - L"finishSecurityDescriptor: SetSecurityDescriptorDacl"); - } - - return std::move(sd); -} - -// Create a security descriptor that grants full control to the local system -// account, built-in administrators, and the owner. -SecurityDescriptor -createPipeSecurityDescriptorOwnerFullControl() { - - struct Impl : SecurityDescriptor::Impl { - Sid localSystem; - Sid builtinAdmins; - Sid owner; - std::array daclEntries = {}; - Acl dacl; - SecurityDescriptor value; - }; - - std::unique_ptr impl(new Impl); - impl->localSystem = localSystemSid(); - impl->builtinAdmins = builtinAdminsSid(); - impl->owner = getOwnerSid(); - - for (auto &ea : impl->daclEntries) { - ea.grfAccessPermissions = GENERIC_ALL; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance = NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - } - impl->daclEntries[0].Trustee.ptstrName = - reinterpret_cast(impl->localSystem.get()); - impl->daclEntries[1].Trustee.ptstrName = - reinterpret_cast(impl->builtinAdmins.get()); - impl->daclEntries[2].Trustee.ptstrName = - reinterpret_cast(impl->owner.get()); - - impl->value = finishSecurityDescriptor( - impl->daclEntries.size(), - impl->daclEntries.data(), - impl->dacl); - - const auto retValue = impl->value.get(); - return SecurityDescriptor(retValue, std::move(impl)); -} - -SecurityDescriptor -createPipeSecurityDescriptorOwnerFullControlEveryoneWrite() { - - struct Impl : SecurityDescriptor::Impl { - Sid localSystem; - Sid builtinAdmins; - Sid owner; - Sid everyone; - std::array daclEntries = {}; - Acl dacl; - SecurityDescriptor value; - }; - - std::unique_ptr impl(new Impl); - impl->localSystem = localSystemSid(); - impl->builtinAdmins = builtinAdminsSid(); - impl->owner = getOwnerSid(); - impl->everyone = everyoneSid(); - - for (auto &ea : impl->daclEntries) { - ea.grfAccessPermissions = GENERIC_ALL; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance = NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - } - impl->daclEntries[0].Trustee.ptstrName = - reinterpret_cast(impl->localSystem.get()); - impl->daclEntries[1].Trustee.ptstrName = - reinterpret_cast(impl->builtinAdmins.get()); - impl->daclEntries[2].Trustee.ptstrName = - reinterpret_cast(impl->owner.get()); - impl->daclEntries[3].Trustee.ptstrName = - reinterpret_cast(impl->everyone.get()); - // Avoid using FILE_GENERIC_WRITE because it includes FILE_APPEND_DATA, - // which is equal to FILE_CREATE_PIPE_INSTANCE. Instead, include all the - // flags that comprise FILE_GENERIC_WRITE, except for the one. - impl->daclEntries[3].grfAccessPermissions = - FILE_GENERIC_READ | - FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA | - STANDARD_RIGHTS_WRITE | SYNCHRONIZE; - - impl->value = finishSecurityDescriptor( - impl->daclEntries.size(), - impl->daclEntries.data(), - impl->dacl); - - const auto retValue = impl->value.get(); - return SecurityDescriptor(retValue, std::move(impl)); -} - -SecurityDescriptor getObjectSecurityDescriptor(HANDLE handle) { - PACL dacl = nullptr; - PSECURITY_DESCRIPTOR sd = nullptr; - const DWORD errCode = GetSecurityInfo(handle, SE_KERNEL_OBJECT, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, - nullptr, nullptr, &dacl, nullptr, &sd); - if (errCode != ERROR_SUCCESS) { - throwWindowsError(L"GetSecurityInfo failed"); - } - return localItem(sd); -} - -// The (SID/SD)<->string conversion APIs are useful for testing/debugging, so -// create convenient accessor functions for them. They're too slow for -// ordinary use. The APIs exist in XP and up, but the MinGW headers only -// declare the SID<->string APIs, not the SD APIs. MinGW also gets the -// prototype wrong for ConvertStringSidToSidW (LPWSTR instead of LPCWSTR) and -// requires WINVER to be defined. MSVC and MinGW-w64 get everything right, but -// for consistency, use LoadLibrary/GetProcAddress for all four APIs. - -typedef BOOL WINAPI ConvertStringSidToSidW_t( - LPCWSTR StringSid, - PSID *Sid); - -typedef BOOL WINAPI ConvertSidToStringSidW_t( - PSID Sid, - LPWSTR *StringSid); - -typedef BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW_t( - LPCWSTR StringSecurityDescriptor, - DWORD StringSDRevision, - PSECURITY_DESCRIPTOR *SecurityDescriptor, - PULONG SecurityDescriptorSize); - -typedef BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW_t( - PSECURITY_DESCRIPTOR SecurityDescriptor, - DWORD RequestedStringSDRevision, - SECURITY_INFORMATION SecurityInformation, - LPWSTR *StringSecurityDescriptor, - PULONG StringSecurityDescriptorLen); - -#define GET_MODULE_PROC(mod, funcName) \ - const auto p##funcName = \ - reinterpret_cast( \ - mod.proc(#funcName)); \ - if (p##funcName == nullptr) { \ - throwWinptyException( \ - L"" L ## #funcName L" API is missing from ADVAPI32.DLL"); \ - } - -const DWORD kSDDL_REVISION_1 = 1; - -std::wstring sidToString(PSID sid) { - OsModule advapi32(L"advapi32.dll"); - GET_MODULE_PROC(advapi32, ConvertSidToStringSidW); - wchar_t *sidString = NULL; - BOOL success = pConvertSidToStringSidW(sid, &sidString); - if (!success) { - throwWindowsError(L"ConvertSidToStringSidW failed"); - } - PointerLocal freer(sidString); - return std::wstring(sidString); -} - -Sid stringToSid(const std::wstring &str) { - // Cast the string from const wchar_t* to LPWSTR because the function is - // incorrectly prototyped in the MinGW sddl.h header. The API does not - // modify the string -- it is correctly prototyped as taking LPCWSTR in - // MinGW-w64, MSVC, and MSDN. - OsModule advapi32(L"advapi32.dll"); - GET_MODULE_PROC(advapi32, ConvertStringSidToSidW); - PSID psid = nullptr; - BOOL success = pConvertStringSidToSidW(const_cast(str.c_str()), - &psid); - if (!success) { - const auto err = GetLastError(); - throwWindowsError( - (std::wstring(L"ConvertStringSidToSidW failed on \"") + - str + L'"').c_str(), - err); - } - return localItem(psid); -} - -SecurityDescriptor stringToSd(const std::wstring &str) { - OsModule advapi32(L"advapi32.dll"); - GET_MODULE_PROC(advapi32, ConvertStringSecurityDescriptorToSecurityDescriptorW); - PSECURITY_DESCRIPTOR desc = nullptr; - if (!pConvertStringSecurityDescriptorToSecurityDescriptorW( - str.c_str(), kSDDL_REVISION_1, &desc, nullptr)) { - const auto err = GetLastError(); - throwWindowsError( - (std::wstring(L"ConvertStringSecurityDescriptorToSecurityDescriptorW failed on \"") + - str + L'"').c_str(), - err); - } - return localItem(desc); -} - -std::wstring sdToString(PSECURITY_DESCRIPTOR sd) { - OsModule advapi32(L"advapi32.dll"); - GET_MODULE_PROC(advapi32, ConvertSecurityDescriptorToStringSecurityDescriptorW); - wchar_t *sdString = nullptr; - if (!pConvertSecurityDescriptorToStringSecurityDescriptorW( - sd, - kSDDL_REVISION_1, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, - &sdString, - nullptr)) { - throwWindowsError( - L"ConvertSecurityDescriptorToStringSecurityDescriptor failed"); - } - PointerLocal freer(sdString); - return std::wstring(sdString); -} - -// Vista added a useful flag to CreateNamedPipe, PIPE_REJECT_REMOTE_CLIENTS, -// that rejects remote connections. Return this flag on Vista, or return 0 -// otherwise. -DWORD rejectRemoteClientsPipeFlag() { - if (isAtLeastWindowsVista()) { - // MinGW lacks this flag; MinGW-w64 has it. - const DWORD kPIPE_REJECT_REMOTE_CLIENTS = 8; - return kPIPE_REJECT_REMOTE_CLIENTS; - } else { - trace("Omitting PIPE_REJECT_REMOTE_CLIENTS on pre-Vista OS"); - return 0; - } -} - -typedef BOOL WINAPI GetNamedPipeClientProcessId_t( - HANDLE Pipe, - PULONG ClientProcessId); - -std::tuple -getNamedPipeClientProcessId(HANDLE serverPipe) { - OsModule kernel32(L"kernel32.dll"); - const auto pGetNamedPipeClientProcessId = - reinterpret_cast( - kernel32.proc("GetNamedPipeClientProcessId")); - if (pGetNamedPipeClientProcessId == nullptr) { - return std::make_tuple( - GetNamedPipeClientProcessId_Result::UnsupportedOs, 0, 0); - } - ULONG pid = 0; - if (!pGetNamedPipeClientProcessId(serverPipe, &pid)) { - return std::make_tuple( - GetNamedPipeClientProcessId_Result::Failure, 0, GetLastError()); - } - return std::make_tuple( - GetNamedPipeClientProcessId_Result::Success, - static_cast(pid), - 0); -} diff --git a/deps/winpty/src/shared/WindowsSecurity.h b/deps/winpty/src/shared/WindowsSecurity.h deleted file mode 100644 index 5f9d53aff..000000000 --- a/deps/winpty/src/shared/WindowsSecurity.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_WINDOWS_SECURITY_H -#define WINPTY_WINDOWS_SECURITY_H - -#include -#include - -#include -#include -#include -#include - -// PSID and PSECURITY_DESCRIPTOR are both pointers to void, but we want -// Sid and SecurityDescriptor to be different types. -struct SidTag { typedef PSID type; }; -struct AclTag { typedef PACL type; }; -struct SecurityDescriptorTag { typedef PSECURITY_DESCRIPTOR type; }; - -template -class SecurityItem { -public: - struct Impl { - virtual ~Impl() {} - }; - -private: - typedef typename T::type P; - P m_v; - std::unique_ptr m_pimpl; - -public: - P get() const { return m_v; } - operator bool() const { return m_v != nullptr; } - - SecurityItem() : m_v(nullptr) {} - SecurityItem(P v, std::unique_ptr &&pimpl) : - m_v(v), m_pimpl(std::move(pimpl)) {} - SecurityItem(SecurityItem &&other) : - m_v(other.m_v), m_pimpl(std::move(other.m_pimpl)) { - other.m_v = nullptr; - } - SecurityItem &operator=(SecurityItem &&other) { - m_v = other.m_v; - other.m_v = nullptr; - m_pimpl = std::move(other.m_pimpl); - return *this; - } -}; - -typedef SecurityItem Sid; -typedef SecurityItem Acl; -typedef SecurityItem SecurityDescriptor; - -Sid getOwnerSid(); -Sid wellKnownSid( - const wchar_t *debuggingName, - SID_IDENTIFIER_AUTHORITY authority, - BYTE authorityCount, - DWORD subAuthority0=0, - DWORD subAuthority1=0); -Sid builtinAdminsSid(); -Sid localSystemSid(); -Sid everyoneSid(); - -SecurityDescriptor createPipeSecurityDescriptorOwnerFullControl(); -SecurityDescriptor createPipeSecurityDescriptorOwnerFullControlEveryoneWrite(); -SecurityDescriptor getObjectSecurityDescriptor(HANDLE handle); - -std::wstring sidToString(PSID sid); -Sid stringToSid(const std::wstring &str); -SecurityDescriptor stringToSd(const std::wstring &str); -std::wstring sdToString(PSECURITY_DESCRIPTOR sd); - -DWORD rejectRemoteClientsPipeFlag(); - -enum class GetNamedPipeClientProcessId_Result { - Success, - Failure, - UnsupportedOs, -}; - -std::tuple -getNamedPipeClientProcessId(HANDLE serverPipe); - -#endif // WINPTY_WINDOWS_SECURITY_H diff --git a/deps/winpty/src/shared/WindowsVersion.cc b/deps/winpty/src/shared/WindowsVersion.cc deleted file mode 100644 index d89b00d83..000000000 --- a/deps/winpty/src/shared/WindowsVersion.cc +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WindowsVersion.h" - -#include -#include - -#include -#include -#include - -#include "DebugClient.h" -#include "OsModule.h" -#include "StringBuilder.h" -#include "StringUtil.h" -#include "WinptyAssert.h" -#include "WinptyException.h" - -namespace { - -typedef std::tuple Version; - -// This function can only return a version up to 6.2 unless the executable is -// manifested for a newer version of Windows. See the MSDN documentation for -// GetVersionEx. -OSVERSIONINFOEX getWindowsVersionInfo() { - // Allow use of deprecated functions (i.e. GetVersionEx). We need to use - // GetVersionEx for the old MinGW toolchain and with MSVC when it targets XP. - // Having two code paths makes code harder to test, and it's not obvious how - // to detect the presence of a new enough SDK. (Including ntverp.h and - // examining VER_PRODUCTBUILD apparently works, but even then, MinGW-w64 and - // MSVC seem to use different version numbers.) -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4996) -#endif - OSVERSIONINFOEX info = {}; - info.dwOSVersionInfoSize = sizeof(info); - const auto success = GetVersionEx(reinterpret_cast(&info)); - ASSERT(success && "GetVersionEx failed"); - return info; -#ifdef _MSC_VER -#pragma warning(pop) -#endif -} - -Version getWindowsVersion() { - const auto info = getWindowsVersionInfo(); - return Version(info.dwMajorVersion, info.dwMinorVersion); -} - -struct ModuleNotFound : WinptyException { - virtual const wchar_t *what() const WINPTY_NOEXCEPT override { - return L"ModuleNotFound"; - } -}; - -// Throws WinptyException on error. -std::wstring getSystemDirectory() { - wchar_t systemDirectory[MAX_PATH]; - const UINT size = GetSystemDirectoryW(systemDirectory, MAX_PATH); - if (size == 0) { - throwWindowsError(L"GetSystemDirectory failed"); - } else if (size >= MAX_PATH) { - throwWinptyException( - L"GetSystemDirectory: path is longer than MAX_PATH"); - } - return systemDirectory; -} - -#define GET_VERSION_DLL_API(name) \ - const auto p ## name = \ - reinterpret_cast( \ - versionDll.proc(#name)); \ - if (p ## name == nullptr) { \ - throwWinptyException(L ## #name L" is missing"); \ - } - -// Throws WinptyException on error. -VS_FIXEDFILEINFO getFixedFileInfo(const std::wstring &path) { - // version.dll is not a conventional KnownDll, so if we link to it, there's - // a danger of accidentally loading a malicious DLL. In a more typical - // application, perhaps we'd guard against this security issue by - // controlling which directories this code runs in (e.g. *not* the - // "Downloads" directory), but that's harder for the winpty library. - OsModule versionDll( - (getSystemDirectory() + L"\\version.dll").c_str(), - OsModule::LoadErrorBehavior::Throw); - GET_VERSION_DLL_API(GetFileVersionInfoSizeW); - GET_VERSION_DLL_API(GetFileVersionInfoW); - GET_VERSION_DLL_API(VerQueryValueW); - DWORD size = pGetFileVersionInfoSizeW(path.c_str(), nullptr); - if (!size) { - // I see ERROR_FILE_NOT_FOUND on Win7 and - // ERROR_RESOURCE_DATA_NOT_FOUND on WinXP. - if (GetLastError() == ERROR_FILE_NOT_FOUND || - GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND) { - throw ModuleNotFound(); - } else { - throwWindowsError( - (L"GetFileVersionInfoSizeW failed on " + path).c_str()); - } - } - std::unique_ptr versionBuffer(new char[size]); - if (!pGetFileVersionInfoW(path.c_str(), 0, size, versionBuffer.get())) { - throwWindowsError((L"GetFileVersionInfoW failed on " + path).c_str()); - } - VS_FIXEDFILEINFO *versionInfo = nullptr; - UINT versionInfoSize = 0; - if (!pVerQueryValueW( - versionBuffer.get(), L"\\", - reinterpret_cast(&versionInfo), &versionInfoSize) || - versionInfo == nullptr || - versionInfoSize != sizeof(VS_FIXEDFILEINFO) || - versionInfo->dwSignature != 0xFEEF04BD) { - throwWinptyException((L"VerQueryValueW failed on " + path).c_str()); - } - return *versionInfo; -} - -uint64_t productVersionFromInfo(const VS_FIXEDFILEINFO &info) { - return (static_cast(info.dwProductVersionMS) << 32) | - (static_cast(info.dwProductVersionLS)); -} - -uint64_t fileVersionFromInfo(const VS_FIXEDFILEINFO &info) { - return (static_cast(info.dwFileVersionMS) << 32) | - (static_cast(info.dwFileVersionLS)); -} - -std::string versionToString(uint64_t version) { - StringBuilder b(32); - b << ((uint16_t)(version >> 48)); - b << '.'; - b << ((uint16_t)(version >> 32)); - b << '.'; - b << ((uint16_t)(version >> 16)); - b << '.'; - b << ((uint16_t)(version >> 0)); - return b.str_moved(); -} - -} // anonymous namespace - -// Returns true for Windows Vista (or Windows Server 2008) or newer. -bool isAtLeastWindowsVista() { - return getWindowsVersion() >= Version(6, 0); -} - -// Returns true for Windows 7 (or Windows Server 2008 R2) or newer. -bool isAtLeastWindows7() { - return getWindowsVersion() >= Version(6, 1); -} - -// Returns true for Windows 8 (or Windows Server 2012) or newer. -bool isAtLeastWindows8() { - return getWindowsVersion() >= Version(6, 2); -} - -#define WINPTY_IA32 1 -#define WINPTY_X64 2 - -#if defined(_M_IX86) || defined(__i386__) -#define WINPTY_ARCH WINPTY_IA32 -#elif defined(_M_X64) || defined(__x86_64__) -#define WINPTY_ARCH WINPTY_X64 -#endif - -typedef BOOL WINAPI IsWow64Process_t(HANDLE hProcess, PBOOL Wow64Process); - -void dumpWindowsVersion() { - if (!isTracingEnabled()) { - return; - } - const auto info = getWindowsVersionInfo(); - StringBuilder b; - b << info.dwMajorVersion << '.' << info.dwMinorVersion - << '.' << info.dwBuildNumber << ' ' - << "SP" << info.wServicePackMajor << '.' << info.wServicePackMinor - << ' '; - switch (info.wProductType) { - case VER_NT_WORKSTATION: b << "Client"; break; - case VER_NT_DOMAIN_CONTROLLER: b << "DomainController"; break; - case VER_NT_SERVER: b << "Server"; break; - default: - b << "product=" << info.wProductType; break; - } - b << ' '; -#if WINPTY_ARCH == WINPTY_IA32 - b << "IA32"; - OsModule kernel32(L"kernel32.dll"); - IsWow64Process_t *pIsWow64Process = - reinterpret_cast( - kernel32.proc("IsWow64Process")); - if (pIsWow64Process != nullptr) { - BOOL result = false; - const BOOL success = pIsWow64Process(GetCurrentProcess(), &result); - if (!success) { - b << " WOW64:error"; - } else if (success && result) { - b << " WOW64"; - } - } else { - b << " WOW64:missingapi"; - } -#elif WINPTY_ARCH == WINPTY_X64 - b << "X64"; -#endif - const auto dllVersion = [](const wchar_t *dllPath) -> std::string { - try { - const auto info = getFixedFileInfo(dllPath); - StringBuilder fb(64); - fb << utf8FromWide(dllPath) << ':'; - fb << "F:" << versionToString(fileVersionFromInfo(info)) << '/' - << "P:" << versionToString(productVersionFromInfo(info)); - return fb.str_moved(); - } catch (const ModuleNotFound&) { - return utf8FromWide(dllPath) + ":none"; - } catch (const WinptyException &e) { - trace("Error getting %s version: %s", - utf8FromWide(dllPath).c_str(), utf8FromWide(e.what()).c_str()); - return utf8FromWide(dllPath) + ":error"; - } - }; - b << ' ' << dllVersion(L"kernel32.dll"); - // ConEmu provides a DLL that hooks many Windows APIs, especially console - // APIs. Its existence and version number could be useful in debugging. -#if WINPTY_ARCH == WINPTY_IA32 - b << ' ' << dllVersion(L"ConEmuHk.dll"); -#elif WINPTY_ARCH == WINPTY_X64 - b << ' ' << dllVersion(L"ConEmuHk64.dll"); -#endif - trace("Windows version: %s", b.c_str()); -} diff --git a/deps/winpty/src/shared/WindowsVersion.h b/deps/winpty/src/shared/WindowsVersion.h deleted file mode 100644 index a80798417..000000000 --- a/deps/winpty/src/shared/WindowsVersion.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SHARED_WINDOWS_VERSION_H -#define WINPTY_SHARED_WINDOWS_VERSION_H - -bool isAtLeastWindowsVista(); -bool isAtLeastWindows7(); -bool isAtLeastWindows8(); -void dumpWindowsVersion(); - -#endif // WINPTY_SHARED_WINDOWS_VERSION_H diff --git a/deps/winpty/src/shared/WinptyAssert.cc b/deps/winpty/src/shared/WinptyAssert.cc deleted file mode 100644 index 1ff0de475..000000000 --- a/deps/winpty/src/shared/WinptyAssert.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WinptyAssert.h" - -#include -#include - -#include "DebugClient.h" - -void assertTrace(const char *file, int line, const char *cond) { - trace("Assertion failed: %s, file %s, line %d", - cond, file, line); -} - -#ifdef WINPTY_AGENT_ASSERT - -void agentShutdown() { - HWND hwnd = GetConsoleWindow(); - if (hwnd != NULL) { - PostMessage(hwnd, WM_CLOSE, 0, 0); - Sleep(30000); - trace("Agent shutdown: WM_CLOSE did not end agent process"); - } else { - trace("Agent shutdown: GetConsoleWindow() is NULL"); - } - // abort() prints a message to the console, and if it is frozen, then the - // process would hang, so instead use exit(). (We shouldn't ever get here, - // though, because the WM_CLOSE message should have ended this process.) - exit(1); -} - -void agentAssertFail(const char *file, int line, const char *cond) { - assertTrace(file, line, cond); - agentShutdown(); -} - -#endif diff --git a/deps/winpty/src/shared/WinptyAssert.h b/deps/winpty/src/shared/WinptyAssert.h deleted file mode 100644 index b2b8b5e64..000000000 --- a/deps/winpty/src/shared/WinptyAssert.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2011-2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_ASSERT_H -#define WINPTY_ASSERT_H - -#ifdef WINPTY_AGENT_ASSERT - -void agentShutdown(); -void agentAssertFail(const char *file, int line, const char *cond); - -// Calling the standard assert() function does not work in the agent because -// the error message would be printed to the console, and the only way the -// user can see the console is via a working agent! Moreover, the console may -// be frozen, so attempting to write to it would block forever. This custom -// assert function instead sends the message to the DebugServer, then attempts -// to close the console, then quietly exits. -#define ASSERT(cond) \ - do { \ - if (!(cond)) { \ - agentAssertFail(__FILE__, __LINE__, #cond); \ - } \ - } while(0) - -#else - -void assertTrace(const char *file, int line, const char *cond); - -// In the other targets, log the assert failure to the debugserver, then fail -// using the ordinary assert mechanism. In case assert is compiled out, fail -// using abort. The amount of code inlined is unfortunate, but asserts aren't -// used much outside the agent. -#include -#include -#define ASSERT_CONDITION(cond) (false && (cond)) -#define ASSERT(cond) \ - do { \ - if (!(cond)) { \ - assertTrace(__FILE__, __LINE__, #cond); \ - assert(ASSERT_CONDITION(#cond)); \ - abort(); \ - } \ - } while(0) - -#endif - -#endif // WINPTY_ASSERT_H diff --git a/deps/winpty/src/shared/WinptyException.cc b/deps/winpty/src/shared/WinptyException.cc deleted file mode 100644 index d0d48823d..000000000 --- a/deps/winpty/src/shared/WinptyException.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WinptyException.h" - -#include -#include - -#include "StringBuilder.h" - -namespace { - -class ExceptionImpl : public WinptyException { -public: - ExceptionImpl(const wchar_t *what) : - m_what(std::make_shared(what)) {} - virtual const wchar_t *what() const WINPTY_NOEXCEPT override { - return m_what->c_str(); - } -private: - // Using a shared_ptr ensures that copying the object raises no exception. - std::shared_ptr m_what; -}; - -} // anonymous namespace - -void throwWinptyException(const wchar_t *what) { - throw ExceptionImpl(what); -} - -void throwWindowsError(const wchar_t *prefix, DWORD errorCode) { - WStringBuilder sb(64); - if (prefix != nullptr) { - sb << prefix << L": "; - } - // It might make sense to use FormatMessage here, but IIRC, its API is hard - // to figure out. - sb << L"Windows error " << errorCode; - throwWinptyException(sb.c_str()); -} diff --git a/deps/winpty/src/shared/WinptyException.h b/deps/winpty/src/shared/WinptyException.h deleted file mode 100644 index ec353369e..000000000 --- a/deps/winpty/src/shared/WinptyException.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_EXCEPTION_H -#define WINPTY_EXCEPTION_H - -#include - -#if defined(__GNUC__) -#define WINPTY_NOEXCEPT noexcept -#elif defined(_MSC_VER) && _MSC_VER >= 1900 -#define WINPTY_NOEXCEPT noexcept -#else -#define WINPTY_NOEXCEPT -#endif - -class WinptyException { -public: - virtual const wchar_t *what() const WINPTY_NOEXCEPT = 0; - virtual ~WinptyException() {} -}; - -void throwWinptyException(const wchar_t *what); -void throwWindowsError(const wchar_t *prefix, DWORD error=GetLastError()); - -#endif // WINPTY_EXCEPTION_H diff --git a/deps/winpty/src/shared/WinptyVersion.cc b/deps/winpty/src/shared/WinptyVersion.cc deleted file mode 100644 index 76bb8a584..000000000 --- a/deps/winpty/src/shared/WinptyVersion.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WinptyVersion.h" - -#include -#include - -#include "DebugClient.h" - -// This header is auto-generated by either the Makefile (Unix) or -// UpdateGenVersion.bat (gyp). It is placed in a 'gen' directory, which is -// added to the search path. -#include "GenVersion.h" - -void dumpVersionToStdout() { - printf("winpty version %s\n", GenVersion_Version); - printf("commit %s\n", GenVersion_Commit); -} - -void dumpVersionToTrace() { - trace("winpty version %s (commit %s)", - GenVersion_Version, - GenVersion_Commit); -} diff --git a/deps/winpty/src/shared/WinptyVersion.h b/deps/winpty/src/shared/WinptyVersion.h deleted file mode 100644 index e6224d7b8..000000000 --- a/deps/winpty/src/shared/WinptyVersion.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_VERSION_H -#define WINPTY_VERSION_H - -void dumpVersionToStdout(); -void dumpVersionToTrace(); - -#endif // WINPTY_VERSION_H diff --git a/deps/winpty/src/shared/winpty_snprintf.h b/deps/winpty/src/shared/winpty_snprintf.h deleted file mode 100644 index e716f245e..000000000 --- a/deps/winpty/src/shared/winpty_snprintf.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2016 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef WINPTY_SNPRINTF_H -#define WINPTY_SNPRINTF_H - -#include -#include -#include - -#include "WinptyAssert.h" - -#if defined(__CYGWIN__) || defined(__MSYS__) -#define WINPTY_SNPRINTF_FORMAT(fmtarg, vararg) \ - __attribute__((format(printf, (fmtarg), ((vararg))))) -#elif defined(__GNUC__) -#define WINPTY_SNPRINTF_FORMAT(fmtarg, vararg) \ - __attribute__((format(ms_printf, (fmtarg), ((vararg))))) -#else -#define WINPTY_SNPRINTF_FORMAT(fmtarg, vararg) -#endif - -// Returns a value between 0 and size - 1 (inclusive) on success. Returns -1 -// on failure (including truncation). The output buffer is always -// NUL-terminated. -inline int -winpty_vsnprintf(char *out, size_t size, const char *fmt, va_list ap) { - ASSERT(size > 0); - out[0] = '\0'; -#if defined(_MSC_VER) && _MSC_VER < 1900 - // MSVC 2015 added a C99-conforming vsnprintf. - int count = _vsnprintf_s(out, size, _TRUNCATE, fmt, ap); -#else - // MinGW configurations frequently provide a vsnprintf function that simply - // calls one of the MS _vsnprintf* functions, which are not C99 conformant. - int count = vsnprintf(out, size, fmt, ap); -#endif - if (count < 0 || static_cast(count) >= size) { - // On truncation, some *printf* implementations return the - // non-truncated size, but other implementations returns -1. Return - // -1 for consistency. - count = -1; - // Guarantee NUL termination. - out[size - 1] = '\0'; - } else { - // Guarantee NUL termination. - out[count] = '\0'; - } - return count; -} - -// Wraps winpty_vsnprintf. -inline int winpty_snprintf(char *out, size_t size, const char *fmt, ...) - WINPTY_SNPRINTF_FORMAT(3, 4); -inline int winpty_snprintf(char *out, size_t size, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - const int count = winpty_vsnprintf(out, size, fmt, ap); - va_end(ap); - return count; -} - -// Wraps winpty_vsnprintf with automatic size determination. -template -int winpty_vsnprintf(char (&out)[size], const char *fmt, va_list ap) { - return winpty_vsnprintf(out, size, fmt, ap); -} - -// Wraps winpty_vsnprintf with automatic size determination. -template -int winpty_snprintf(char (&out)[size], const char *fmt, ...) - WINPTY_SNPRINTF_FORMAT(2, 3); -template -int winpty_snprintf(char (&out)[size], const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - const int count = winpty_vsnprintf(out, size, fmt, ap); - va_end(ap); - return count; -} - -#endif // WINPTY_SNPRINTF_H diff --git a/deps/winpty/src/subdir.mk b/deps/winpty/src/subdir.mk deleted file mode 100644 index 9ae8031b0..000000000 --- a/deps/winpty/src/subdir.mk +++ /dev/null @@ -1,5 +0,0 @@ -include src/agent/subdir.mk -include src/debugserver/subdir.mk -include src/libwinpty/subdir.mk -include src/tests/subdir.mk -include src/unix-adapter/subdir.mk diff --git a/deps/winpty/src/tests/subdir.mk b/deps/winpty/src/tests/subdir.mk deleted file mode 100644 index 18799c4a5..000000000 --- a/deps/winpty/src/tests/subdir.mk +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -build/%.exe : src/tests/%.cc build/winpty.dll - $(info Building $@) - @$(MINGW_CXX) $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS) -o $@ $^ - -TEST_PROGRAMS = \ - build/trivial_test.exe - --include $(TEST_PROGRAMS:.exe=.d) diff --git a/deps/winpty/src/tests/trivial_test.cc b/deps/winpty/src/tests/trivial_test.cc deleted file mode 100644 index 2188a4bef..000000000 --- a/deps/winpty/src/tests/trivial_test.cc +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include - -#include -#include -#include -#include -#include -#include - -#include "../include/winpty.h" -#include "../shared/DebugClient.h" - -static std::vector filterContent( - const std::vector &content) { - std::vector result; - auto it = content.begin(); - const auto itEnd = content.end(); - while (it < itEnd) { - if (*it == '\r') { - // Filter out carriage returns. Sometimes the output starts with - // a single CR; other times, it has multiple CRs. - it++; - } else if (*it == '\x1b' && (it + 1) < itEnd && *(it + 1) == '[') { - // Filter out escape sequences. They have no interior letters and - // end with a single letter. - it += 2; - while (it < itEnd && !isalpha(*it)) { - it++; - } - it++; - } else { - // Let everything else through. - result.push_back(*it); - it++; - } - } - return result; -} - -// Read bytes from the non-overlapped file handle until the file is closed or -// until an I/O error occurs. -static std::vector readAll(HANDLE handle) { - unsigned char buf[1024]; - std::vector result; - while (true) { - DWORD amount = 0; - BOOL ret = ReadFile(handle, buf, sizeof(buf), &amount, nullptr); - if (!ret || amount == 0) { - break; - } - result.insert(result.end(), buf, buf + amount); - } - return result; -} - -static void parentTest() { - wchar_t program[1024]; - wchar_t cmdline[1024]; - GetModuleFileNameW(nullptr, program, 1024); - - { - // XXX: We'd like to use swprintf, which is part of C99 and takes a - // size_t maxlen argument. MinGW-w64 has this function, as does MSVC. - // The old MinGW doesn't, though -- instead, it apparently provides an - // swprintf taking no maxlen argument. This *might* be a regression? - // (There is also no swnprintf, but that function is obsolescent with a - // correct swprintf, and it isn't in POSIX or ISO C.) - // - // Visual C++ 6 also provided this non-conformant swprintf, and I'm - // guessing MSVCRT.DLL does too. (My impression is that the old MinGW - // prefers to rely on MSVCRT.DLL for convenience?) - // - // I could compile differently for old MinGW, but what if it fixes its - // function later? Instead, use a workaround. It's starting to make - // sense to drop MinGW support in favor of MinGW-w64. This is too - // annoying. - // - // grepbait: OLD-MINGW / WINPTY_TARGET_MSYS1 - cmdline[0] = L'\0'; - wcscat(cmdline, L"\""); - wcscat(cmdline, program); - wcscat(cmdline, L"\" CHILD"); - } - // swnprintf(cmdline, sizeof(cmdline) / sizeof(cmdline[0]), - // L"\"%ls\" CHILD", program); - - auto agentCfg = winpty_config_new(0, nullptr); - assert(agentCfg != nullptr); - auto pty = winpty_open(agentCfg, nullptr); - assert(pty != nullptr); - winpty_config_free(agentCfg); - - HANDLE conin = CreateFileW( - winpty_conin_name(pty), - GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); - HANDLE conout = CreateFileW( - winpty_conout_name(pty), - GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr); - assert(conin != INVALID_HANDLE_VALUE); - assert(conout != INVALID_HANDLE_VALUE); - - auto spawnCfg = winpty_spawn_config_new( - WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, program, cmdline, - nullptr, nullptr, nullptr); - assert(spawnCfg != nullptr); - HANDLE process = nullptr; - BOOL spawnSuccess = winpty_spawn( - pty, spawnCfg, &process, nullptr, nullptr, nullptr); - assert(spawnSuccess && process != nullptr); - - auto content = readAll(conout); - content = filterContent(content); - - std::vector expectedContent = { - 'H', 'I', '\n', 'X', 'Y', '\n' - }; - DWORD exitCode = 0; - assert(GetExitCodeProcess(process, &exitCode) && exitCode == 42); - CloseHandle(process); - CloseHandle(conin); - CloseHandle(conout); - assert(content == expectedContent); - winpty_free(pty); -} - -static void childTest() { - printf("HI\nXY\n"); - exit(42); -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - parentTest(); - } else { - childTest(); - } - return 0; -} diff --git a/deps/winpty/src/unix-adapter/InputHandler.cc b/deps/winpty/src/unix-adapter/InputHandler.cc deleted file mode 100644 index 39f1e0968..000000000 --- a/deps/winpty/src/unix-adapter/InputHandler.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "InputHandler.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include "../shared/DebugClient.h" -#include "Util.h" -#include "WakeupFd.h" - -InputHandler::InputHandler( - HANDLE conin, int inputfd, WakeupFd &completionWakeup) : - m_conin(conin), - m_inputfd(inputfd), - m_completionWakeup(completionWakeup), - m_threadHasBeenJoined(false), - m_shouldShutdown(0), - m_threadCompleted(0) -{ - pthread_create(&m_thread, NULL, InputHandler::threadProcS, this); -} - -void InputHandler::shutdown() { - startShutdown(); - if (!m_threadHasBeenJoined) { - int ret = pthread_join(m_thread, NULL); - assert(ret == 0 && "pthread_join failed"); - m_threadHasBeenJoined = true; - } -} - -void InputHandler::threadProc() { - std::vector buffer(4096); - fd_set readfds; - FD_ZERO(&readfds); - while (true) { - // Handle shutdown. - m_wakeup.reset(); - if (m_shouldShutdown) { - trace("InputHandler: shutting down"); - break; - } - - // Block until data arrives. - { - const int max_fd = std::max(m_inputfd, m_wakeup.fd()); - FD_SET(m_inputfd, &readfds); - FD_SET(m_wakeup.fd(), &readfds); - selectWrapper("InputHandler", max_fd + 1, &readfds); - if (!FD_ISSET(m_inputfd, &readfds)) { - continue; - } - } - - const int numRead = read(m_inputfd, &buffer[0], buffer.size()); - if (numRead == -1 && errno == EINTR) { - // Apparently, this read is interrupted on Cygwin 1.7 by a SIGWINCH - // signal even though I set the SA_RESTART flag on the handler. - continue; - } - - // tty is closed, or the read failed for some unexpected reason. - if (numRead <= 0) { - trace("InputHandler: tty read failed: numRead=%d", numRead); - break; - } - - DWORD written = 0; - BOOL ret = WriteFile(m_conin, - &buffer[0], numRead, - &written, NULL); - if (!ret || written != static_cast(numRead)) { - if (!ret && GetLastError() == ERROR_BROKEN_PIPE) { - trace("InputHandler: pipe closed: written=%u", - static_cast(written)); - } else { - trace("InputHandler: write failed: " - "ret=%d lastError=0x%x numRead=%d written=%u", - ret, - static_cast(GetLastError()), - numRead, - static_cast(written)); - } - break; - } - } - m_threadCompleted = 1; - m_completionWakeup.set(); -} diff --git a/deps/winpty/src/unix-adapter/InputHandler.h b/deps/winpty/src/unix-adapter/InputHandler.h deleted file mode 100644 index 9c3f540d6..000000000 --- a/deps/winpty/src/unix-adapter/InputHandler.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNIX_ADAPTER_INPUT_HANDLER_H -#define UNIX_ADAPTER_INPUT_HANDLER_H - -#include -#include -#include - -#include "WakeupFd.h" - -// Connect a Cygwin blocking fd to winpty CONIN. -class InputHandler { -public: - InputHandler(HANDLE conin, int inputfd, WakeupFd &completionWakeup); - ~InputHandler() { shutdown(); } - bool isComplete() { return m_threadCompleted; } - void startShutdown() { m_shouldShutdown = 1; m_wakeup.set(); } - void shutdown(); - -private: - static void *threadProcS(void *pvthis) { - reinterpret_cast(pvthis)->threadProc(); - return NULL; - } - void threadProc(); - - HANDLE m_conin; - int m_inputfd; - pthread_t m_thread; - WakeupFd &m_completionWakeup; - WakeupFd m_wakeup; - bool m_threadHasBeenJoined; - volatile sig_atomic_t m_shouldShutdown; - volatile sig_atomic_t m_threadCompleted; -}; - -#endif // UNIX_ADAPTER_INPUT_HANDLER_H diff --git a/deps/winpty/src/unix-adapter/OutputHandler.cc b/deps/winpty/src/unix-adapter/OutputHandler.cc deleted file mode 100644 index 573b8adce..000000000 --- a/deps/winpty/src/unix-adapter/OutputHandler.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "OutputHandler.h" - -#include -#include -#include -#include - -#include -#include - -#include "../shared/DebugClient.h" -#include "Util.h" -#include "WakeupFd.h" - -OutputHandler::OutputHandler( - HANDLE conout, int outputfd, WakeupFd &completionWakeup) : - m_conout(conout), - m_outputfd(outputfd), - m_completionWakeup(completionWakeup), - m_threadHasBeenJoined(false), - m_threadCompleted(0) -{ - pthread_create(&m_thread, NULL, OutputHandler::threadProcS, this); -} - -void OutputHandler::shutdown() { - if (!m_threadHasBeenJoined) { - int ret = pthread_join(m_thread, NULL); - assert(ret == 0 && "pthread_join failed"); - m_threadHasBeenJoined = true; - } -} - -void OutputHandler::threadProc() { - std::vector buffer(4096); - while (true) { - DWORD numRead = 0; - BOOL ret = ReadFile(m_conout, - &buffer[0], buffer.size(), - &numRead, NULL); - if (!ret || numRead == 0) { - if (!ret && GetLastError() == ERROR_BROKEN_PIPE) { - trace("OutputHandler: pipe closed: numRead=%u", - static_cast(numRead)); - } else { - trace("OutputHandler: read failed: " - "ret=%d lastError=0x%x numRead=%u", - ret, - static_cast(GetLastError()), - static_cast(numRead)); - } - break; - } - if (!writeAll(m_outputfd, &buffer[0], numRead)) { - break; - } - } - m_threadCompleted = 1; - m_completionWakeup.set(); -} diff --git a/deps/winpty/src/unix-adapter/OutputHandler.h b/deps/winpty/src/unix-adapter/OutputHandler.h deleted file mode 100644 index 48241c553..000000000 --- a/deps/winpty/src/unix-adapter/OutputHandler.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNIX_ADAPTER_OUTPUT_HANDLER_H -#define UNIX_ADAPTER_OUTPUT_HANDLER_H - -#include -#include -#include - -#include "WakeupFd.h" - -// Connect winpty CONOUT/CONERR to a Cygwin blocking fd. -class OutputHandler { -public: - OutputHandler(HANDLE conout, int outputfd, WakeupFd &completionWakeup); - ~OutputHandler() { shutdown(); } - bool isComplete() { return m_threadCompleted; } - void shutdown(); - -private: - static void *threadProcS(void *pvthis) { - reinterpret_cast(pvthis)->threadProc(); - return NULL; - } - void threadProc(); - - HANDLE m_conout; - int m_outputfd; - pthread_t m_thread; - WakeupFd &m_completionWakeup; - bool m_threadHasBeenJoined; - volatile sig_atomic_t m_threadCompleted; -}; - -#endif // UNIX_ADAPTER_OUTPUT_HANDLER_H diff --git a/deps/winpty/src/unix-adapter/Util.cc b/deps/winpty/src/unix-adapter/Util.cc deleted file mode 100644 index e13f84a52..000000000 --- a/deps/winpty/src/unix-adapter/Util.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "Util.h" - -#include -#include -#include -#include -#include - -#include "../shared/DebugClient.h" - -// Write the entire buffer, restarting it as necessary. -bool writeAll(int fd, const void *buffer, size_t size) { - size_t written = 0; - while (written < size) { - int ret = write(fd, - reinterpret_cast(buffer) + written, - size - written); - if (ret == -1 && errno == EINTR) { - continue; - } - if (ret <= 0) { - trace("write failed: " - "fd=%d errno=%d size=%u written=%d ret=%d", - fd, - errno, - static_cast(size), - static_cast(written), - ret); - return false; - } - assert(static_cast(ret) <= size - written); - written += ret; - } - assert(written == size); - return true; -} - -bool writeStr(int fd, const char *str) { - return writeAll(fd, str, strlen(str)); -} - -void selectWrapper(const char *diagName, int nfds, fd_set *readfds) { - int ret = select(nfds, readfds, NULL, NULL, NULL); - if (ret < 0) { - if (errno == EINTR) { - FD_ZERO(readfds); - return; - } -#ifdef WINPTY_TARGET_MSYS1 - // The select system call sometimes fails with EAGAIN instead of EINTR. - // This apparantly only happens with the old Cygwin fork "MSYS" used in - // the mingw.org project. select is not supposed to fail with EAGAIN, - // and EAGAIN does not make much sense as an error code. (The whole - // point of select is to block.) - if (errno == EAGAIN) { - trace("%s select returned EAGAIN: interpreting like EINTR", - diagName); - FD_ZERO(readfds); - return; - } -#endif - fprintf(stderr, "Internal error: %s select failed: " - "error %d", diagName, errno); - abort(); - } -} diff --git a/deps/winpty/src/unix-adapter/Util.h b/deps/winpty/src/unix-adapter/Util.h deleted file mode 100644 index cadb4c82a..000000000 --- a/deps/winpty/src/unix-adapter/Util.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNIX_ADAPTER_UTIL_H -#define UNIX_ADAPTER_UTIL_H - -#include -#include - -bool writeAll(int fd, const void *buffer, size_t size); -bool writeStr(int fd, const char *str); -void selectWrapper(const char *diagName, int nfds, fd_set *readfds); - -#endif // UNIX_ADAPTER_UTIL_H diff --git a/deps/winpty/src/unix-adapter/WakeupFd.cc b/deps/winpty/src/unix-adapter/WakeupFd.cc deleted file mode 100644 index 6b4737901..000000000 --- a/deps/winpty/src/unix-adapter/WakeupFd.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#include "WakeupFd.h" - -#include -#include -#include -#include -#include - -static void setFdNonBlock(int fd) { - int status = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, status | O_NONBLOCK); -} - -WakeupFd::WakeupFd() { - int pipeFd[2]; - if (pipe(pipeFd) != 0) { - perror("Could not create internal wakeup pipe"); - abort(); - } - m_pipeReadFd = pipeFd[0]; - m_pipeWriteFd = pipeFd[1]; - setFdNonBlock(m_pipeReadFd); - setFdNonBlock(m_pipeWriteFd); -} - -WakeupFd::~WakeupFd() { - close(m_pipeReadFd); - close(m_pipeWriteFd); -} - -void WakeupFd::set() { - char dummy = 0; - int ret; - do { - ret = write(m_pipeWriteFd, &dummy, 1); - } while (ret < 0 && errno == EINTR); -} - -void WakeupFd::reset() { - char tmpBuf[256]; - while (true) { - int amount = read(m_pipeReadFd, tmpBuf, sizeof(tmpBuf)); - if (amount < 0 && errno == EAGAIN) { - break; - } else if (amount <= 0) { - perror("error reading from internal wakeup pipe"); - abort(); - } - } -} diff --git a/deps/winpty/src/unix-adapter/WakeupFd.h b/deps/winpty/src/unix-adapter/WakeupFd.h deleted file mode 100644 index dd8d362aa..000000000 --- a/deps/winpty/src/unix-adapter/WakeupFd.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -#ifndef UNIX_ADAPTER_WAKEUP_FD_H -#define UNIX_ADAPTER_WAKEUP_FD_H - -class WakeupFd { -public: - WakeupFd(); - ~WakeupFd(); - int fd() { return m_pipeReadFd; } - void set(); - void reset(); - -private: - // Do not allow copying the WakeupFd object. - WakeupFd(const WakeupFd &other); - WakeupFd &operator=(const WakeupFd &other); - -private: - int m_pipeReadFd; - int m_pipeWriteFd; -}; - -#endif // UNIX_ADAPTER_WAKEUP_FD_H diff --git a/deps/winpty/src/unix-adapter/main.cc b/deps/winpty/src/unix-adapter/main.cc deleted file mode 100644 index 992cb70e4..000000000 --- a/deps/winpty/src/unix-adapter/main.cc +++ /dev/null @@ -1,729 +0,0 @@ -// Copyright (c) 2011-2015 Ryan Prichard -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. - -// MSYS's sys/cygwin.h header only declares cygwin_internal if WINVER is -// defined, which is defined in windows.h. Therefore, include windows.h early. -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include "../shared/DebugClient.h" -#include "../shared/UnixCtrlChars.h" -#include "../shared/WinptyVersion.h" -#include "InputHandler.h" -#include "OutputHandler.h" -#include "Util.h" -#include "WakeupFd.h" - -#define CSI "\x1b[" - -static WakeupFd *g_mainWakeup = NULL; - -static WakeupFd &mainWakeup() -{ - if (g_mainWakeup == NULL) { - static const char msg[] = "Internal error: g_mainWakeup is NULL\r\n"; - write(STDERR_FILENO, msg, sizeof(msg) - 1); - abort(); - } - return *g_mainWakeup; -} - -struct SavedTermiosMode { - int count; - bool valid[3]; - termios mode[3]; -}; - -// Put the input terminal into non-canonical mode. -static SavedTermiosMode setRawTerminalMode( - bool allowNonTtys, bool setStdout, bool setStderr) -{ - SavedTermiosMode ret; - const char *const kNames[3] = { "stdin", "stdout", "stderr" }; - - ret.valid[0] = true; - ret.valid[1] = setStdout; - ret.valid[2] = setStderr; - - for (int i = 0; i < 3; ++i) { - if (!ret.valid[i]) { - continue; - } - if (!isatty(i)) { - ret.valid[i] = false; - if (!allowNonTtys) { - fprintf(stderr, "%s is not a tty\n", kNames[i]); - exit(1); - } - } else { - ret.valid[i] = true; - if (tcgetattr(i, &ret.mode[i]) < 0) { - perror("tcgetattr failed"); - exit(1); - } - } - } - - if (ret.valid[STDIN_FILENO]) { - termios buf; - if (tcgetattr(STDIN_FILENO, &buf) < 0) { - perror("tcgetattr failed"); - exit(1); - } - buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - buf.c_cflag &= ~(CSIZE | PARENB); - buf.c_cflag |= CS8; - buf.c_cc[VMIN] = 1; // blocking read - buf.c_cc[VTIME] = 0; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &buf) < 0) { - fprintf(stderr, "tcsetattr failed\n"); - exit(1); - } - } - - for (int i = STDOUT_FILENO; i <= STDERR_FILENO; ++i) { - if (!ret.valid[i]) { - continue; - } - termios buf; - if (tcgetattr(i, &buf) < 0) { - perror("tcgetattr failed"); - exit(1); - } - buf.c_cflag &= ~(CSIZE | PARENB); - buf.c_cflag |= CS8; - buf.c_oflag &= ~OPOST; - if (tcsetattr(i, TCSAFLUSH, &buf) < 0) { - fprintf(stderr, "tcsetattr failed\n"); - exit(1); - } - } - - return ret; -} - -static void restoreTerminalMode(const SavedTermiosMode &original) -{ - for (int i = 0; i < 3; ++i) { - if (!original.valid[i]) { - continue; - } - if (tcsetattr(i, TCSAFLUSH, &original.mode[i]) < 0) { - perror("error restoring terminal mode"); - exit(1); - } - } -} - -static void debugShowKey(bool allowNonTtys) -{ - printf("\nPress any keys -- Ctrl-D exits\n\n"); - const SavedTermiosMode saved = - setRawTerminalMode(allowNonTtys, false, false); - char buf[128]; - while (true) { - const ssize_t len = read(STDIN_FILENO, buf, sizeof(buf)); - if (len <= 0) { - break; - } - for (int i = 0; i < len; ++i) { - char ctrl = decodeUnixCtrlChar(buf[i]); - if (ctrl == '\0') { - putchar(buf[i]); - } else { - putchar('^'); - putchar(ctrl); - } - } - for (int i = 0; i < len; ++i) { - unsigned char uch = buf[i]; - printf("\t%3d %04o 0x%02x\n", uch, uch, uch); - fflush(stdout); - } - if (buf[0] == 4) { - // Ctrl-D - break; - } - } - restoreTerminalMode(saved); -} - -static void terminalResized(int signo) -{ - mainWakeup().set(); -} - -static void registerResizeSignalHandler() -{ - struct sigaction resizeSigAct; - memset(&resizeSigAct, 0, sizeof(resizeSigAct)); - resizeSigAct.sa_handler = terminalResized; - resizeSigAct.sa_flags = SA_RESTART; - sigaction(SIGWINCH, &resizeSigAct, NULL); -} - -// Convert the path to a Win32 path if it is a POSIX path, and convert slashes -// to backslashes. -static std::string convertPosixPathToWin(const std::string &path) -{ - char *tmp; -#if defined(CYGWIN_VERSION_CYGWIN_CONV) && \ - CYGWIN_VERSION_API_MINOR >= CYGWIN_VERSION_CYGWIN_CONV - // MSYS2 and versions of Cygwin released after 2009 or so use this API. - // The original MSYS still lacks this API. - ssize_t newSize = cygwin_conv_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, - path.c_str(), NULL, 0); - assert(newSize >= 0); - tmp = new char[newSize + 1]; - ssize_t success = cygwin_conv_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, - path.c_str(), tmp, newSize + 1); - assert(success == 0); -#else - // In the current Cygwin header file, this API is documented as deprecated - // because it's restricted to paths of MAX_PATH length. In the CVS version - // of MSYS, the newer API doesn't exist, and this older API is implemented - // using msys_p2w, which seems like it would handle paths larger than - // MAX_PATH, but there's no way to query how large the new path is. - // Hopefully, this is large enough. - tmp = new char[MAX_PATH + path.size()]; - cygwin_conv_to_win32_path(path.c_str(), tmp); -#endif - for (int i = 0; tmp[i] != '\0'; ++i) { - if (tmp[i] == '/') - tmp[i] = '\\'; - } - std::string ret(tmp); - delete [] tmp; - return ret; -} - -static std::string resolvePath(const std::string &path) -{ - char ret[PATH_MAX]; - ret[0] = '\0'; - if (realpath(path.c_str(), ret) != ret) { - return std::string(); - } - return ret; -} - -template -static bool endsWith(const std::string &path, const char (&suf)[N]) -{ - const size_t suffixLen = N - 1; - char actualSuf[N]; - if (path.size() < suffixLen) { - return false; - } - strcpy(actualSuf, &path.c_str()[path.size() - suffixLen]); - for (size_t i = 0; i < suffixLen; ++i) { - actualSuf[i] = tolower(actualSuf[i]); - } - return !strcmp(actualSuf, suf); -} - -static std::string findProgram( - const char *winptyProgName, - const std::string &prog) -{ - std::string candidate; - if (prog.find('/') == std::string::npos && - prog.find('\\') == std::string::npos) { - // XXX: It would be nice to use a lambda here (once/if old MSYS support - // is dropped). - // Search the PATH. - const char *const pathVar = getenv("PATH"); - const std::string pathList(pathVar ? pathVar : ""); - size_t elpos = 0; - while (true) { - const size_t elend = pathList.find(':', elpos); - candidate = pathList.substr(elpos, elend - elpos); - if (!candidate.empty() && *(candidate.end() - 1) != '/') { - candidate += '/'; - } - candidate += prog; - candidate = resolvePath(candidate); - if (!candidate.empty()) { - int perm = X_OK; - if (endsWith(candidate, ".bat") || endsWith(candidate, ".cmd")) { -#ifdef __MSYS__ - // In MSYS/MSYS2, batch files don't have the execute bit - // set, so just check that they're readable. - perm = R_OK; -#endif - } else if (endsWith(candidate, ".com") || endsWith(candidate, ".exe")) { - // Do nothing. - } else { - // Make the exe extension explicit so that we don't try to - // run shell scripts with CreateProcess/winpty_spawn. - candidate += ".exe"; - } - if (!access(candidate.c_str(), perm)) { - break; - } - } - if (elend == std::string::npos) { - fprintf(stderr, "%s: error: cannot start '%s': Not found in PATH\n", - winptyProgName, prog.c_str()); - exit(1); - } else { - elpos = elend + 1; - } - } - } else { - candidate = resolvePath(prog); - if (candidate.empty()) { - std::string errstr(strerror(errno)); - fprintf(stderr, "%s: error: cannot start '%s': %s\n", - winptyProgName, prog.c_str(), errstr.c_str()); - exit(1); - } - } - return convertPosixPathToWin(candidate); -} - -// Convert argc/argv into a Win32 command-line following the escaping convention -// documented on MSDN. (e.g. see CommandLineToArgvW documentation) -static std::string argvToCommandLine(const std::vector &argv) -{ - std::string result; - for (size_t argIndex = 0; argIndex < argv.size(); ++argIndex) { - if (argIndex > 0) - result.push_back(' '); - const char *arg = argv[argIndex].c_str(); - const bool quote = - strchr(arg, ' ') != NULL || - strchr(arg, '\t') != NULL || - *arg == '\0'; - if (quote) - result.push_back('\"'); - int bsCount = 0; - for (const char *p = arg; *p != '\0'; ++p) { - if (*p == '\\') { - bsCount++; - } else if (*p == '\"') { - result.append(bsCount * 2 + 1, '\\'); - result.push_back('\"'); - bsCount = 0; - } else { - result.append(bsCount, '\\'); - bsCount = 0; - result.push_back(*p); - } - } - if (quote) { - result.append(bsCount * 2, '\\'); - result.push_back('\"'); - } else { - result.append(bsCount, '\\'); - } - } - return result; -} - -static wchar_t *heapMbsToWcs(const char *text) -{ - // Calling mbstowcs with a NULL first argument seems to be broken on MSYS. - // Instead of returning the size of the converted string, it returns 0. - // Using strlen(text) * 2 is probably big enough. - size_t maxLen = strlen(text) * 2 + 1; - wchar_t *ret = new wchar_t[maxLen]; - size_t len = mbstowcs(ret, text, maxLen); - assert(len != (size_t)-1 && len < maxLen); - return ret; -} - -static char *heapWcsToMbs(const wchar_t *text) -{ - // Calling wcstombs with a NULL first argument seems to be broken on MSYS. - // Instead of returning the size of the converted string, it returns 0. - // Using wcslen(text) * 3 is big enough for UTF-8 and probably other - // encodings. For UTF-8, codepoints that fit in a single wchar - // (U+0000 to U+FFFF) are encoded using 1-3 bytes. The remaining code - // points needs two wchar's and are encoded using 4 bytes. - size_t maxLen = wcslen(text) * 3 + 1; - char *ret = new char[maxLen]; - size_t len = wcstombs(ret, text, maxLen); - if (len == (size_t)-1 || len >= maxLen) { - delete [] ret; - return NULL; - } else { - return ret; - } -} - -static std::string wcsToMbs(const wchar_t *text) -{ - std::string ret; - const char *ptr = heapWcsToMbs(text); - if (ptr != NULL) { - ret = ptr; - delete [] ptr; - } - return ret; -} - -void setupWin32Environment() -{ - std::map varsToCopy; - const char *vars[] = { - "WINPTY_DEBUG", - "WINPTY_SHOW_CONSOLE", - NULL - }; - for (int i = 0; vars[i] != NULL; ++i) { - const char *cstr = getenv(vars[i]); - if (cstr != NULL && cstr[0] != '\0') { - varsToCopy[vars[i]] = cstr; - } - } - -#if defined(__MSYS__) && CYGWIN_VERSION_API_MINOR >= 48 || \ - !defined(__MSYS__) && CYGWIN_VERSION_API_MINOR >= 153 - // Use CW_SYNC_WINENV to copy the Unix environment to the Win32 - // environment. The command performs special translation on some variables - // (such as PATH and TMP). It also copies the debugging environment - // variables. - // - // Note that the API minor versions have diverged in Cygwin and MSYS. - // CW_SYNC_WINENV was added to Cygwin in version 153. (Cygwin's - // include/cygwin/version.h says that CW_SETUP_WINENV was added in 153. - // The flag was renamed 8 days after it was added, but the API docs weren't - // updated.) The flag was added to MSYS in version 48. - // - // Also, in my limited testing, this call seems to be necessary with Cygwin - // but unnecessary with MSYS. Perhaps MSYS is automatically syncing the - // Unix environment with the Win32 environment before starting console.exe? - // It shouldn't hurt to call it for MSYS. - cygwin_internal(CW_SYNC_WINENV); -#endif - - // Copy debugging environment variables from the Cygwin environment - // to the Win32 environment so the agent will inherit it. - for (std::map::iterator it = varsToCopy.begin(); - it != varsToCopy.end(); - ++it) { - wchar_t *nameW = heapMbsToWcs(it->first.c_str()); - wchar_t *valueW = heapMbsToWcs(it->second.c_str()); - SetEnvironmentVariableW(nameW, valueW); - delete [] nameW; - delete [] valueW; - } - - // Clear the TERM variable. The child process's immediate console/terminal - // environment is a Windows console, not the terminal that winpty is - // communicating with. Leaving the TERM variable set can break programs in - // various ways. (e.g. arrows keys broken in Cygwin less, IronPython's - // help(...) function doesn't start, misc programs decide they should - // output color escape codes on pre-Win10). See - // https://github.com/rprichard/winpty/issues/43. - SetEnvironmentVariableW(L"TERM", NULL); -} - -static void usage(const char *program, int exitCode) -{ - printf("Usage: %s [options] [--] program [args]\n", program); - printf("\n"); - printf("Options:\n"); - printf(" -h, --help Show this help message\n"); - printf(" --mouse Enable terminal mouse input\n"); - printf(" --showkey Dump STDIN escape sequences\n"); - printf(" --version Show the winpty version number\n"); - exit(exitCode); -} - -struct Arguments { - std::vector childArgv; - bool mouseInput; - bool testAllowNonTtys; - bool testConerr; - bool testPlainOutput; - bool testColorEscapes; -}; - -static void parseArguments(int argc, char *argv[], Arguments &out) -{ - out.mouseInput = false; - out.testAllowNonTtys = false; - out.testConerr = false; - out.testPlainOutput = false; - out.testColorEscapes = false; - bool doShowKeys = false; - const char *const program = argc >= 1 ? argv[0] : ""; - int argi = 1; - while (argi < argc) { - std::string arg(argv[argi++]); - if (arg.size() >= 1 && arg[0] == '-') { - if (arg == "-h" || arg == "--help") { - usage(program, 0); - } else if (arg == "--mouse") { - out.mouseInput = true; - } else if (arg == "--showkey") { - doShowKeys = true; - } else if (arg == "--version") { - dumpVersionToStdout(); - exit(0); - } else if (arg == "-Xallow-non-tty") { - out.testAllowNonTtys = true; - } else if (arg == "-Xconerr") { - out.testConerr = true; - } else if (arg == "-Xplain") { - out.testPlainOutput = true; - } else if (arg == "-Xcolor") { - out.testColorEscapes = true; - } else if (arg == "--") { - break; - } else { - fprintf(stderr, "Error: unrecognized option: '%s'\n", - arg.c_str()); - exit(1); - } - } else { - out.childArgv.push_back(arg); - break; - } - } - for (; argi < argc; ++argi) { - out.childArgv.push_back(argv[argi]); - } - if (doShowKeys) { - debugShowKey(out.testAllowNonTtys); - exit(0); - } - if (out.childArgv.size() == 0) { - usage(program, 1); - } -} - -static std::string errorMessageToString(DWORD err) -{ - // Use FormatMessageW rather than FormatMessageA, because we want to use - // wcstombs to convert to the Cygwin locale, which might not match the - // codepage FormatMessageA would use. We need to convert using wcstombs, - // rather than print using %ls, because %ls doesn't work in the original - // MSYS. - wchar_t *wideMsgPtr = NULL; - const DWORD formatRet = FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(&wideMsgPtr), - 0, - NULL); - if (formatRet == 0 || wideMsgPtr == NULL) { - return std::string(); - } - std::string msg = wcsToMbs(wideMsgPtr); - LocalFree(wideMsgPtr); - const size_t pos = msg.find_last_not_of(" \r\n\t"); - if (pos == std::string::npos) { - msg.clear(); - } else { - msg.erase(pos + 1); - } - return msg; -} - -static std::string formatErrorMessage(DWORD err) -{ - char buf[64]; - sprintf(buf, "error %#x", static_cast(err)); - std::string ret = errorMessageToString(err); - if (ret.empty()) { - ret += buf; - } else { - ret += " ("; - ret += buf; - ret += ")"; - } - return ret; -} - -int main(int argc, char *argv[]) -{ - setlocale(LC_ALL, ""); - - g_mainWakeup = new WakeupFd(); - - Arguments args; - parseArguments(argc, argv, args); - - setupWin32Environment(); - - winsize sz = { 0 }; - sz.ws_col = 80; - sz.ws_row = 25; - ioctl(STDIN_FILENO, TIOCGWINSZ, &sz); - - DWORD agentFlags = WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION; - if (args.testConerr) { agentFlags |= WINPTY_FLAG_CONERR; } - if (args.testPlainOutput) { agentFlags |= WINPTY_FLAG_PLAIN_OUTPUT; } - if (args.testColorEscapes) { agentFlags |= WINPTY_FLAG_COLOR_ESCAPES; } - winpty_config_t *agentCfg = winpty_config_new(agentFlags, NULL); - assert(agentCfg != NULL); - winpty_config_set_initial_size(agentCfg, sz.ws_col, sz.ws_row); - if (args.mouseInput) { - winpty_config_set_mouse_mode(agentCfg, WINPTY_MOUSE_MODE_FORCE); - } - - winpty_error_ptr_t openErr = NULL; - winpty_t *wp = winpty_open(agentCfg, &openErr); - if (wp == NULL) { - fprintf(stderr, "Error creating winpty: %s\n", - wcsToMbs(winpty_error_msg(openErr)).c_str()); - exit(1); - } - winpty_config_free(agentCfg); - winpty_error_free(openErr); - - HANDLE conin = CreateFileW(winpty_conin_name(wp), GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, 0, NULL); - HANDLE conout = CreateFileW(winpty_conout_name(wp), GENERIC_READ, 0, NULL, - OPEN_EXISTING, 0, NULL); - assert(conin != INVALID_HANDLE_VALUE); - assert(conout != INVALID_HANDLE_VALUE); - HANDLE conerr = NULL; - if (args.testConerr) { - conerr = CreateFileW(winpty_conerr_name(wp), GENERIC_READ, 0, NULL, - OPEN_EXISTING, 0, NULL); - assert(conerr != INVALID_HANDLE_VALUE); - } - - HANDLE childHandle = NULL; - - { - // Start the child process under the console. - args.childArgv[0] = findProgram(argv[0], args.childArgv[0]); - std::string cmdLine = argvToCommandLine(args.childArgv); - wchar_t *cmdLineW = heapMbsToWcs(cmdLine.c_str()); - - winpty_spawn_config_t *spawnCfg = winpty_spawn_config_new( - WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, - NULL, cmdLineW, NULL, NULL, NULL); - assert(spawnCfg != NULL); - - winpty_error_ptr_t spawnErr = NULL; - DWORD lastError = 0; - BOOL spawnRet = winpty_spawn(wp, spawnCfg, &childHandle, NULL, - &lastError, &spawnErr); - winpty_spawn_config_free(spawnCfg); - - if (!spawnRet) { - winpty_result_t spawnCode = winpty_error_code(spawnErr); - if (spawnCode == WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED) { - fprintf(stderr, "%s: error: cannot start '%s': %s\n", - argv[0], - cmdLine.c_str(), - formatErrorMessage(lastError).c_str()); - } else { - fprintf(stderr, "%s: error: cannot start '%s': internal error: %s\n", - argv[0], - cmdLine.c_str(), - wcsToMbs(winpty_error_msg(spawnErr)).c_str()); - } - exit(1); - } - winpty_error_free(spawnErr); - delete [] cmdLineW; - } - - registerResizeSignalHandler(); - SavedTermiosMode mode = - setRawTerminalMode(args.testAllowNonTtys, true, args.testConerr); - - InputHandler inputHandler(conin, STDIN_FILENO, mainWakeup()); - OutputHandler outputHandler(conout, STDOUT_FILENO, mainWakeup()); - OutputHandler *errorHandler = NULL; - if (args.testConerr) { - errorHandler = new OutputHandler(conerr, STDERR_FILENO, mainWakeup()); - } - - while (true) { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(mainWakeup().fd(), &readfds); - selectWrapper("main thread", mainWakeup().fd() + 1, &readfds); - mainWakeup().reset(); - - // Check for terminal resize. - { - winsize sz2; - ioctl(STDIN_FILENO, TIOCGWINSZ, &sz2); - if (memcmp(&sz, &sz2, sizeof(sz)) != 0) { - sz = sz2; - winpty_set_size(wp, sz.ws_col, sz.ws_row, NULL); - } - } - - // Check for an I/O handler shutting down (possibly indicating that the - // child process has exited). - if (inputHandler.isComplete() || outputHandler.isComplete() || - (errorHandler != NULL && errorHandler->isComplete())) { - break; - } - } - - // Kill the agent connection. This will kill the agent, closing the CONIN - // and CONOUT pipes on the agent pipe, prompting our I/O handler to shut - // down. - winpty_free(wp); - - inputHandler.shutdown(); - outputHandler.shutdown(); - CloseHandle(conin); - CloseHandle(conout); - - if (errorHandler != NULL) { - errorHandler->shutdown(); - delete errorHandler; - CloseHandle(conerr); - } - - restoreTerminalMode(mode); - - DWORD exitCode = 0; - if (!GetExitCodeProcess(childHandle, &exitCode)) { - exitCode = 1; - } - CloseHandle(childHandle); - return exitCode; -} diff --git a/deps/winpty/src/unix-adapter/subdir.mk b/deps/winpty/src/unix-adapter/subdir.mk deleted file mode 100644 index 200193a1b..000000000 --- a/deps/winpty/src/unix-adapter/subdir.mk +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2011-2015 Ryan Prichard -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -ALL_TARGETS += build/$(UNIX_ADAPTER_EXE) - -$(eval $(call def_unix_target,unix-adapter,)) - -UNIX_ADAPTER_OBJECTS = \ - build/unix-adapter/unix-adapter/InputHandler.o \ - build/unix-adapter/unix-adapter/OutputHandler.o \ - build/unix-adapter/unix-adapter/Util.o \ - build/unix-adapter/unix-adapter/WakeupFd.o \ - build/unix-adapter/unix-adapter/main.o \ - build/unix-adapter/shared/DebugClient.o \ - build/unix-adapter/shared/WinptyAssert.o \ - build/unix-adapter/shared/WinptyVersion.o - -build/unix-adapter/shared/WinptyVersion.o : build/gen/GenVersion.h - -build/$(UNIX_ADAPTER_EXE) : $(UNIX_ADAPTER_OBJECTS) build/winpty.dll - $(info Linking $@) - @$(UNIX_CXX) $(UNIX_LDFLAGS) -o $@ $^ - --include $(UNIX_ADAPTER_OBJECTS:.o=.d) diff --git a/deps/winpty/src/winpty.gyp b/deps/winpty/src/winpty.gyp deleted file mode 100644 index 0d753ff48..000000000 --- a/deps/winpty/src/winpty.gyp +++ /dev/null @@ -1,236 +0,0 @@ -{ - # The MSVC generator is the default. Select the compiler version by - # passing -G msvs_version= to gyp. is a string like 2013e. - # See gyp\pylib\gyp\MSVSVersion.py for sample version strings. You - # can also pass configurations.gypi to gyp for 32-bit and 64-bit builds. - # See that file for details. - # - # Pass --format=make to gyp to generate a Makefile instead. The Makefile - # can be configured by passing variables to make, e.g.: - # make -j4 CXX=i686-w64-mingw32-g++ LDFLAGS="-static -static-libgcc -static-libstdc++" - - 'variables': { - 'WINPTY_COMMIT_HASH%': '= 18309 (instead of winpty). Note that ConPTY is available from + * build 17134 but is too unstable to enable by default. + * + * @deprecated This option is ignored and will be removed in a future version. + * https://github.com/microsoft/node-pty/issues/871 + */ useConpty?: boolean; useConptyDll?: boolean; conptyInheritCursor?: boolean; diff --git a/src/native.d.ts b/src/native.d.ts index c53e086b4..720e239ec 100644 --- a/src/native.d.ts +++ b/src/native.d.ts @@ -10,14 +10,6 @@ interface IConptyNative { kill(ptyId: number, useConptyDll: boolean): void; } -interface IWinptyNative { - startProcess(file: string, commandLine: string, env: string[], cwd: string, cols: number, rows: number, debug: boolean): IWinptyProcess; - resize(pid: number, cols: number, rows: number): void; - kill(pid: number, innerPid: number): void; - getProcessList(pid: number): number[]; - getExitCode(innerPid: number): number; -} - interface IUnixNative { fork(file: string, args: string[], parsedEnv: string[], cwd: string, cols: number, rows: number, uid: number, gid: number, useUtf8: boolean, helperPath: string, onExitCallback: (code: number, signal: number) => void): IUnixProcess; open(cols: number, rows: number): IUnixOpenProcess; @@ -32,15 +24,6 @@ interface IConptyProcess { conout: string; } -interface IWinptyProcess { - pty: number; - fd: number; - conin: string; - conout: string; - pid: number; - innerPid: number; -} - interface IUnixProcess { fd: number; pid: number; diff --git a/src/terminal.test.ts b/src/terminal.test.ts index 253bd6835..c9e55177e 100644 --- a/src/terminal.test.ts +++ b/src/terminal.test.ts @@ -4,15 +4,15 @@ */ import * as assert from 'assert'; -import { WindowsTerminal } from './windowsTerminal'; -import { UnixTerminal } from './unixTerminal'; import { Terminal } from './terminal'; import { Socket } from 'net'; -const terminalConstructor = (process.platform === 'win32') ? WindowsTerminal : UnixTerminal; +const terminalConstructor = (process.platform === 'win32') + ? require('./windowsTerminal').WindowsTerminal + : require('./unixTerminal').UnixTerminal; const SHELL = (process.platform === 'win32') ? 'cmd.exe' : '/bin/bash'; -let terminalCtor: WindowsTerminal | UnixTerminal; +let terminalCtor: any; // Will be WindowsTerminal | UnixTerminal depending on conditional report if (process.platform === 'win32') { terminalCtor = require('./windowsTerminal'); } else { diff --git a/src/unixTerminal.test.ts b/src/unixTerminal.test.ts index 9b69fd3bd..63f1fc3c9 100644 --- a/src/unixTerminal.test.ts +++ b/src/unixTerminal.test.ts @@ -3,7 +3,6 @@ * Copyright (c) 2018, Microsoft Corporation (MIT License). */ -import { UnixTerminal } from './unixTerminal'; import * as assert from 'assert'; import * as cp from 'child_process'; import * as path from 'path'; @@ -12,10 +11,15 @@ import * as fs from 'fs'; import { constants } from 'os'; import { pollUntil } from './testUtils.test'; import { pid } from 'process'; +import type { UnixTerminal as UnixTerminalType } from './unixTerminal'; const FIXTURES_PATH = path.normalize(path.join(__dirname, '..', 'fixtures', 'utf8-character.txt')); if (process.platform !== 'win32') { + // Dynamic require to avoid loading pty.node on Windows + // eslint-disable-next-line @typescript-eslint/naming-convention + const { UnixTerminal } = require('./unixTerminal') as { UnixTerminal: typeof UnixTerminalType }; + describe('UnixTerminal', () => { describe('Constructor', () => { it('should set a valid pts name', () => { @@ -75,7 +79,7 @@ if (process.platform !== 'win32') { }); describe('open', () => { - let term: UnixTerminal; + let term: UnixTerminalType; afterEach(() => { if (term) { @@ -259,7 +263,7 @@ if (process.platform !== 'win32') { if (process.platform === 'linux') { it('should not leak pty file descriptors to child processes', (done) => { // Spawn 3 ptys - the 3rd should not see FDs from the first two - const ptys: UnixTerminal[] = []; + const ptys: UnixTerminalType[] = []; for (let i = 0; i < 3; i++) { ptys.push(new UnixTerminal('/bin/bash', [], {})); } @@ -348,7 +352,7 @@ if (process.platform !== 'win32') { fs.statSync(`/proc/${sub}/fd/${readFd}`); done('not reachable'); } catch (error) { - assert.notStrictEqual(error.message.indexOf('ENOENT'), -1); + assert.notStrictEqual((error as NodeJS.ErrnoException).message.indexOf('ENOENT'), -1); } setTimeout(() => { process.kill(parseInt(sub), 'SIGINT'); // SIGINT to child diff --git a/src/win/conpty.cc b/src/win/conpty.cc index 7b286d3d6..633102d7f 100644 --- a/src/win/conpty.cc +++ b/src/win/conpty.cc @@ -230,7 +230,6 @@ HRESULT CreateNamedPipesAndPseudoConsole(const Napi::CallbackInfo& info, { // Failed to find CreatePseudoConsole in kernel32. This is likely because // the user is not running a build of Windows that supports that API. - // We should fall back to winpty in this case. return HRESULT_FROM_WIN32(GetLastError()); } } else { @@ -238,7 +237,7 @@ HRESULT CreateNamedPipesAndPseudoConsole(const Napi::CallbackInfo& info, } // Failed to find kernel32. This is realy unlikely - honestly no idea how - // this is even possible to hit. But if it does happen, fall back to winpty. + // this is even possible to hit. return HRESULT_FROM_WIN32(GetLastError()); } diff --git a/src/win/winpty.cc b/src/win/winpty.cc deleted file mode 100644 index 3996f8d66..000000000 --- a/src/win/winpty.cc +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Copyright (c) 2013-2015, Christopher Jeffrey, Peter Sunde (MIT License) - * Copyright (c) 2016, Daniel Imms (MIT License). - * Copyright (c) 2018, Microsoft Corporation (MIT License). - * - * pty.cc: - * This file is responsible for starting processes - * with pseudo-terminal file descriptors. - */ - -#define NODE_ADDON_API_DISABLE_DEPRECATED -#include -#include -#include -#include -#include // PathCombine, PathIsRelative -#include -#include -#include -#include -#include -#include - -#include "path_util.h" - -/** -* Misc -*/ -#define WINPTY_DBG_VARIABLE TEXT("WINPTYDBG") - -/** -* winpty -*/ -static std::vector ptyHandles; -static volatile LONG ptyCounter; - -/** -* Helpers -*/ - -/** Keeps track of the handles created by PtyStartProcess */ -static std::map createdHandles; - -static winpty_t *get_pipe_handle(DWORD pid) { - for (size_t i = 0; i < ptyHandles.size(); ++i) { - winpty_t *ptyHandle = ptyHandles[i]; - HANDLE current = winpty_agent_process(ptyHandle); - if (GetProcessId(current) == pid) { - return ptyHandle; - } - } - return nullptr; -} - -static bool remove_pipe_handle(DWORD pid) { - for (size_t i = 0; i < ptyHandles.size(); ++i) { - winpty_t *ptyHandle = ptyHandles[i]; - HANDLE current = winpty_agent_process(ptyHandle); - if (GetProcessId(current) == pid) { - winpty_free(ptyHandle); - ptyHandles.erase(ptyHandles.begin() + i); - ptyHandle = nullptr; - return true; - } - } - return false; -} - -Napi::Error error_with_winpty_msg(const char *generalMsg, winpty_error_ptr_t error_ptr, Napi::Env env) { - std::string why; - why += generalMsg; - why += ": "; - why += path_util::wstring_to_string(winpty_error_msg(error_ptr)); - winpty_error_free(error_ptr); - return Napi::Error::New(env, why); -} - -static Napi::Value PtyGetExitCode(const Napi::CallbackInfo& info) { - Napi::Env env(info.Env()); - Napi::HandleScope scope(env); - - if (info.Length() != 1 || - !info[0].IsNumber()) { - throw Napi::Error::New(env, "Usage: pty.getExitCode(pid)"); - } - - DWORD pid = info[0].As().Uint32Value(); - HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (handle == NULL) { - return Napi::Number::New(env, -1); - } - - DWORD exitCode = 0; - BOOL success = GetExitCodeProcess(handle, &exitCode); - if (success == FALSE) { - exitCode = -1; - } - - CloseHandle(handle); - return Napi::Number::New(env, exitCode); -} - -static Napi::Value PtyGetProcessList(const Napi::CallbackInfo& info) { - Napi::Env env(info.Env()); - Napi::HandleScope scope(env); - - if (info.Length() != 1 || - !info[0].IsNumber()) { - throw Napi::Error::New(env, "Usage: pty.getProcessList(pid)"); - } - - DWORD pid = info[0].As().Uint32Value(); - winpty_t *pc = get_pipe_handle(pid); - if (pc == nullptr) { - return Napi::Number::New(env, 0); - } - int processList[64]; - const int processCount = 64; - int actualCount = winpty_get_console_process_list(pc, processList, processCount, nullptr); - if (actualCount <= 0) { - return Napi::Number::New(env, 0); - } - Napi::Array result = Napi::Array::New(env, actualCount); - for (int i = 0; i < actualCount; i++) { - result.Set(i, Napi::Number::New(env, processList[i])); - } - return result; -} - -static Napi::Value PtyStartProcess(const Napi::CallbackInfo& info) { - Napi::Env env(info.Env()); - Napi::HandleScope scope(env); - - if (info.Length() != 7 || - !info[0].IsString() || - !info[1].IsString() || - !info[2].IsArray() || - !info[3].IsString() || - !info[4].IsNumber() || - !info[5].IsNumber() || - !info[6].IsBoolean()) { - throw Napi::Error::New(env, "Usage: pty.startProcess(file, cmdline, env, cwd, cols, rows, debug)"); - } - - std::wstring filename(path_util::to_wstring(info[0].As())); - std::wstring cmdline(path_util::to_wstring(info[1].As())); - std::wstring cwd(path_util::to_wstring(info[3].As())); - - // create environment block - std::wstring envStr; - const Napi::Array envValues = info[2].As(); - if (!envValues.IsEmpty()) { - std::wstring envBlock; - for(uint32_t i = 0; i < envValues.Length(); i++) { - envBlock += path_util::to_wstring(envValues.Get(i).As()); - envBlock += L'\0'; - } - envStr = std::move(envBlock); - } - - // use environment 'Path' variable to determine location of - // the relative path that we have recieved (e.g cmd.exe) - std::wstring shellpath; - if (::PathIsRelativeW(filename.c_str())) { - shellpath = path_util::get_shell_path(filename); - } else { - shellpath = filename; - } - - if (shellpath.empty() || !path_util::file_exists(shellpath)) { - std::string why; - why += "File not found: "; - why += path_util::wstring_to_string(shellpath); - throw Napi::Error::New(env, why); - } - - int cols = info[4].As().Int32Value(); - int rows = info[5].As().Int32Value(); - bool debug = info[6].As().Value(); - - // Enable/disable debugging - SetEnvironmentVariable(WINPTY_DBG_VARIABLE, debug ? "1" : NULL); // NULL = deletes variable - - // Create winpty config - winpty_error_ptr_t error_ptr = nullptr; - winpty_config_t* winpty_config = winpty_config_new(0, &error_ptr); - if (winpty_config == nullptr) { - throw error_with_winpty_msg("Error creating WinPTY config", error_ptr, env); - } - winpty_error_free(error_ptr); - - // Set pty size on config - winpty_config_set_initial_size(winpty_config, cols, rows); - - // Start the pty agent - winpty_t *pc = winpty_open(winpty_config, &error_ptr); - winpty_config_free(winpty_config); - if (pc == nullptr) { - throw error_with_winpty_msg("Error launching WinPTY agent", error_ptr, env); - } - winpty_error_free(error_ptr); - - // Create winpty spawn config - winpty_spawn_config_t* config = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, shellpath.c_str(), cmdline.c_str(), cwd.c_str(), envStr.c_str(), &error_ptr); - if (config == nullptr) { - winpty_free(pc); - throw error_with_winpty_msg("Error creating WinPTY spawn config", error_ptr, env); - } - winpty_error_free(error_ptr); - - // Spawn the new process - HANDLE handle = nullptr; - BOOL spawnSuccess = winpty_spawn(pc, config, &handle, nullptr, nullptr, &error_ptr); - winpty_spawn_config_free(config); - if (!spawnSuccess) { - if (handle) { - CloseHandle(handle); - } - winpty_free(pc); - throw error_with_winpty_msg("Unable to start terminal process", error_ptr, env); - } - winpty_error_free(error_ptr); - - LPCWSTR coninPipeName = winpty_conin_name(pc); - std::string coninPipeNameStr(path_util::from_wstring(coninPipeName)); - if (coninPipeNameStr.empty()) { - CloseHandle(handle); - winpty_free(pc); - throw Napi::Error::New(env, "Failed to initialize winpty conin"); - } - - LPCWSTR conoutPipeName = winpty_conout_name(pc); - std::string conoutPipeNameStr(path_util::from_wstring(conoutPipeName)); - if (conoutPipeNameStr.empty()) { - CloseHandle(handle); - winpty_free(pc); - throw Napi::Error::New(env, "Failed to initialize winpty conout"); - } - - DWORD innerPid = GetProcessId(handle); - if (createdHandles[innerPid]) { - CloseHandle(handle); - winpty_free(pc); - std::stringstream why; - why << "There is already a process with innerPid " << innerPid; - throw Napi::Error::New(env, why.str()); - } - createdHandles[innerPid] = handle; - - // Save pty struct for later use - ptyHandles.push_back(pc); - - DWORD pid = GetProcessId(winpty_agent_process(pc)); - Napi::Object marshal = Napi::Object::New(env); - marshal.Set("innerPid", Napi::Number::New(env, (int)innerPid)); - marshal.Set("pid", Napi::Number::New(env, (int)pid)); - marshal.Set("pty", Napi::Number::New(env, InterlockedIncrement(&ptyCounter))); - marshal.Set("fd", Napi::Number::New(env, -1)); - marshal.Set("conin", Napi::String::New(env, coninPipeNameStr)); - marshal.Set("conout", Napi::String::New(env, conoutPipeNameStr)); - - return marshal; -} - -static Napi::Value PtyResize(const Napi::CallbackInfo& info) { - Napi::Env env(info.Env()); - Napi::HandleScope scope(env); - - if (info.Length() != 3 || - !info[0].IsNumber() || - !info[1].IsNumber() || - !info[2].IsNumber()) { - throw Napi::Error::New(env, "Usage: pty.resize(pid, cols, rows)"); - } - - DWORD pid = info[0].As().Uint32Value(); - int cols = info[1].As().Int32Value(); - int rows = info[2].As().Int32Value(); - - winpty_t *pc = get_pipe_handle(pid); - - if (pc == nullptr) { - throw Napi::Error::New(env, "The pty doesn't appear to exist"); - } - BOOL success = winpty_set_size(pc, cols, rows, nullptr); - if (!success) { - throw Napi::Error::New(env, "The pty could not be resized"); - } - - return env.Undefined(); -} - -static Napi::Value PtyKill(const Napi::CallbackInfo& info) { - Napi::Env env(info.Env()); - Napi::HandleScope scope(env); - - if (info.Length() != 2 || - !info[0].IsNumber() || - !info[1].IsNumber()) { - throw Napi::Error::New(env, "Usage: pty.kill(pid, innerPid)"); - } - - DWORD pid = info[0].As().Uint32Value(); - DWORD innerPid = info[1].As().Uint32Value(); - - winpty_t *pc = get_pipe_handle(pid); - if (pc == nullptr) { - throw Napi::Error::New(env, "Pty seems to have been killed already"); - } - - assert(remove_pipe_handle(pid)); - - HANDLE innerPidHandle = createdHandles[innerPid]; - createdHandles.erase(innerPid); - CloseHandle(innerPidHandle); - - return env.Undefined(); -} - -/** -* Init -*/ - -Napi::Object init(Napi::Env env, Napi::Object exports) { - exports.Set("startProcess", Napi::Function::New(env, PtyStartProcess)); - exports.Set("resize", Napi::Function::New(env, PtyResize)); - exports.Set("kill", Napi::Function::New(env, PtyKill)); - exports.Set("getExitCode", Napi::Function::New(env, PtyGetExitCode)); - exports.Set("getProcessList", Napi::Function::New(env, PtyGetProcessList)); - return exports; -}; - -NODE_API_MODULE(NODE_GYP_MODULE_NAME, init); diff --git a/src/windowsPtyAgent.ts b/src/windowsPtyAgent.ts index d70544495..277594d34 100644 --- a/src/windowsPtyAgent.ts +++ b/src/windowsPtyAgent.ts @@ -5,7 +5,6 @@ */ import * as fs from 'fs'; -import * as os from 'os'; import * as path from 'path'; import { fork } from 'child_process'; import { Socket } from 'net'; @@ -14,7 +13,6 @@ import { ConoutConnection } from './windowsConoutConnection'; import { loadNativeModule } from './utils'; let conptyNative: IConptyNative; -let winptyNative: IWinptyNative; /** * The amount of time to wait for additional data after the conpty shell process has exited before @@ -24,13 +22,11 @@ let winptyNative: IWinptyNative; const FLUSH_DATA_INTERVAL = 1000; /** - * This agent sits between the WindowsTerminal class and provides a common interface for both conpty - * and winpty. + * This agent sits between the WindowsTerminal class and provides an interface for conpty. */ export class WindowsPtyAgent { private _inSocket: Socket; private _outSocket: Socket; - private _pid: number = 0; private _innerPid: number = 0; private _closeTimeout: NodeJS.Timer | undefined; private _exitCode: number | undefined; @@ -38,7 +34,7 @@ export class WindowsPtyAgent { private _fd: any; private _pty: number; - private _ptyNative: IConptyNative | IWinptyNative; + private _ptyNative: IConptyNative; public get inSocket(): Socket { return this._inSocket; } public get outSocket(): Socket { return this._outSocket; } @@ -54,23 +50,13 @@ export class WindowsPtyAgent { cols: number, rows: number, debug: boolean, - private _useConpty: boolean | undefined, private _useConptyDll: boolean = false, conptyInheritCursor: boolean = false ) { - if (this._useConpty === undefined || this._useConpty === true) { - this._useConpty = this._getWindowsBuildNumber() >= 18309; + if (!conptyNative) { + conptyNative = loadNativeModule('conpty').module; } - if (this._useConpty) { - if (!conptyNative) { - conptyNative = loadNativeModule('conpty').module; - } - } else { - if (!winptyNative) { - winptyNative = loadNativeModule('pty').module; - } - } - this._ptyNative = this._useConpty ? conptyNative : winptyNative; + this._ptyNative = conptyNative; // Sanitize input variable. cwd = path.resolve(cwd); @@ -79,14 +65,7 @@ export class WindowsPtyAgent { const commandLine = argsToCommandLine(file, args); // Open pty session. - let term: IConptyProcess | IWinptyProcess; - if (this._useConpty) { - term = (this._ptyNative as IConptyNative).startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor, this._useConptyDll); - } else { - term = (this._ptyNative as IWinptyNative).startProcess(file, commandLine, env, cwd, cols, rows, debug); - this._pid = (term as IWinptyProcess).pid; - this._innerPid = (term as IWinptyProcess).innerPid; - } + const term: IConptyProcess = conptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor, this._useConptyDll); // Not available on windows. this._fd = term.fd; @@ -115,69 +94,43 @@ export class WindowsPtyAgent { }); this._inSocket.setEncoding('utf8'); - if (this._useConpty) { - const connect = (this._ptyNative as IConptyNative).connect(this._pty, commandLine, cwd, env, this._useConptyDll, c => this._$onProcessExit(c)); - this._innerPid = connect.pid; - } + const connect = conptyNative.connect(this._pty, commandLine, cwd, env, this._useConptyDll, c => this._$onProcessExit(c)); + this._innerPid = connect.pid; } public resize(cols: number, rows: number): void { - if (this._useConpty) { - if (this._exitCode !== undefined) { - throw new Error('Cannot resize a pty that has already exited'); - } - (this._ptyNative as IConptyNative).resize(this._pty, cols, rows, this._useConptyDll); - return; + if (this._exitCode !== undefined) { + throw new Error('Cannot resize a pty that has already exited'); } - (this._ptyNative as IWinptyNative).resize(this._pid, cols, rows); + this._ptyNative.resize(this._pty, cols, rows, this._useConptyDll); } public clear(): void { - if (this._useConpty) { - (this._ptyNative as IConptyNative).clear(this._pty, this._useConptyDll); - } + this._ptyNative.clear(this._pty, this._useConptyDll); } public kill(): void { // Tell the agent to kill the pty, this releases handles to the process - if (this._useConpty) { - if (!this._useConptyDll) { - this._inSocket.readable = false; - this._outSocket.readable = false; - this._getConsoleProcessList().then(consoleProcessList => { - consoleProcessList.forEach((pid: number) => { - try { - process.kill(pid); - } catch (e) { - // Ignore if process cannot be found (kill ESRCH error) - } - }); - }); - (this._ptyNative as IConptyNative).kill(this._pty, this._useConptyDll); - this._conoutSocketWorker.dispose(); - } else { - // Close the input write handle to signal the end of session. - this._inSocket.destroy(); - (this._ptyNative as IConptyNative).kill(this._pty, this._useConptyDll); - this._outSocket.on('data', () => { - this._conoutSocketWorker.dispose(); + if (!this._useConptyDll) { + this._inSocket.readable = false; + this._outSocket.readable = false; + this._getConsoleProcessList().then(consoleProcessList => { + consoleProcessList.forEach((pid: number) => { + try { + process.kill(pid); + } catch (e) { + // Ignore if process cannot be found (kill ESRCH error) + } }); - } + }); + this._ptyNative.kill(this._pty, this._useConptyDll); + this._conoutSocketWorker.dispose(); } else { - // Because pty.kill closes the handle, it will kill most processes by itself. - // Process IDs can be reused as soon as all handles to them are - // dropped, so we want to immediately kill the entire console process list. - // If we do not force kill all processes here, node servers in particular - // seem to become detached and remain running (see - // Microsoft/vscode#26807). - const processList: number[] = (this._ptyNative as IWinptyNative).getProcessList(this._pid); - (this._ptyNative as IWinptyNative).kill(this._pid, this._innerPid); - processList.forEach(pid => { - try { - process.kill(pid); - } catch (e) { - // Ignore if process cannot be found (kill ESRCH error) - } + // Close the input write handle to signal the end of session. + this._inSocket.destroy(); + this._ptyNative.kill(this._pty, this._useConptyDll); + this._outSocket.on('data', () => { + this._conoutSocketWorker.dispose(); }); } } @@ -198,20 +151,7 @@ export class WindowsPtyAgent { } public get exitCode(): number | undefined { - if (this._useConpty) { - return this._exitCode; - } - const winptyExitCode = (this._ptyNative as IWinptyNative).getExitCode(this._innerPid); - return winptyExitCode === -1 ? undefined : winptyExitCode; - } - - private _getWindowsBuildNumber(): number { - const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); - let buildNumber: number = 0; - if (osVersion && osVersion.length === 4) { - buildNumber = parseInt(osVersion[3]); - } - return buildNumber; + return this._exitCode; } private _generatePipeName(): string { diff --git a/src/windowsTerminal.test.ts b/src/windowsTerminal.test.ts index 8f1274edf..29f0411d1 100644 --- a/src/windowsTerminal.test.ts +++ b/src/windowsTerminal.test.ts @@ -92,18 +92,18 @@ function pollForProcessTreeSize(pid: number, size: number, intervalMs: number = } if (process.platform === 'win32') { - [[false, false], [true, false], [true, true]].forEach(([useConpty, useConptyDll]) => { - describe(`WindowsTerminal (useConpty = ${useConpty}, useConptyDll = ${useConptyDll})`, () => { + [false, true].forEach((useConptyDll) => { + describe(`WindowsTerminal (useConptyDll = ${useConptyDll})`, () => { describe('kill', () => { it('should not crash parent process', function (done) { this.timeout(20000); - const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', [], { useConptyDll }); term.on('exit', () => done()); term.kill(); }); it('should kill the process tree', function (done: Mocha.Done): void { this.timeout(20000); - const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', [], { useConptyDll }); // Start sub-processes term.write('powershell.exe\r'); term.write('node.exe\r'); @@ -120,16 +120,16 @@ if (process.platform === 'win32') { term.on('exit', () => { pollForProcessState(desiredState, 1000, 5000).then(() => { done(); - }); + }).catch(done); }); - }); + }).catch(done); }); }); describe('resize', () => { it('should throw a non-native exception when resizing an invalid value', function(done) { this.timeout(20000); - const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', [], { useConptyDll }); assert.throws(() => term.resize(-1, -1)); assert.throws(() => term.resize(0, 0)); assert.doesNotThrow(() => term.resize(1, 1)); @@ -140,7 +140,7 @@ if (process.platform === 'win32') { }); it('should throw a non-native exception when resizing a killed terminal', function(done) { this.timeout(20000); - const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', [], { useConptyDll }); (term)._defer(() => { term.once('exit', () => { assert.throws(() => term.resize(1, 1)); @@ -167,7 +167,7 @@ if (process.platform === 'win32') { // Skip test if git bash isn't installed return; } - const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConpty, useConptyDll }); + const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConptyDll }); let result = ''; term.on('data', (data) => { result += data; @@ -182,7 +182,7 @@ if (process.platform === 'win32') { describe('env', () => { it('should set environment variables of the shell', function (done) { this.timeout(10000); - const term = new WindowsTerminal('cmd.exe', '/C echo %FOO%', { useConpty, useConptyDll, env: { FOO: 'BAR' }}); + const term = new WindowsTerminal('cmd.exe', '/C echo %FOO%', { useConptyDll, env: { FOO: 'BAR' }}); let result = ''; term.on('data', (data) => { result += data; @@ -197,7 +197,7 @@ if (process.platform === 'win32') { describe('On close', () => { it('should return process zero exit codes', function (done) { this.timeout(10000); - const term = new WindowsTerminal('cmd.exe', '/C exit', { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', '/C exit', { useConptyDll }); term.on('exit', (code) => { assert.strictEqual(code, 0); done(); @@ -206,7 +206,7 @@ if (process.platform === 'win32') { it('should return process non-zero exit codes', function (done) { this.timeout(10000); - const term = new WindowsTerminal('cmd.exe', '/C exit 2', { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', '/C exit 2', { useConptyDll }); term.on('exit', (code) => { assert.strictEqual(code, 2); done(); @@ -217,7 +217,7 @@ if (process.platform === 'win32') { describe('Write', () => { it('should accept input', function (done) { this.timeout(10000); - const term = new WindowsTerminal('cmd.exe', '', { useConpty, useConptyDll }); + const term = new WindowsTerminal('cmd.exe', '', { useConptyDll }); term.write('exit\r'); term.on('exit', () => { done(); diff --git a/src/windowsTerminal.ts b/src/windowsTerminal.ts index 13f6c6dbb..3105e9019 100644 --- a/src/windowsTerminal.ts +++ b/src/windowsTerminal.ts @@ -48,7 +48,7 @@ export class WindowsTerminal extends Terminal { this._deferreds = []; // Create new termal. - this._agent = new WindowsPtyAgent(file, args, parsedEnv, cwd, this._cols, this._rows, false, opt.useConpty, opt.useConptyDll, opt.conptyInheritCursor); + this._agent = new WindowsPtyAgent(file, args, parsedEnv, cwd, this._cols, this._rows, false, opt.useConptyDll, opt.conptyInheritCursor); this._socket = this._agent.outSocket; // Not available until `ready` event emitted. diff --git a/test/spam-close.js b/test/spam-close.js index 3a84ce418..f9f5876a0 100644 --- a/test/spam-close.js +++ b/test/spam-close.js @@ -17,8 +17,7 @@ setInterval(() => { cols: 80, rows: 26, cwd: isWindows ? process.env.USERPROFILE : process.env.HOME, - env: Object.assign({ TEST: "Environment vars work" }, process.env), - useConpty: true + env: Object.assign({ TEST: "Environment vars work" }, process.env) }); ptyProcess.onData(data => console.log(` data: ${data.replace(/\x1b|\n|\r/g, '_')}`)); diff --git a/typings/node-pty.d.ts b/typings/node-pty.d.ts index 6f050ff1d..c16ce9240 100644 --- a/typings/node-pty.d.ts +++ b/typings/node-pty.d.ts @@ -86,13 +86,14 @@ declare module 'node-pty' { } export interface IWindowsPtyForkOptions extends IBasePtyForkOptions { - /** - * Whether to use the ConPTY system on Windows. When this is not set, ConPTY will be used when - * the Windows build number is >= 18309 (instead of winpty). Note that ConPTY is available from - * build 17134 but is too unstable to enable by default. - * - * This setting does nothing on non-Windows. - */ + /** + * Whether to use the ConPTY system on Windows. When this is not set, ConPTY will be used when + * the Windows build number is >= 18309 (instead of winpty). Note that ConPTY is available from + * build 17134 but is too unstable to enable by default. + * + * @deprecated This option is ignored and will be removed in a future version. + * https://github.com/microsoft/node-pty/issues/871 + */ useConpty?: boolean; /** @@ -111,7 +112,7 @@ declare module 'node-pty' { } /** - * An interface representing a pseudoterminal, on Windows this is emulated via the winpty library. + * An interface representing a pseudoterminal. */ export interface IPty { /**