2010-11-08 15:31:01 +10:00
|
|
|
/*
|
|
|
|
ANSI.c - ANSI escape sequence console driver.
|
|
|
|
|
|
|
|
Jason Hood, 21 & 22 October, 2005.
|
|
|
|
|
|
|
|
Derived from ANSI.xs by Jean-Louis Morel, from his Perl package
|
|
|
|
Win32::Console::ANSI. I removed the codepage conversion ("\e(") and added
|
|
|
|
WriteConsole hooking.
|
|
|
|
|
|
|
|
v1.01, 11 & 12 March, 2006:
|
|
|
|
disable when console has disabled processed output;
|
|
|
|
\e[5m (blink) is the same as \e[4m (underline);
|
|
|
|
do not conceal control characters (0 to 31);
|
|
|
|
\e[m will restore original color.
|
|
|
|
|
|
|
|
v1.10, 22 February, 2009:
|
|
|
|
fix MyWriteConsoleW for strings longer than the buffer;
|
|
|
|
initialise attributes to current;
|
|
|
|
hook into child processes.
|
|
|
|
|
|
|
|
v1.11, 28 February, 2009:
|
|
|
|
fix hooking into child processes (only do console executables).
|
|
|
|
|
|
|
|
v1.12, 9 March, 2009:
|
|
|
|
really fix hooking (I didn't realise MinGW didn't generate relocations).
|
|
|
|
|
|
|
|
v1.13, 21 & 27 March, 2009:
|
|
|
|
alternate injection method, to work with DEP;
|
|
|
|
use Unicode and the current output code page (not OEMCP).
|
|
|
|
|
|
|
|
v1.14, 3 April, 2009:
|
|
|
|
fix test for empty import section.
|
|
|
|
|
|
|
|
v1.15, 17 May, 2009:
|
|
|
|
properly update lpNumberOfCharsWritten in MyWriteConsoleA.
|
|
|
|
|
|
|
|
v1.20, 26 & 29 May, 17 to 21 June, 2009:
|
|
|
|
create an ANSICON environment variable;
|
|
|
|
hook GetEnvironmentVariable to create ANSICON dynamically;
|
|
|
|
use another injection method.
|
|
|
|
|
|
|
|
v1.22, 5 October, 2009:
|
|
|
|
hook LoadLibrary to intercept the newly loaded functions.
|
|
|
|
|
|
|
|
v1.23, 11 November, 2009:
|
|
|
|
unload gracefully;
|
|
|
|
conceal characters by making foreground same as background;
|
|
|
|
reverse the bold/underline attributes, too.
|
|
|
|
|
|
|
|
v1.25, 15, 20 & 21 July, 2010:
|
|
|
|
hook LoadLibraryEx (now cscript works);
|
|
|
|
Win7 support.
|
|
|
|
|
|
|
|
v1.30, 3 August to 7 September, 2010:
|
|
|
|
x64 support.
|
2010-11-13 14:49:27 +10:00
|
|
|
|
2010-11-19 15:50:10 +10:00
|
|
|
v1.31, 13 & 19 November, 2010:
|
2010-11-13 14:49:27 +10:00
|
|
|
fix multibyte conversion problems.
|
2010-12-04 15:19:36 +10:00
|
|
|
|
2010-12-22 18:47:45 +10:00
|
|
|
v1.32, 4 to 22 December, 2010:
|
2010-12-12 21:58:35 +10:00
|
|
|
test for lpNumberOfCharsWritten/lpNumberOfBytesWritten being NULL;
|
|
|
|
recognise DSR and xterm window title;
|
2010-12-16 16:00:56 +10:00
|
|
|
ignore sequences starting with \e[? & \e[>;
|
|
|
|
close the handles opened by CreateProcess.
|
2011-02-26 01:12:35 +10:00
|
|
|
|
2011-03-01 21:01:37 +10:00
|
|
|
v1.40, 25 & 26 February, 1 March, 2011:
|
2011-02-26 17:14:21 +10:00
|
|
|
hook GetProcAddress, addresses issues with .NET (work with PowerShell);
|
|
|
|
implement SO & SI to use the DEC Special Graphics Character Set (enables
|
2011-03-01 21:01:37 +10:00
|
|
|
line drawing via ASCII); ignore \e(X & \e)X (where X is any character);
|
|
|
|
add \e[?25h & \e[?25l to show/hide the cursor (DECTCEM).
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
v1.50, 7 to 14 December, 2011:
|
|
|
|
added dynamic environment variable ANSICON_VER to return version;
|
|
|
|
read ANSICON_EXC environment variable to exclude selected modules;
|
|
|
|
read ANSICON_GUI environment variable to hook selected GUI programs;
|
|
|
|
read ANSICON_DEF environment variable to set the default GR;
|
|
|
|
transfer current GR to child, read it on exit.
|
2012-02-24 12:53:07 +10:00
|
|
|
|
|
|
|
v1.51, 15 January, 5, 22 & 24 February, 2012:
|
|
|
|
added log mask 16 to log all the imported modules of imported modules;
|
|
|
|
ignore the version within the core API DLL names;
|
|
|
|
fix 32-bit process trying to identify 64-bit process;
|
|
|
|
hook _lwrite & _hwrite.
|
2012-04-10 15:39:58 +10:00
|
|
|
|
2012-06-02 17:20:21 +10:00
|
|
|
v1.52, 10 April, 1 & 2 June, 2012:
|
2012-06-01 23:42:58 +10:00
|
|
|
use ansicon.exe to enable 32-bit to inject into 64-bit;
|
2012-06-02 17:20:21 +10:00
|
|
|
implement \e[39m & \e[49m (only setting color, nothing else);
|
|
|
|
added the character/line equivalents (keaj`) of the cursor movement
|
|
|
|
sequences (ABCDG), as well as vertical absolute (d) and erase characters
|
|
|
|
(X).
|
2012-06-12 14:38:00 +10:00
|
|
|
|
|
|
|
v1.53, 12 June, 2012:
|
|
|
|
fixed Update_GRM when running multiple processes (e.g. "cl /MP").
|
2012-11-24 23:41:29 +10:00
|
|
|
|
|
|
|
v1.60, 22 to 24 November, 2012:
|
|
|
|
alternative method to obtain LLW for 64->32 injection;
|
|
|
|
support for VC6 (remove section pragma, rename isdigit to is_digit).
|
2013-02-14 18:12:13 +10:00
|
|
|
|
|
|
|
v1.61, 14 February, 2013:
|
|
|
|
go back to using ANSI-LLW.exe for 64->32 injection.
|
2013-07-19 00:14:54 +10:00
|
|
|
|
|
|
|
v1.62, 17 & 18 July, 2013:
|
|
|
|
another method to obtain LLW for 64->32 injection.
|
2013-08-02 23:21:07 +10:00
|
|
|
|
|
|
|
v1.64, 2 August, 2013:
|
|
|
|
better method of determining a console handle (see IsConsoleHandle).
|
2013-09-04 19:37:55 +10:00
|
|
|
|
|
|
|
v1.65, 28 August, 2013:
|
|
|
|
fix \e[K (was using window, not buffer).
|
2014-01-25 23:43:41 +10:00
|
|
|
|
2014-02-05 00:21:42 +10:00
|
|
|
v1.66, 20 & 21 September, 2013:
|
2014-01-25 23:43:41 +10:00
|
|
|
fix 32-bit process trying to detect 64-bit process.
|
|
|
|
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
v1.70, 25 January to 26 February, 2014:
|
2014-01-25 23:43:41 +10:00
|
|
|
don't hook ourself from LoadLibrary or LoadLibraryEx;
|
2014-01-27 14:03:53 +10:00
|
|
|
update the LoadLibraryEx flags that should not cause hooking;
|
2014-02-08 01:10:51 +10:00
|
|
|
inject by manipulating the import directory table; for 64-bit AnyCPU use
|
|
|
|
ntdll's LdrLoadDll via CreateRemoteThread;
|
2014-02-08 12:04:43 +10:00
|
|
|
restore original attributes on detach (for LoadLibrary/FreeLibrary usage);
|
2014-02-08 01:10:51 +10:00
|
|
|
log: remove the quotes around the CreateProcess command line string and
|
2014-02-08 18:30:53 +10:00
|
|
|
distinguish NULL and "" args;
|
2014-02-10 16:33:42 +10:00
|
|
|
attributes (and saved position) are local to each console window;
|
|
|
|
exclude entire programs, by not using an extension in ANSICON_EXC;
|
|
|
|
hook modules injected via CreateRemoteThread+LoadLibrary;
|
|
|
|
hook all modules loaded due to LoadLibrary, not just the specified;
|
2014-02-18 21:34:39 +10:00
|
|
|
don't hook a module that's already hooked us;
|
|
|
|
better parsing of escape & CSI sequences;
|
|
|
|
ignore xterm 38 & 48 SGR values;
|
2014-02-20 18:06:28 +10:00
|
|
|
change G1 blank from space to U+00A0 - No-Break Space;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
use window height, not buffer;
|
|
|
|
added more sequences;
|
|
|
|
don't add a newline immediately after a wrap;
|
|
|
|
restore cursor visibility on unload.
|
2015-10-23 07:49:33 -05:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
v1.71, 23 October, 2015:
|
|
|
|
add _CRT_NON_CONFORMING_WCSTOK define for VS2015.
|
|
|
|
|
|
|
|
v1.72, 14 to 24 December, 2015:
|
|
|
|
recognize the standard handle defines in WriteFile;
|
|
|
|
minor speed improvement by caching GetConsoleMode;
|
|
|
|
keep track of three handles (ostensibly stdout, stderr and a file);
|
|
|
|
test a DOS header exists before writing to e_oemid;
|
|
|
|
more flexible/robust handling of data directories;
|
|
|
|
files writing to the console will always succeed;
|
|
|
|
log: use API file functions and a custom printf;
|
|
|
|
add a blank line between processes;
|
|
|
|
set function name for MyWriteConsoleA;
|
|
|
|
scan imports from "kernel32" (without extension);
|
|
|
|
added dynamic environment variable CLICOLOR;
|
|
|
|
removed _hwrite (it's the same address as _lwrite);
|
|
|
|
join multibyte characters split across separate writes;
|
|
|
|
remove wcstok, avoiding potential interference with the host;
|
|
|
|
similarly, use a private heap instead of malloc.
|
2017-10-26 21:46:53 +10:00
|
|
|
|
2017-10-28 11:19:06 +10:00
|
|
|
v1.80, 26 to 28 October, 2017:
|
|
|
|
fix unloading;
|
2017-10-28 12:31:35 +10:00
|
|
|
revert back to (re)storing buffer cursor position;
|
|
|
|
increase cache to five handles.
|
2010-11-08 15:31:01 +10:00
|
|
|
*/
|
|
|
|
|
2010-12-12 21:58:35 +10:00
|
|
|
#include "ansicon.h"
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
#include "version.h"
|
2010-11-08 15:31:01 +10:00
|
|
|
#include <tlhelp32.h>
|
2010-11-15 21:51:38 +10:00
|
|
|
|
2012-11-24 23:41:29 +10:00
|
|
|
#define is_digit(c) ('0' <= (c) && (c) <= '9')
|
2010-11-08 15:31:01 +10:00
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
// ========== Global variables and constants
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
HANDLE hConOut; // handle to CONOUT$
|
|
|
|
WORD orgattr; // original attributes
|
|
|
|
DWORD orgmode; // original mode
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
CONSOLE_CURSOR_INFO orgcci; // original cursor state
|
2017-07-25 18:18:34 +10:00
|
|
|
HANDLE hHeap; // local memory heap
|
|
|
|
|
2017-10-28 12:31:35 +10:00
|
|
|
#define CACHE 5
|
2017-07-25 18:18:34 +10:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
HANDLE h;
|
|
|
|
DWORD mode;
|
|
|
|
} cache[CACHE];
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2010-12-12 21:58:35 +10:00
|
|
|
#define ESC '\x1B' // ESCape character
|
|
|
|
#define BEL '\x07'
|
2011-02-26 17:14:21 +10:00
|
|
|
#define SO '\x0E' // Shift Out
|
|
|
|
#define SI '\x0F' // Shift In
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
#define MAX_ARG 16 // max number of args in an escape sequence
|
|
|
|
int state; // automata state
|
2010-12-12 21:58:35 +10:00
|
|
|
TCHAR prefix; // escape sequence prefix ( '[', ']' or '(' );
|
|
|
|
TCHAR prefix2; // secondary prefix ( '?' or '>' );
|
2010-11-08 15:31:01 +10:00
|
|
|
TCHAR suffix; // escape sequence suffix
|
2014-02-18 21:34:39 +10:00
|
|
|
TCHAR suffix2; // escape sequence secondary suffix
|
2010-11-08 15:31:01 +10:00
|
|
|
int es_argc; // escape sequence args count
|
|
|
|
int es_argv[MAX_ARG]; // escape sequence args
|
2010-12-12 21:58:35 +10:00
|
|
|
TCHAR Pt_arg[MAX_PATH*2]; // text parameter for Operating System Command
|
|
|
|
int Pt_len;
|
2011-02-26 17:14:21 +10:00
|
|
|
BOOL shifted;
|
2014-02-20 18:06:28 +10:00
|
|
|
int screen_top = -1; // initial window top when cleared
|
2011-02-26 17:14:21 +10:00
|
|
|
|
|
|
|
|
|
|
|
// DEC Special Graphics Character Set from
|
|
|
|
// http://vt100.net/docs/vt220-rm/table2-4.html
|
|
|
|
// Some of these may not look right, depending on the font and code page (in
|
|
|
|
// particular, the Control Pictures probably won't work at all).
|
|
|
|
const WCHAR G1[] =
|
|
|
|
{
|
2014-02-18 21:34:39 +10:00
|
|
|
L'\x00a0', // _ - No-Break Space
|
2011-02-26 17:14:21 +10:00
|
|
|
L'\x2666', // ` - Black Diamond Suit
|
|
|
|
L'\x2592', // a - Medium Shade
|
|
|
|
L'\x2409', // b - HT
|
|
|
|
L'\x240c', // c - FF
|
|
|
|
L'\x240d', // d - CR
|
|
|
|
L'\x240a', // e - LF
|
|
|
|
L'\x00b0', // f - Degree Sign
|
|
|
|
L'\x00b1', // g - Plus-Minus Sign
|
|
|
|
L'\x2424', // h - NL
|
|
|
|
L'\x240b', // i - VT
|
|
|
|
L'\x2518', // j - Box Drawings Light Up And Left
|
|
|
|
L'\x2510', // k - Box Drawings Light Down And Left
|
|
|
|
L'\x250c', // l - Box Drawings Light Down And Right
|
|
|
|
L'\x2514', // m - Box Drawings Light Up And Right
|
|
|
|
L'\x253c', // n - Box Drawings Light Vertical And Horizontal
|
|
|
|
L'\x00af', // o - SCAN 1 - Macron
|
|
|
|
L'\x25ac', // p - SCAN 3 - Black Rectangle
|
|
|
|
L'\x2500', // q - SCAN 5 - Box Drawings Light Horizontal
|
|
|
|
L'_', // r - SCAN 7 - Low Line
|
|
|
|
L'_', // s - SCAN 9 - Low Line
|
|
|
|
L'\x251c', // t - Box Drawings Light Vertical And Right
|
|
|
|
L'\x2524', // u - Box Drawings Light Vertical And Left
|
|
|
|
L'\x2534', // v - Box Drawings Light Up And Horizontal
|
|
|
|
L'\x252c', // w - Box Drawings Light Down And Horizontal
|
|
|
|
L'\x2502', // x - Box Drawings Light Vertical
|
|
|
|
L'\x2264', // y - Less-Than Or Equal To
|
|
|
|
L'\x2265', // z - Greater-Than Or Equal To
|
|
|
|
L'\x03c0', // { - Greek Small Letter Pi
|
|
|
|
L'\x2260', // | - Not Equal To
|
|
|
|
L'\x00a3', // } - Pound Sign
|
|
|
|
L'\x00b7', // ~ - Middle Dot
|
|
|
|
};
|
|
|
|
|
|
|
|
#define FIRST_G1 '_'
|
|
|
|
#define LAST_G1 '~'
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
// color constants
|
|
|
|
|
|
|
|
#define FOREGROUND_BLACK 0
|
|
|
|
#define FOREGROUND_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE
|
|
|
|
|
|
|
|
#define BACKGROUND_BLACK 0
|
|
|
|
#define BACKGROUND_WHITE BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
const BYTE foregroundcolor[8] =
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
FOREGROUND_BLACK, // black foreground
|
|
|
|
FOREGROUND_RED, // red foreground
|
|
|
|
FOREGROUND_GREEN, // green foreground
|
|
|
|
FOREGROUND_RED | FOREGROUND_GREEN, // yellow foreground
|
|
|
|
FOREGROUND_BLUE, // blue foreground
|
|
|
|
FOREGROUND_BLUE | FOREGROUND_RED, // magenta foreground
|
|
|
|
FOREGROUND_BLUE | FOREGROUND_GREEN, // cyan foreground
|
|
|
|
FOREGROUND_WHITE // white foreground
|
|
|
|
};
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
const BYTE backgroundcolor[8] =
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
BACKGROUND_BLACK, // black background
|
|
|
|
BACKGROUND_RED, // red background
|
|
|
|
BACKGROUND_GREEN, // green background
|
|
|
|
BACKGROUND_RED | BACKGROUND_GREEN, // yellow background
|
|
|
|
BACKGROUND_BLUE, // blue background
|
|
|
|
BACKGROUND_BLUE | BACKGROUND_RED, // magenta background
|
|
|
|
BACKGROUND_BLUE | BACKGROUND_GREEN, // cyan background
|
|
|
|
BACKGROUND_WHITE, // white background
|
|
|
|
};
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
const BYTE attr2ansi[8] = // map console attribute to ANSI number
|
|
|
|
{
|
|
|
|
0, // black
|
|
|
|
4, // blue
|
|
|
|
2, // green
|
|
|
|
6, // cyan
|
|
|
|
1, // red
|
|
|
|
5, // magenta
|
|
|
|
3, // yellow
|
|
|
|
7 // white
|
|
|
|
};
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
BYTE foreground; // ANSI base color (0 to 7; add 30)
|
|
|
|
BYTE background; // ANSI base color (0 to 7; add 40)
|
|
|
|
BYTE bold; // console FOREGROUND_INTENSITY bit
|
|
|
|
BYTE underline; // console BACKGROUND_INTENSITY bit
|
|
|
|
BYTE rvideo; // swap foreground/bold & background/underline
|
|
|
|
BYTE concealed; // set foreground/bold to background/underline
|
|
|
|
BYTE reverse; // swap console foreground & background attributes
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
BYTE crm; // showing control characters?
|
2014-02-08 18:30:53 +10:00
|
|
|
COORD SavePos; // saved cursor position
|
|
|
|
} STATE, *PSTATE;
|
|
|
|
|
|
|
|
PSTATE pState;
|
|
|
|
HANDLE hMap;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO );
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
void get_state( void )
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
TCHAR buf[64];
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL init;
|
|
|
|
HANDLE hConOut;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
static STATE state; // on the odd chance file mapping fails
|
|
|
|
|
|
|
|
if (pState != NULL)
|
|
|
|
return;
|
2012-06-12 14:38:00 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
hwnd = GetConsoleWindow();
|
|
|
|
if (hwnd == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wsprintf( buf, L"ANSICON_State_%X", PtrToUint( hwnd ) );
|
|
|
|
hMap = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
|
|
|
0, sizeof(STATE), buf );
|
|
|
|
if (hMap == NULL)
|
|
|
|
{
|
|
|
|
no_go:
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "File mapping failed (%u) - using default state",
|
2014-02-08 18:30:53 +10:00
|
|
|
GetLastError() );
|
|
|
|
pState = &state;
|
|
|
|
goto do_init;
|
|
|
|
}
|
|
|
|
init = (GetLastError() != ERROR_ALREADY_EXISTS);
|
2012-06-12 14:38:00 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
pState = MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
|
|
|
|
if (pState == NULL)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
CloseHandle( hMap );
|
2017-07-25 18:18:34 +10:00
|
|
|
hMap = NULL;
|
2014-02-08 18:30:53 +10:00
|
|
|
goto no_go;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
if (init)
|
|
|
|
{
|
|
|
|
do_init:
|
|
|
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
2017-07-25 18:18:34 +10:00
|
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
2014-02-08 18:30:53 +10:00
|
|
|
if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Failed to get screen buffer info (%u) - assuming defaults",
|
|
|
|
GetLastError() );
|
2014-02-08 18:30:53 +10:00
|
|
|
csbi.wAttributes = 7;
|
|
|
|
csbi.dwSize.X = 80;
|
|
|
|
csbi.dwSize.Y = 300;
|
|
|
|
csbi.srWindow.Left = 0;
|
|
|
|
csbi.srWindow.Right = 79;
|
|
|
|
csbi.srWindow.Top = 0;
|
|
|
|
csbi.srWindow.Bottom = 24;
|
|
|
|
}
|
|
|
|
if (GetEnvironmentVariable( L"ANSICON_REVERSE", NULL, 0 ))
|
|
|
|
{
|
|
|
|
SetEnvironmentVariable( L"ANSICON_REVERSE", NULL );
|
|
|
|
pState->reverse = TRUE;
|
|
|
|
pState->foreground = attr2ansi[(csbi.wAttributes >> 4) & 7];
|
|
|
|
pState->background = attr2ansi[csbi.wAttributes & 7];
|
|
|
|
pState->bold = (csbi.wAttributes & BACKGROUND_INTENSITY) >> 4;
|
|
|
|
pState->underline = (csbi.wAttributes & FOREGROUND_INTENSITY) << 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pState->foreground = attr2ansi[csbi.wAttributes & 7];
|
|
|
|
pState->background = attr2ansi[(csbi.wAttributes >> 4) & 7];
|
|
|
|
pState->bold = csbi.wAttributes & FOREGROUND_INTENSITY;
|
|
|
|
pState->underline = csbi.wAttributes & BACKGROUND_INTENSITY;
|
|
|
|
}
|
|
|
|
if (!GetEnvironmentVariable( L"ANSICON_DEF", NULL, 0 ))
|
|
|
|
{
|
|
|
|
TCHAR def[4];
|
|
|
|
LPTSTR a = def;
|
|
|
|
if (pState->reverse)
|
|
|
|
{
|
|
|
|
*a++ = '-';
|
|
|
|
csbi.wAttributes = ((csbi.wAttributes >> 4) & 15)
|
|
|
|
| ((csbi.wAttributes & 15) << 4);
|
|
|
|
}
|
|
|
|
wsprintf( a, L"%X", csbi.wAttributes & 255 );
|
|
|
|
SetEnvironmentVariable( L"ANSICON_DEF", def );
|
|
|
|
}
|
|
|
|
set_ansicon( &csbi );
|
|
|
|
CloseHandle( hConOut );
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
// Search an environment variable for a string.
|
|
|
|
BOOL search_env( LPCTSTR var, LPCTSTR val )
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
static LPTSTR env;
|
|
|
|
static DWORD env_len;
|
2017-07-25 18:18:34 +10:00
|
|
|
DWORD len;
|
|
|
|
BOOL not;
|
|
|
|
LPTSTR end;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
len = GetEnvironmentVariable( var, env, env_len );
|
|
|
|
if (len == 0)
|
|
|
|
return FALSE;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (len > env_len)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
LPTSTR tmp = (env == NULL) ? HeapAlloc( hHeap, 0, TSIZE(len) )
|
|
|
|
: HeapReAlloc( hHeap, 0, env, TSIZE(len) );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (tmp == NULL)
|
|
|
|
return FALSE;
|
|
|
|
env = tmp;
|
2017-07-25 18:18:34 +10:00
|
|
|
env_len = (DWORD)HeapSize( hHeap, 0, env );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
GetEnvironmentVariable( var, env, env_len );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
not = (*env == '!');
|
|
|
|
if (not && env[1] == '\0')
|
|
|
|
return TRUE;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
end = env + not;
|
|
|
|
while (*end != '\0')
|
|
|
|
{
|
|
|
|
var = end;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (*end++ == ';')
|
|
|
|
{
|
|
|
|
end[-1] = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (*end != '\0');
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (_wcsicmp( val, var ) == 0)
|
|
|
|
return !not;
|
2017-07-25 18:18:34 +10:00
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
return not;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
// ========== Print Buffer functions
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
#define BUFFER_SIZE 2048
|
2011-02-26 17:14:21 +10:00
|
|
|
|
|
|
|
int nCharInBuffer;
|
|
|
|
WCHAR ChBuffer[BUFFER_SIZE];
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
WCHAR ChPrev;
|
|
|
|
BOOL fWrapped;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// FlushBuffer()
|
|
|
|
// Writes the buffer to the console and empties it.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void FlushBuffer( void )
|
|
|
|
{
|
|
|
|
DWORD nWritten;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
if (nCharInBuffer <= 0) return;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
|
|
|
|
if (pState->crm)
|
|
|
|
{
|
|
|
|
DWORD mode;
|
|
|
|
GetConsoleMode( hConOut, &mode );
|
|
|
|
SetConsoleMode( hConOut, mode & ~ENABLE_PROCESSED_OUTPUT );
|
|
|
|
WriteConsole( hConOut, ChBuffer, nCharInBuffer, &nWritten, NULL );
|
|
|
|
SetConsoleMode( hConOut, mode );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HANDLE hConWrap;
|
|
|
|
CONSOLE_CURSOR_INFO cci;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
|
|
|
|
if (nCharInBuffer < 4)
|
|
|
|
{
|
|
|
|
LPWSTR b = ChBuffer;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
WriteConsole( hConOut, b, 1, &nWritten, NULL );
|
|
|
|
if (*b != '\r' && *b != '\b' && *b != '\a')
|
|
|
|
{
|
|
|
|
GetConsoleScreenBufferInfo( hConOut, &csbi );
|
|
|
|
if (csbi.dwCursorPosition.X == 0)
|
|
|
|
fWrapped = TRUE;
|
|
|
|
}
|
|
|
|
} while (++b, --nCharInBuffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// To detect wrapping of multiple characters, create a new buffer, write
|
|
|
|
// to the top of it and see if the cursor changes line. This doesn't
|
|
|
|
// always work on the normal buffer, since if you're already on the last
|
|
|
|
// line, wrapping scrolls everything up and still leaves you on the last.
|
|
|
|
hConWrap = CreateConsoleScreenBuffer( GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
|
|
|
CONSOLE_TEXTMODE_BUFFER, NULL );
|
|
|
|
// Even though the buffer isn't visible, the cursor still shows up.
|
|
|
|
cci.dwSize = 1;
|
|
|
|
cci.bVisible = FALSE;
|
|
|
|
SetConsoleCursorInfo( hConWrap, &cci );
|
|
|
|
// Ensure the buffer is the same width (it gets created using the window
|
|
|
|
// width) and more than one line.
|
|
|
|
GetConsoleScreenBufferInfo( hConOut, &csbi );
|
|
|
|
csbi.dwSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 2;
|
|
|
|
SetConsoleScreenBufferSize( hConWrap, csbi.dwSize );
|
|
|
|
// Put the cursor on the top line, in the same column.
|
|
|
|
csbi.dwCursorPosition.Y = 0;
|
|
|
|
SetConsoleCursorPosition( hConWrap, csbi.dwCursorPosition );
|
|
|
|
WriteConsole( hConWrap, ChBuffer, nCharInBuffer, &nWritten, NULL );
|
|
|
|
GetConsoleScreenBufferInfo( hConWrap, &csbi );
|
|
|
|
if (csbi.dwCursorPosition.Y != 0)
|
|
|
|
fWrapped = TRUE;
|
|
|
|
CloseHandle( hConWrap );
|
|
|
|
WriteConsole( hConOut, ChBuffer, nCharInBuffer, &nWritten, NULL );
|
|
|
|
}
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
nCharInBuffer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2011-02-26 17:14:21 +10:00
|
|
|
// PushBuffer( WCHAR c )
|
|
|
|
// Adds a character in the buffer.
|
2010-11-08 15:31:01 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2011-02-26 17:14:21 +10:00
|
|
|
void PushBuffer( WCHAR c )
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
DWORD nWritten;
|
|
|
|
|
|
|
|
ChPrev = c;
|
|
|
|
|
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
if (pState->crm)
|
|
|
|
ChBuffer[nCharInBuffer++] = c;
|
2011-02-26 17:14:21 +10:00
|
|
|
FlushBuffer();
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
// Avoid writing the newline if wrap has already occurred.
|
|
|
|
GetConsoleScreenBufferInfo( hConOut, &csbi );
|
|
|
|
if (pState->crm)
|
|
|
|
{
|
|
|
|
// If we're displaying controls, then the only way we can be on the left
|
|
|
|
// margin is if wrap occurred.
|
|
|
|
if (csbi.dwCursorPosition.X != 0)
|
|
|
|
WriteConsole( hConOut, L"\n", 1, &nWritten, NULL );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LPCWSTR nl = L"\n";
|
|
|
|
if (fWrapped)
|
|
|
|
{
|
|
|
|
// It's wrapped, but was anything more written? Look at the current
|
|
|
|
// row, checking that each character is space in current attributes.
|
|
|
|
// If it's all blank we can drop the newline. If the cursor isn't
|
|
|
|
// already at the margin, then it was spaces or tabs that caused the
|
|
|
|
// wrap, which can be ignored and overwritten.
|
|
|
|
CHAR_INFO blank;
|
|
|
|
PCHAR_INFO row;
|
2017-07-25 18:18:34 +10:00
|
|
|
row = HeapAlloc( hHeap, 0, csbi.dwSize.X * sizeof(CHAR_INFO) );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (row != NULL)
|
|
|
|
{
|
|
|
|
COORD s, c;
|
|
|
|
SMALL_RECT r;
|
|
|
|
s.X = csbi.dwSize.X;
|
|
|
|
s.Y = 1;
|
|
|
|
c.X = c.Y = 0;
|
|
|
|
r.Left = 0;
|
|
|
|
r.Right = s.X - 1;
|
|
|
|
r.Top = r.Bottom = csbi.dwCursorPosition.Y;
|
|
|
|
ReadConsoleOutput( hConOut, row, s, c, &r );
|
|
|
|
blank.Char.UnicodeChar = ' ';
|
|
|
|
blank.Attributes = csbi.wAttributes;
|
|
|
|
while (*(PDWORD)&row[c.X] == *(PDWORD)&blank)
|
2017-07-25 18:18:34 +10:00
|
|
|
{
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (++c.X == s.X)
|
|
|
|
{
|
|
|
|
nl = (csbi.dwCursorPosition.X == 0) ? NULL : L"\r";
|
|
|
|
break;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
}
|
|
|
|
HeapFree( hHeap, 0, row );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
}
|
|
|
|
fWrapped = FALSE;
|
|
|
|
}
|
|
|
|
if (nl)
|
|
|
|
WriteConsole( hConOut, nl, 1, &nWritten, NULL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (shifted && c >= FIRST_G1 && c <= LAST_G1)
|
|
|
|
c = G1[c-FIRST_G1];
|
|
|
|
ChBuffer[nCharInBuffer] = c;
|
|
|
|
if (++nCharInBuffer == BUFFER_SIZE)
|
|
|
|
FlushBuffer();
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
2010-12-12 21:58:35 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// SendSequence( LPTSTR seq )
|
|
|
|
// Send the string to the input buffer.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SendSequence( LPTSTR seq )
|
|
|
|
{
|
|
|
|
DWORD out;
|
|
|
|
INPUT_RECORD in;
|
|
|
|
HANDLE hStdIn = GetStdHandle( STD_INPUT_HANDLE );
|
|
|
|
|
2010-12-12 23:32:22 +10:00
|
|
|
in.EventType = KEY_EVENT;
|
|
|
|
in.Event.KeyEvent.bKeyDown = TRUE;
|
|
|
|
in.Event.KeyEvent.wRepeatCount = 1;
|
|
|
|
in.Event.KeyEvent.wVirtualKeyCode = 0;
|
|
|
|
in.Event.KeyEvent.wVirtualScanCode = 0;
|
|
|
|
in.Event.KeyEvent.dwControlKeyState = 0;
|
2010-12-12 21:58:35 +10:00
|
|
|
for (; *seq; ++seq)
|
|
|
|
{
|
|
|
|
in.Event.KeyEvent.uChar.UnicodeChar = *seq;
|
|
|
|
WriteConsoleInput( hStdIn, &in, 1, &out );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
// ========== Print functions
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// InterpretEscSeq()
|
|
|
|
// Interprets the last escape sequence scanned by ParseAndPrintString
|
|
|
|
// prefix escape sequence prefix
|
|
|
|
// es_argc escape sequence args count
|
|
|
|
// es_argv[] escape sequence args array
|
|
|
|
// suffix escape sequence suffix
|
|
|
|
//
|
|
|
|
// for instance, with \e[33;45;1m we have
|
|
|
|
// prefix = '[',
|
|
|
|
// es_argc = 3, es_argv[0] = 33, es_argv[1] = 45, es_argv[2] = 1
|
|
|
|
// suffix = 'm'
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void InterpretEscSeq( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
WORD attribut;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO Info;
|
2011-03-01 21:01:37 +10:00
|
|
|
CONSOLE_CURSOR_INFO CursInfo;
|
2010-11-08 15:31:01 +10:00
|
|
|
DWORD len, NumberOfCharsWritten;
|
|
|
|
COORD Pos;
|
|
|
|
SMALL_RECT Rect;
|
|
|
|
CHAR_INFO CharInfo;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
DWORD mode;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2014-02-20 18:06:28 +10:00
|
|
|
#define WIDTH Info.dwSize.X
|
|
|
|
#define CUR Info.dwCursorPosition
|
|
|
|
#define WIN Info.srWindow
|
|
|
|
#define TOP WIN.Top
|
|
|
|
#define BOTTOM WIN.Bottom
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
#define LEFT 0
|
|
|
|
#define RIGHT (WIDTH - 1)
|
2014-02-20 18:06:28 +10:00
|
|
|
|
|
|
|
#define FillBlank( len, Pos ) \
|
|
|
|
FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten );\
|
|
|
|
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, \
|
|
|
|
&NumberOfCharsWritten )
|
|
|
|
|
2010-12-12 21:58:35 +10:00
|
|
|
if (prefix == '[')
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (prefix2 == '?' && (suffix == 'h' || suffix == 'l') && es_argc == 1)
|
2011-03-01 21:01:37 +10:00
|
|
|
{
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
switch (es_argv[0])
|
2011-03-01 21:01:37 +10:00
|
|
|
{
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
case 25:
|
|
|
|
GetConsoleCursorInfo( hConOut, &CursInfo );
|
|
|
|
CursInfo.bVisible = (suffix == 'h');
|
|
|
|
SetConsoleCursorInfo( hConOut, &CursInfo );
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
mode = ENABLE_PROCESSED_OUTPUT;
|
|
|
|
if (suffix == 'h')
|
|
|
|
mode |= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
|
|
SetConsoleMode( hConOut, mode );
|
2011-03-01 21:01:37 +10:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2014-02-18 21:34:39 +10:00
|
|
|
// Ignore any other private sequences.
|
2011-03-01 21:01:37 +10:00
|
|
|
if (prefix2 != 0)
|
|
|
|
return;
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
GetConsoleScreenBufferInfo( hConOut, &Info );
|
|
|
|
switch (suffix)
|
|
|
|
{
|
|
|
|
case 'm':
|
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 0;
|
|
|
|
for (i = 0; i < es_argc; i++)
|
|
|
|
{
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (30 <= es_argv[i] && es_argv[i] <= 37)
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->foreground = es_argv[i] - 30;
|
2014-02-18 21:34:39 +10:00
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
else if (40 <= es_argv[i] && es_argv[i] <= 47)
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->background = es_argv[i] - 40;
|
2014-02-18 21:34:39 +10:00
|
|
|
}
|
|
|
|
else if (es_argv[i] == 38 || es_argv[i] == 48)
|
|
|
|
{
|
|
|
|
// This is technically incorrect, but it's what xterm does, so
|
|
|
|
// that's what we do. According to T.416 (ISO 8613-6), there is
|
|
|
|
// only one parameter, which is divided into elements. So where
|
|
|
|
// xterm does "38;2;R;G;B" it should really be "38;2:I:R:G:B" (I is
|
|
|
|
// a colour space identifier).
|
|
|
|
if (i+1 < es_argc)
|
|
|
|
{
|
|
|
|
if (es_argv[i+1] == 2) // rgb
|
|
|
|
i += 4;
|
|
|
|
else if (es_argv[i+1] == 5) // index
|
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
else switch (es_argv[i])
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
case 0:
|
2012-06-01 23:42:58 +10:00
|
|
|
case 39:
|
|
|
|
case 49:
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
|
|
|
TCHAR def[4];
|
|
|
|
int a;
|
|
|
|
*def = '7'; def[1] = '\0';
|
|
|
|
GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) );
|
|
|
|
a = wcstol( def, NULL, 16 );
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->reverse = FALSE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (a < 0)
|
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->reverse = TRUE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
a = -a;
|
|
|
|
}
|
2012-06-01 23:42:58 +10:00
|
|
|
if (es_argv[i] != 49)
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->foreground = attr2ansi[a & 7];
|
2012-06-01 23:42:58 +10:00
|
|
|
if (es_argv[i] != 39)
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->background = attr2ansi[(a >> 4) & 7];
|
2012-06-01 23:42:58 +10:00
|
|
|
if (es_argv[i] == 0)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2012-06-01 23:42:58 +10:00
|
|
|
if (es_argc == 1)
|
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->bold = a & FOREGROUND_INTENSITY;
|
|
|
|
pState->underline = a & BACKGROUND_INTENSITY;
|
2012-06-01 23:42:58 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->bold = 0;
|
|
|
|
pState->underline = 0;
|
2012-06-01 23:42:58 +10:00
|
|
|
}
|
2014-02-08 18:30:53 +10:00
|
|
|
pState->rvideo = 0;
|
|
|
|
pState->concealed = 0;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
break;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
case 1: pState->bold = FOREGROUND_INTENSITY; break;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
case 5: // blink
|
2014-02-08 18:30:53 +10:00
|
|
|
case 4: pState->underline = BACKGROUND_INTENSITY; break;
|
|
|
|
case 7: pState->rvideo = 1; break;
|
|
|
|
case 8: pState->concealed = 1; break;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
case 21: // oops, this actually turns on double underline
|
2014-02-05 00:21:42 +10:00
|
|
|
// but xterm turns off bold too, so that's alright
|
2014-02-08 18:30:53 +10:00
|
|
|
case 22: pState->bold = 0; break;
|
2010-11-08 15:31:01 +10:00
|
|
|
case 25:
|
2014-02-08 18:30:53 +10:00
|
|
|
case 24: pState->underline = 0; break;
|
|
|
|
case 27: pState->rvideo = 0; break;
|
|
|
|
case 28: pState->concealed = 0; break;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
}
|
2014-02-08 18:30:53 +10:00
|
|
|
if (pState->concealed)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
if (pState->rvideo)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
attribut = foregroundcolor[pState->foreground]
|
|
|
|
| backgroundcolor[pState->foreground];
|
|
|
|
if (pState->bold)
|
2010-11-08 15:31:01 +10:00
|
|
|
attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
attribut = foregroundcolor[pState->background]
|
|
|
|
| backgroundcolor[pState->background];
|
|
|
|
if (pState->underline)
|
2010-11-08 15:31:01 +10:00
|
|
|
attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
|
|
|
|
}
|
|
|
|
}
|
2014-02-08 18:30:53 +10:00
|
|
|
else if (pState->rvideo)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 18:30:53 +10:00
|
|
|
attribut = foregroundcolor[pState->background]
|
|
|
|
| backgroundcolor[pState->foreground];
|
|
|
|
if (pState->bold)
|
2010-11-08 15:31:01 +10:00
|
|
|
attribut |= BACKGROUND_INTENSITY;
|
2014-02-08 18:30:53 +10:00
|
|
|
if (pState->underline)
|
2010-11-08 15:31:01 +10:00
|
|
|
attribut |= FOREGROUND_INTENSITY;
|
|
|
|
}
|
|
|
|
else
|
2014-02-08 18:30:53 +10:00
|
|
|
attribut = foregroundcolor[pState->foreground] | pState->bold
|
|
|
|
| backgroundcolor[pState->background] | pState->underline;
|
|
|
|
if (pState->reverse)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4);
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleTextAttribute( hConOut, attribut );
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[J == ESC[0J
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
switch (es_argv[0])
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
case 0: // ESC[0J erase from cursor to end of display
|
2014-02-20 18:06:28 +10:00
|
|
|
len = (BOTTOM - CUR.Y) * WIDTH + WIDTH - CUR.X;
|
|
|
|
FillBlank( len, CUR );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 1: // ESC[1J erase from start to cursor.
|
2010-11-08 15:31:01 +10:00
|
|
|
Pos.X = 0;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = TOP;
|
|
|
|
len = (CUR.Y - TOP) * WIDTH + CUR.X + 1;
|
|
|
|
FillBlank( len, Pos );
|
|
|
|
return;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 2: // ESC[2J Clear screen and home cursor
|
2014-02-20 18:06:28 +10:00
|
|
|
if (TOP != screen_top || BOTTOM == Info.dwSize.Y - 1)
|
|
|
|
{
|
|
|
|
// Rather than clearing the existing window, make the current
|
|
|
|
// line the new top of the window (assuming this is the first
|
|
|
|
// thing a program does).
|
|
|
|
int range = BOTTOM - TOP;
|
|
|
|
if (CUR.Y + range < Info.dwSize.Y)
|
|
|
|
{
|
|
|
|
TOP = CUR.Y;
|
|
|
|
BOTTOM = TOP + range;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BOTTOM = Info.dwSize.Y - 1;
|
|
|
|
TOP = BOTTOM - range;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Rect.Left = LEFT;
|
|
|
|
Rect.Right = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Rect.Top = CUR.Y - TOP;
|
|
|
|
Rect.Bottom = CUR.Y - 1;
|
|
|
|
Pos.X = Pos.Y = 0;
|
|
|
|
CharInfo.Char.UnicodeChar = ' ';
|
|
|
|
CharInfo.Attributes = Info.wAttributes;
|
|
|
|
ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Pos, &CharInfo);
|
|
|
|
}
|
|
|
|
SetConsoleWindowInfo( hConOut, TRUE, &WIN );
|
|
|
|
screen_top = TOP;
|
|
|
|
}
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = TOP;
|
|
|
|
len = (BOTTOM - TOP + 1) * WIDTH;
|
|
|
|
FillBlank( len, Pos );
|
|
|
|
// Not technically correct, but perhaps expected.
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'K':
|
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[K == ESC[0K
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
switch (es_argv[0])
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
case 0: // ESC[0K Clear to end of line
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
len = WIDTH - CUR.X;
|
2014-02-20 18:06:28 +10:00
|
|
|
FillBlank( len, CUR );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 1: // ESC[1K Clear from start of line to cursor
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y;
|
|
|
|
FillBlank( CUR.X + 1, Pos );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 2: // ESC[2K Clear whole line.
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y;
|
|
|
|
FillBlank( WIDTH, Pos );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'X': // ESC[#X Erase # characters.
|
2012-06-02 17:20:21 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
FillBlank( es_argv[0], CUR );
|
2012-06-02 17:20:21 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'L': // ESC[#L Insert # blank lines.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L
|
|
|
|
if (es_argc != 1) return;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Rect.Left = WIN.Left = LEFT;
|
|
|
|
Rect.Right = WIN.Right = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Rect.Top = CUR.Y;
|
|
|
|
Rect.Bottom = BOTTOM;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y + es_argv[0];
|
2010-11-08 15:31:01 +10:00
|
|
|
CharInfo.Char.UnicodeChar = ' ';
|
|
|
|
CharInfo.Attributes = Info.wAttributes;
|
2014-02-20 18:06:28 +10:00
|
|
|
ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
|
|
|
|
// Technically should home the cursor, but perhaps not expected.
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'M': // ESC[#M Delete # lines.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M
|
|
|
|
if (es_argc != 1) return;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Rect.Left = WIN.Left = LEFT;
|
|
|
|
Rect.Right = WIN.Right = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Rect.Bottom = BOTTOM;
|
|
|
|
Rect.Top = CUR.Y - es_argv[0];
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = TOP = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
CharInfo.Char.UnicodeChar = ' ';
|
|
|
|
CharInfo.Attributes = Info.wAttributes;
|
2014-02-20 18:06:28 +10:00
|
|
|
ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
|
|
|
|
// Technically should home the cursor, but perhaps not expected.
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'P': // ESC[#P Delete # characters.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Rect.Left = WIN.Left = CUR.X;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Rect.Right = WIN.Right = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.X = CUR.X - es_argv[0];
|
|
|
|
Pos.Y =
|
|
|
|
Rect.Top =
|
|
|
|
Rect.Bottom = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
CharInfo.Char.UnicodeChar = ' ';
|
|
|
|
CharInfo.Attributes = Info.wAttributes;
|
2014-02-20 18:06:28 +10:00
|
|
|
ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case '@': // ESC[#@ Insert # blank characters.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Rect.Left = WIN.Left = CUR.X;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Rect.Right = WIN.Right = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.X = CUR.X + es_argv[0];
|
|
|
|
Pos.Y =
|
|
|
|
Rect.Top =
|
|
|
|
Rect.Bottom = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
CharInfo.Char.UnicodeChar = ' ';
|
|
|
|
CharInfo.Attributes = Info.wAttributes;
|
2014-02-20 18:06:28 +10:00
|
|
|
ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'k': // ESC[#k
|
|
|
|
case 'A': // ESC[#A Moves cursor up # lines
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y - es_argv[0];
|
|
|
|
if (Pos.Y < TOP) Pos.Y = TOP;
|
|
|
|
Pos.X = CUR.X;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'e': // ESC[#e
|
|
|
|
case 'B': // ESC[#B Moves cursor down # lines
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y + es_argv[0];
|
|
|
|
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
|
|
|
|
Pos.X = CUR.X;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'a': // ESC[#a
|
|
|
|
case 'C': // ESC[#C Moves cursor forward # spaces
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.X = CUR.X + es_argv[0];
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'j': // ESC[#j
|
|
|
|
case 'D': // ESC[#D Moves cursor back # spaces
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.X = CUR.X - es_argv[0];
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (Pos.X < LEFT) Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'E': // ESC[#E Moves cursor down # lines, column 1.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y + es_argv[0];
|
|
|
|
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'F': // ESC[#F Moves cursor up # lines, column 1.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F
|
|
|
|
if (es_argc != 1) return;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y - es_argv[0];
|
|
|
|
if (Pos.Y < TOP) Pos.Y = TOP;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
Pos.X = LEFT;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case '`': // ESC[#`
|
|
|
|
case 'G': // ESC[#G Moves cursor column # in current row.
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
Pos.X = es_argv[0] - 1;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
|
|
|
if (Pos.X < LEFT) Pos.X = LEFT;
|
2014-02-20 18:06:28 +10:00
|
|
|
Pos.Y = CUR.Y;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'd': // ESC[#d Moves cursor row #, current column.
|
2012-06-02 17:20:21 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
Pos.Y = es_argv[0] - 1;
|
2014-02-20 18:06:28 +10:00
|
|
|
if (Pos.Y < TOP) Pos.Y = TOP;
|
|
|
|
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
|
2012-06-02 17:20:21 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'f': // ESC[#;#f
|
|
|
|
case 'H': // ESC[#;#H Moves cursor to line #, column #
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc == 0)
|
|
|
|
es_argv[es_argc++] = 1; // ESC[H == ESC[1;1H
|
|
|
|
if (es_argc == 1)
|
|
|
|
es_argv[es_argc++] = 1; // ESC[#H == ESC[#;1H
|
|
|
|
if (es_argc > 2) return;
|
|
|
|
Pos.X = es_argv[1] - 1;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (Pos.X < LEFT) Pos.X = LEFT;
|
|
|
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
2010-11-08 15:31:01 +10:00
|
|
|
Pos.Y = es_argv[0] - 1;
|
2014-02-20 18:06:28 +10:00
|
|
|
if (Pos.Y < TOP) Pos.Y = TOP;
|
|
|
|
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
|
2010-11-08 15:31:01 +10:00
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'I': // ESC[#I Moves cursor forward # tabs
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[I == ESC[1I
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
Pos.Y = CUR.Y;
|
|
|
|
Pos.X = (CUR.X & -8) + es_argv[0] * 8;
|
|
|
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'Z': // ESC[#Z Moves cursor back # tabs
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[Z == ESC[1Z
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
Pos.Y = CUR.Y;
|
|
|
|
if ((CUR.X & 7) == 0)
|
|
|
|
Pos.X = CUR.X - es_argv[0] * 8;
|
|
|
|
else
|
|
|
|
Pos.X = (CUR.X & -8) - (es_argv[0] - 1) * 8;
|
|
|
|
if (Pos.X < LEFT) Pos.X = LEFT;
|
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'b': // ESC[#b Repeat character
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[b == ESC[1b
|
|
|
|
if (es_argc != 1) return;
|
|
|
|
while (--es_argv[0] >= 0)
|
|
|
|
PushBuffer( ChPrev );
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 's': // ESC[s Saves cursor position for recall later
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc != 0) return;
|
2017-10-28 11:19:06 +10:00
|
|
|
pState->SavePos = CUR;
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'u': // ESC[u Return to saved cursor position
|
2010-11-08 15:31:01 +10:00
|
|
|
if (es_argc != 0) return;
|
2017-10-28 11:19:06 +10:00
|
|
|
Pos = pState->SavePos;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
2014-02-20 18:06:28 +10:00
|
|
|
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
|
|
|
|
SetConsoleCursorPosition( hConOut, Pos );
|
2010-11-08 15:31:01 +10:00
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'n': // ESC[#n Device status report
|
2010-12-12 21:58:35 +10:00
|
|
|
if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored
|
2010-12-12 23:32:22 +10:00
|
|
|
switch (es_argv[0])
|
2010-12-12 21:58:35 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
case 5: // ESC[5n Report status
|
2010-12-12 23:32:22 +10:00
|
|
|
SendSequence( L"\33[0n" ); // "OK"
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 6: // ESC[6n Report cursor position
|
2010-12-12 23:32:22 +10:00
|
|
|
{
|
|
|
|
TCHAR buf[32];
|
2014-02-20 18:06:28 +10:00
|
|
|
wsprintf( buf, L"\33[%d;%dR", CUR.Y - TOP + 1, CUR.X + 1 );
|
2010-12-12 23:32:22 +10:00
|
|
|
SendSequence( buf );
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
2010-12-12 21:58:35 +10:00
|
|
|
}
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 't': // ESC[#t Window manipulation
|
2010-12-12 21:58:35 +10:00
|
|
|
if (es_argc != 1) return;
|
|
|
|
if (es_argv[0] == 21) // ESC[21t Report xterm window's title
|
|
|
|
{
|
|
|
|
TCHAR buf[MAX_PATH*2];
|
|
|
|
DWORD len = GetConsoleTitle( buf+3, lenof(buf)-3-2 );
|
|
|
|
// Too bad if it's too big or fails.
|
|
|
|
buf[0] = ESC;
|
|
|
|
buf[1] = ']';
|
|
|
|
buf[2] = 'l';
|
|
|
|
buf[3+len] = ESC;
|
|
|
|
buf[3+len+1] = '\\';
|
|
|
|
buf[3+len+2] = '\0';
|
|
|
|
SendSequence( buf );
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'h': // ESC[#h Set Mode
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
if (es_argc == 1 && es_argv[0] == 3)
|
|
|
|
pState->crm = TRUE;
|
|
|
|
return;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
case 'l': // ESC[#l Reset Mode
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
return; // ESC[3l is handled during parsing
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-12-12 21:58:35 +10:00
|
|
|
else // (prefix == ']')
|
|
|
|
{
|
2014-02-18 21:34:39 +10:00
|
|
|
// Ignore any "private" sequences.
|
2011-03-01 21:01:37 +10:00
|
|
|
if (prefix2 != 0)
|
|
|
|
return;
|
|
|
|
|
2014-02-18 21:34:39 +10:00
|
|
|
if (es_argc == 1 && (es_argv[0] == 0 || // ESC]0;titleST - icon (ignored) &
|
|
|
|
es_argv[0] == 2)) // ESC]2;titleST - window
|
2010-12-12 21:58:35 +10:00
|
|
|
{
|
2010-12-12 23:32:22 +10:00
|
|
|
SetConsoleTitle( Pt_arg );
|
2010-12-12 21:58:35 +10:00
|
|
|
}
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// ParseAndPrintString(hDev, lpBuffer, nNumberOfBytesToWrite)
|
|
|
|
// Parses the string lpBuffer, interprets the escapes sequences and prints the
|
|
|
|
// characters in the device hDev (console).
|
|
|
|
// The lexer is a three states automata.
|
|
|
|
// If the number of arguments es_argc > MAX_ARG, only the MAX_ARG-1 firsts and
|
|
|
|
// the last arguments are processed (no es_argv[] overflow).
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
ParseAndPrintString( HANDLE hDev,
|
|
|
|
LPCVOID lpBuffer,
|
|
|
|
DWORD nNumberOfBytesToWrite,
|
|
|
|
LPDWORD lpNumberOfBytesWritten
|
|
|
|
)
|
|
|
|
{
|
2010-12-16 16:00:56 +10:00
|
|
|
DWORD i;
|
|
|
|
LPCTSTR s;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
if (hDev != hConOut) // reinit if device has changed
|
|
|
|
{
|
|
|
|
hConOut = hDev;
|
|
|
|
state = 1;
|
2011-02-26 17:14:21 +10:00
|
|
|
shifted = FALSE;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2010-12-16 16:00:56 +10:00
|
|
|
for (i = nNumberOfBytesToWrite, s = (LPCTSTR)lpBuffer; i > 0; i--, s++)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
int c = *s; // more efficient to use int than short, fwiw
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
if (state == 1)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == ESC)
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
|
|
|
suffix2 = 0;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
get_state();
|
|
|
|
state = (pState->crm) ? 7 : 2;
|
2014-02-18 21:34:39 +10:00
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == SO) shifted = TRUE;
|
|
|
|
else if (c == SI) shifted = FALSE;
|
|
|
|
else PushBuffer( (WCHAR)c );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
else if (state == 2)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == ESC) ; // \e\e...\e == \e
|
|
|
|
else if (c >= '\x20' && c <= '\x2f')
|
|
|
|
suffix2 = c;
|
2014-02-18 21:34:39 +10:00
|
|
|
else if (suffix2 != 0)
|
|
|
|
state = 1;
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == '[' || // CSI Control Sequence Introducer
|
|
|
|
c == ']') // OSC Operating System Command
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
FlushBuffer();
|
2017-07-25 18:18:34 +10:00
|
|
|
prefix = c;
|
2010-12-12 21:58:35 +10:00
|
|
|
prefix2 = 0;
|
|
|
|
Pt_len = 0;
|
|
|
|
*Pt_arg = '\0';
|
2014-02-18 21:34:39 +10:00
|
|
|
state = 3;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == 'P' || // DCS Device Control String
|
|
|
|
c == 'X' || // SOS Start Of String
|
|
|
|
c == '^' || // PM Privacy Message
|
|
|
|
c == '_') // APC Application Program Command
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
|
|
|
*Pt_arg = '\0';
|
|
|
|
state = 6;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
else state = 1;
|
|
|
|
}
|
|
|
|
else if (state == 3)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (is_digit( c ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
es_argc = 0;
|
2017-07-25 18:18:34 +10:00
|
|
|
es_argv[0] = c - '0';
|
2010-11-08 15:31:01 +10:00
|
|
|
state = 4;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == ';')
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
es_argc = 1;
|
|
|
|
es_argv[0] = 0;
|
|
|
|
es_argv[1] = 0;
|
|
|
|
state = 4;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == ':')
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
|
|
|
// ignore it
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c >= '\x3b' && c <= '\x3f')
|
2010-12-12 21:58:35 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
prefix2 = c;
|
2010-12-12 21:58:35 +10:00
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c >= '\x20' && c <= '\x2f')
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
suffix2 = c;
|
2014-02-18 21:34:39 +10:00
|
|
|
}
|
|
|
|
else if (suffix2 != 0)
|
|
|
|
{
|
|
|
|
state = 1;
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
es_argc = 0;
|
2017-07-25 18:18:34 +10:00
|
|
|
suffix = c;
|
2010-11-08 15:31:01 +10:00
|
|
|
InterpretEscSeq();
|
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (state == 4)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (is_digit( c ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
es_argv[es_argc] = 10 * es_argv[es_argc] + (c - '0');
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == ';')
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
if (es_argc < MAX_ARG-1) es_argc++;
|
2010-12-12 21:58:35 +10:00
|
|
|
es_argv[es_argc] = 0;
|
|
|
|
if (prefix == ']')
|
|
|
|
state = 5;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c >= '\x3a' && c <= '\x3f')
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
|
|
|
// ignore 'em
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c >= '\x20' && c <= '\x2f')
|
2014-02-18 21:34:39 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
suffix2 = c;
|
2014-02-18 21:34:39 +10:00
|
|
|
}
|
|
|
|
else if (suffix2 != 0)
|
|
|
|
{
|
|
|
|
state = 1;
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
es_argc++;
|
2017-07-25 18:18:34 +10:00
|
|
|
suffix = c;
|
2010-11-08 15:31:01 +10:00
|
|
|
InterpretEscSeq();
|
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
}
|
2010-12-12 21:58:35 +10:00
|
|
|
else if (state == 5)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == BEL)
|
2010-12-12 21:58:35 +10:00
|
|
|
{
|
|
|
|
Pt_arg[Pt_len] = '\0';
|
|
|
|
InterpretEscSeq();
|
|
|
|
state = 1;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
else if (c == '\\' && Pt_len > 0 && Pt_arg[Pt_len-1] == ESC)
|
2010-12-12 21:58:35 +10:00
|
|
|
{
|
|
|
|
Pt_arg[--Pt_len] = '\0';
|
|
|
|
InterpretEscSeq();
|
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
else if (Pt_len < lenof(Pt_arg)-1)
|
2017-07-25 18:18:34 +10:00
|
|
|
Pt_arg[Pt_len++] = c;
|
2010-12-12 21:58:35 +10:00
|
|
|
}
|
2011-02-26 17:14:21 +10:00
|
|
|
else if (state == 6)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == BEL || (c == '\\' && *Pt_arg == ESC))
|
2014-02-18 21:34:39 +10:00
|
|
|
state = 1;
|
|
|
|
else
|
2017-07-25 18:18:34 +10:00
|
|
|
*Pt_arg = c;
|
2011-02-26 17:14:21 +10:00
|
|
|
}
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
else if (state == 7)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == '[') state = 8;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
PushBuffer( ESC );
|
2017-07-25 18:18:34 +10:00
|
|
|
PushBuffer( (WCHAR)c );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (state == 8)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == '3') state = 9;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
PushBuffer( ESC );
|
|
|
|
PushBuffer( '[' );
|
2017-07-25 18:18:34 +10:00
|
|
|
PushBuffer( (WCHAR)c );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (state == 9)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (c == 'l') pState->crm = FALSE;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
PushBuffer( ESC );
|
|
|
|
PushBuffer( '[' );
|
|
|
|
PushBuffer( '3' );
|
2017-07-25 18:18:34 +10:00
|
|
|
PushBuffer( (WCHAR)c );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
}
|
|
|
|
state = 1;
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
FlushBuffer();
|
2010-12-04 15:19:36 +10:00
|
|
|
if (lpNumberOfBytesWritten != NULL)
|
|
|
|
*lpNumberOfBytesWritten = nNumberOfBytesToWrite - i;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return (i == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== Hooking API functions
|
|
|
|
//
|
|
|
|
// References about API hooking (and dll injection):
|
|
|
|
// - Matt Pietrek ~ Windows 95 System Programming Secrets.
|
|
|
|
// - Jeffrey Richter ~ Programming Applications for Microsoft Windows 4th ed.
|
|
|
|
|
|
|
|
const char APIKernel[] = "kernel32.dll";
|
2012-01-15 15:24:01 +10:00
|
|
|
const char APIConsole[] = "API-MS-Win-Core-Console-";
|
|
|
|
const char APIProcessThreads[] = "API-MS-Win-Core-ProcessThreads-";
|
|
|
|
const char APIProcessEnvironment[] = "API-MS-Win-Core-ProcessEnvironment-";
|
|
|
|
const char APILibraryLoader[] = "API-MS-Win-Core-LibraryLoader-";
|
|
|
|
const char APIFile[] = "API-MS-Win-Core-File-";
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2012-01-15 15:24:01 +10:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
PCSTR name;
|
|
|
|
DWORD len;
|
|
|
|
HMODULE base;
|
|
|
|
} API_DATA, *PAPI_DATA;
|
|
|
|
|
|
|
|
API_DATA APIs[] =
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2012-01-15 15:24:01 +10:00
|
|
|
{ APIConsole, sizeof(APIConsole) - 1, NULL },
|
|
|
|
{ APIProcessThreads, sizeof(APIProcessThreads) - 1, NULL },
|
|
|
|
{ APIProcessEnvironment, sizeof(APIProcessEnvironment) - 1, NULL },
|
|
|
|
{ APILibraryLoader, sizeof(APILibraryLoader) - 1, NULL },
|
|
|
|
{ APIFile, sizeof(APIFile) - 1, NULL },
|
|
|
|
{ NULL, 0, NULL }
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
HMODULE hKernel; // Kernel32 module handle
|
|
|
|
HINSTANCE hDllInstance; // Dll instance handle
|
2012-04-10 15:39:58 +10:00
|
|
|
#if defined(_WIN64) || defined(W32ON64)
|
2014-02-08 01:10:51 +10:00
|
|
|
LPTSTR DllNameType; // pointer to process type within DllName
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
PCSTR lib;
|
|
|
|
PSTR name;
|
|
|
|
PROC newfunc;
|
|
|
|
PROC oldfunc;
|
|
|
|
PROC apifunc;
|
2014-02-10 16:33:42 +10:00
|
|
|
PULONG_PTR myimport;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
} HookFn, *PHookFn;
|
|
|
|
|
|
|
|
HookFn Hooks[];
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
const char zIgnoring[] = "Ignoring";
|
|
|
|
const char zScanning[] = "Scanning";
|
|
|
|
const char zSkipping[] = "Skipping";
|
|
|
|
const char zHooking[] = "Hooking";
|
|
|
|
const char zUnhooking[] = "Unhooking";
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// HookAPIOneMod
|
|
|
|
// Substitute a new function in the Import Address Table (IAT) of the
|
|
|
|
// specified module.
|
|
|
|
// Return FALSE on error and TRUE on success.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
BOOL HookAPIOneMod(
|
|
|
|
HMODULE hFromModule, // Handle of the module to intercept calls from
|
|
|
|
PHookFn Hooks, // Functions to replace
|
2014-02-10 16:33:42 +10:00
|
|
|
BOOL restore, // Restore the original functions
|
2017-07-25 18:18:34 +10:00
|
|
|
LPCSTR sp // Logging indentation
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
)
|
|
|
|
{
|
|
|
|
PIMAGE_DOS_HEADER pDosHeader;
|
|
|
|
PIMAGE_NT_HEADERS pNTHeader;
|
|
|
|
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
|
|
|
|
PIMAGE_THUNK_DATA pThunk;
|
|
|
|
PHookFn hook;
|
2014-02-10 16:33:42 +10:00
|
|
|
BOOL self;
|
|
|
|
|
|
|
|
if (hFromModule == NULL)
|
|
|
|
{
|
|
|
|
self = TRUE;
|
|
|
|
hFromModule = hDllInstance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
self = FALSE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Tests to make sure we're looking at a module image (the 'MZ' header)
|
|
|
|
pDosHeader = (PIMAGE_DOS_HEADER)hFromModule;
|
|
|
|
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Image has no DOS header!" );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The MZ header has a pointer to the PE header
|
|
|
|
pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );
|
|
|
|
|
|
|
|
// One more test to make sure we're looking at a "PE" image
|
|
|
|
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Image has no NT header!" );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We now have a valid pointer to the module's PE header.
|
|
|
|
// Get a pointer to its imports section.
|
|
|
|
pImportDesc = MakeVA( PIMAGE_IMPORT_DESCRIPTOR,
|
2014-02-05 00:21:42 +10:00
|
|
|
pNTHeader->IMPORTDIR.VirtualAddress );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Bail out if the RVA of the imports section is 0 (it doesn't exist)
|
|
|
|
if (pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pDosHeader)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
// Iterate through the array of imported module descriptors, looking
|
|
|
|
// for the module whose name matches the pszFunctionModule parameter.
|
|
|
|
for (; pImportDesc->Name; pImportDesc++)
|
|
|
|
{
|
2012-01-15 15:24:01 +10:00
|
|
|
BOOL kernel = TRUE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );
|
2017-07-25 18:18:34 +10:00
|
|
|
if (_strnicmp( pszModName, APIKernel, 8 ) != 0 ||
|
|
|
|
(_stricmp( pszModName+8, APIKernel+8 ) != 0 && pszModName[8] != '\0'))
|
2012-01-15 15:24:01 +10:00
|
|
|
{
|
|
|
|
PAPI_DATA lib;
|
|
|
|
for (lib = APIs; lib->name; ++lib)
|
|
|
|
{
|
|
|
|
if (_strnicmp( pszModName, lib->name, lib->len ) == 0)
|
|
|
|
{
|
|
|
|
if (lib->base == NULL)
|
|
|
|
{
|
|
|
|
lib->base = GetModuleHandleA( pszModName );
|
|
|
|
for (hook = Hooks; hook->name; ++hook)
|
|
|
|
if (hook->lib == lib->name)
|
|
|
|
hook->apifunc = GetProcAddress( lib->base, hook->name );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lib->name == NULL)
|
|
|
|
{
|
|
|
|
if (log_level & 16)
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, " %s%s %s", sp, zIgnoring, pszModName );
|
2012-01-15 15:24:01 +10:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
kernel = FALSE;
|
|
|
|
}
|
|
|
|
if (log_level & 16)
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, " %s%s %s", sp, zScanning, pszModName );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Get a pointer to the found module's import address table (IAT).
|
|
|
|
pThunk = MakeVA( PIMAGE_THUNK_DATA, pImportDesc->FirstThunk );
|
|
|
|
|
|
|
|
// Blast through the table of import addresses, looking for the ones
|
|
|
|
// that match the original addresses.
|
|
|
|
while (pThunk->u1.Function)
|
|
|
|
{
|
|
|
|
for (hook = Hooks; hook->name; ++hook)
|
|
|
|
{
|
|
|
|
PROC patch = 0;
|
|
|
|
if (restore)
|
|
|
|
{
|
|
|
|
if ((PROC)pThunk->u1.Function == hook->newfunc)
|
2012-01-15 15:24:01 +10:00
|
|
|
patch = (kernel) ? hook->oldfunc : hook->apifunc;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
else if ((PROC)pThunk->u1.Function == hook->oldfunc ||
|
|
|
|
(PROC)pThunk->u1.Function == hook->apifunc)
|
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
if (self)
|
2017-07-25 18:18:34 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
hook->myimport = &pThunk->u1.Function;
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, " %s%s", sp, hook->name );
|
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Don't hook if our import already points to the module being
|
|
|
|
// hooked (i.e. it's already hooked us).
|
|
|
|
MEMORY_BASIC_INFORMATION minfo;
|
|
|
|
VirtualQuery( (LPVOID)*hook->myimport, &minfo, sizeof(minfo) );
|
|
|
|
if (minfo.AllocationBase != hFromModule)
|
|
|
|
patch = hook->newfunc;
|
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
if (patch)
|
|
|
|
{
|
2014-02-05 00:21:42 +10:00
|
|
|
DWORD pr;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, " %s%s", sp, hook->name );
|
2014-02-05 00:21:42 +10:00
|
|
|
// Change the access protection on the region of committed pages in
|
|
|
|
// the virtual address space of the current process.
|
|
|
|
VirtualProtect( &pThunk->u1.Function, PTRSZ, PAGE_READWRITE, &pr );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Overwrite the original address with the address of the new function.
|
2014-02-05 00:21:42 +10:00
|
|
|
pThunk->u1.Function = (DWORD_PTR)patch;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Put the page attributes back the way they were.
|
2014-02-05 00:21:42 +10:00
|
|
|
VirtualProtect( &pThunk->u1.Function, PTRSZ, pr, &pr );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pThunk++; // Advance to next imported function address
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE; // Function not found
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// HookAPIAllMod
|
|
|
|
// Substitute a new function in the Import Address Table (IAT) of all
|
|
|
|
// the modules in the current process.
|
|
|
|
// Return FALSE on error and TRUE on success.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore, BOOL indent )
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
|
|
|
HANDLE hModuleSnap;
|
|
|
|
MODULEENTRY32 me;
|
|
|
|
BOOL fOk;
|
2017-07-25 18:18:34 +10:00
|
|
|
LPCSTR op, sp;
|
2014-02-10 16:33:42 +10:00
|
|
|
DWORD pr;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
|
|
|
// Take a snapshot of all modules in the current process.
|
|
|
|
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,
|
|
|
|
GetCurrentProcessId() );
|
|
|
|
|
|
|
|
if (hModuleSnap == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Failed to create snapshot (%u)", GetLastError() );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
op = (restore) ? zUnhooking : zHooking;
|
2017-07-25 18:18:34 +10:00
|
|
|
sp = (indent) ? " " : "";
|
2014-02-10 16:33:42 +10:00
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
// Fill the size of the structure before using it.
|
|
|
|
me.dwSize = sizeof(MODULEENTRY32);
|
|
|
|
|
|
|
|
// Walk the module list of the modules.
|
|
|
|
for (fOk = Module32First( hModuleSnap, &me ); fOk;
|
|
|
|
fOk = Module32Next( hModuleSnap, &me ))
|
|
|
|
{
|
|
|
|
// We don't hook functions in our own module.
|
2014-02-10 16:33:42 +10:00
|
|
|
if (me.hModule == hDllInstance || me.hModule == hKernel)
|
|
|
|
continue;
|
|
|
|
|
2017-10-26 21:46:53 +10:00
|
|
|
if (!restore)
|
2017-07-25 18:18:34 +10:00
|
|
|
{
|
2017-10-26 21:46:53 +10:00
|
|
|
// Don't scan what we've already scanned.
|
|
|
|
if (*(PDWORD)((PBYTE)me.hModule + 36) == 'ISNA') // e_oemid, e_oeminfo
|
|
|
|
{
|
|
|
|
if (log_level & 16)
|
|
|
|
DEBUGSTR( 2, "%s%s %S", sp, zSkipping, me.szModule );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// It's possible for the PE header to be inside the DOS header.
|
|
|
|
if (*(PDWORD)((PBYTE)me.hModule + 0x3C) >= 0x40)
|
|
|
|
{
|
|
|
|
VirtualProtect( (PBYTE)me.hModule + 36, 4, PAGE_READWRITE, &pr );
|
|
|
|
*(PDWORD)((PBYTE)me.hModule + 36) = 'ISNA';
|
|
|
|
VirtualProtect( (PBYTE)me.hModule + 36, 4, pr, &pr );
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
}
|
2017-10-26 21:46:53 +10:00
|
|
|
else
|
2017-07-25 18:18:34 +10:00
|
|
|
{
|
2017-10-26 21:46:53 +10:00
|
|
|
if (*(PDWORD)((PBYTE)me.hModule + 36) != 'ISNA' &&
|
|
|
|
*(PDWORD)((PBYTE)me.hModule + 0x3C) >= 0x40)
|
|
|
|
{
|
|
|
|
if (log_level & 16)
|
|
|
|
DEBUGSTR( 2, "%s%s %S", sp, zSkipping, me.szModule );
|
|
|
|
continue;
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
if (search_env( L"ANSICON_EXC", me.szModule ))
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "%s%s %S", sp, zIgnoring, me.szModule );
|
2014-02-10 16:33:42 +10:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hook the functions in this module.
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "%s%s %S", sp, op, me.szModule );
|
2014-02-10 16:33:42 +10:00
|
|
|
if (!HookAPIOneMod( me.hModule, Hooks, restore, sp ))
|
|
|
|
{
|
|
|
|
CloseHandle( hModuleSnap );
|
|
|
|
return FALSE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CloseHandle( hModuleSnap );
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "%s%s completed", sp, op );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return TRUE;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== Child process injection
|
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
#define MAX_DEV_PATH (32+MAX_PATH) // device form instead of drive letter
|
|
|
|
|
|
|
|
static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
|
|
|
BOOL wide, LPCVOID lpApp, LPCVOID lpCmd )
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
app[MAX_DEV_PATH-1] = '\0';
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2014-02-08 01:10:51 +10:00
|
|
|
if (lpApp == NULL)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
typedef DWORD (WINAPI *PGPIFNW)( HANDLE, LPTSTR, DWORD );
|
|
|
|
static PGPIFNW GetProcessImageFileName;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
if (GetProcessImageFileName == NULL)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
// Use Ex to avoid potential recursion with other hooks.
|
|
|
|
HMODULE psapi = LoadLibraryEx( L"psapi.dll", NULL, 0 );
|
|
|
|
if (psapi != NULL)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
GetProcessImageFileName = (PGPIFNW)GetProcAddress( psapi,
|
|
|
|
"GetProcessImageFileNameW" );
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
if (GetProcessImageFileName == NULL)
|
|
|
|
GetProcessImageFileName = INVALID_HANDLE_VALUE;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
if (GetProcessImageFileName == INVALID_HANDLE_VALUE ||
|
|
|
|
GetProcessImageFileName( hProcess, app, MAX_DEV_PATH ) == 0)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
LPTSTR name;
|
|
|
|
LPCTSTR term = L" \t";
|
|
|
|
|
|
|
|
if (wide)
|
2014-02-08 01:10:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
LPCTSTR pos;
|
|
|
|
for (pos = lpCmd; *pos == ' ' || *pos == '\t'; ++pos) ;
|
|
|
|
if (*pos == '"')
|
|
|
|
{
|
|
|
|
term = L"\"";
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
wcsncpy( app, pos, MAX_DEV_PATH-1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LPCSTR pos;
|
|
|
|
for (pos = lpCmd; *pos == ' ' || *pos == '\t'; ++pos) ;
|
|
|
|
if (*pos == '"')
|
|
|
|
{
|
|
|
|
term = L"\"";
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
MultiByteToWideChar( CP_ACP, 0, pos, -1, app, MAX_DEV_PATH-1 );
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
// CreateProcess only works with surrounding quotes ('"a name"' works,
|
|
|
|
// but 'a" "name' fails), so that's all I'll test, too. However, it also
|
|
|
|
// tests for a file at each separator ('a name' tries "a.exe" before
|
|
|
|
// "a name.exe") which I won't do.
|
|
|
|
name = wcspbrk( app, term );
|
2017-07-25 18:18:34 +10:00
|
|
|
if (name != NULL)
|
2014-02-10 16:33:42 +10:00
|
|
|
*name = '\0';
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (wide)
|
2014-02-10 16:33:42 +10:00
|
|
|
wcsncpy( app, lpApp, MAX_DEV_PATH-1 );
|
2014-02-08 01:10:51 +10:00
|
|
|
else
|
2014-02-10 16:33:42 +10:00
|
|
|
MultiByteToWideChar( CP_ACP, 0, lpApp, -1, app, MAX_DEV_PATH-1 );
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
|
|
|
return get_program_name( app );
|
|
|
|
}
|
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
|
2014-02-08 01:10:51 +10:00
|
|
|
// Inject code into the target process to load our DLL.
|
|
|
|
void Inject( DWORD dwCreationFlags, LPPROCESS_INFORMATION lpi,
|
|
|
|
LPPROCESS_INFORMATION child_pi,
|
|
|
|
BOOL wide, LPCVOID lpApp, LPCVOID lpCmd )
|
|
|
|
{
|
|
|
|
int type;
|
|
|
|
PBYTE base;
|
|
|
|
BOOL gui;
|
2014-02-10 16:33:42 +10:00
|
|
|
WCHAR app[MAX_DEV_PATH];
|
|
|
|
LPTSTR name;
|
2014-02-08 01:10:51 +10:00
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
name = get_program( app, child_pi->hProcess, wide, lpApp, lpCmd );
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "%S (%u)", name, child_pi->dwProcessId );
|
2014-02-10 16:33:42 +10:00
|
|
|
if (search_env( L"ANSICON_EXC", name ))
|
2014-02-08 01:10:51 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, " Excluded" );
|
2014-02-10 16:33:42 +10:00
|
|
|
type = 0;
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
else
|
2014-02-08 01:10:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
type = ProcessType( child_pi, &base, &gui );
|
|
|
|
if (gui && type > 0)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2014-02-10 16:33:42 +10:00
|
|
|
if (!search_env( L"ANSICON_GUI", name ))
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, " %s", zIgnoring );
|
2014-02-10 16:33:42 +10:00
|
|
|
type = 0;
|
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
|
|
|
}
|
2014-02-05 00:21:42 +10:00
|
|
|
if (type > 0)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
#ifdef _WIN64
|
2014-02-08 01:10:51 +10:00
|
|
|
if (type == 64)
|
|
|
|
{
|
|
|
|
ansi_bits[0] = '6';
|
|
|
|
ansi_bits[1] = '4';
|
|
|
|
InjectDLL( child_pi, base );
|
|
|
|
}
|
|
|
|
else if (type == 32)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-05 00:21:42 +10:00
|
|
|
ansi_bits[0] = '3';
|
|
|
|
ansi_bits[1] = '2';
|
|
|
|
InjectDLL32( child_pi, base );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2014-02-08 01:10:51 +10:00
|
|
|
else // (type == 48)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2014-02-08 01:10:51 +10:00
|
|
|
InjectDLL64( child_pi );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
#else
|
2012-04-10 15:39:58 +10:00
|
|
|
#ifdef W32ON64
|
2014-02-08 01:10:51 +10:00
|
|
|
if (type != 32)
|
2012-04-10 15:39:58 +10:00
|
|
|
{
|
|
|
|
TCHAR args[64];
|
|
|
|
STARTUPINFO si;
|
|
|
|
PROCESS_INFORMATION pi;
|
2014-02-08 01:10:51 +10:00
|
|
|
wcscpy( DllNameType, L"CON.exe" );
|
|
|
|
wsprintf( args, L"ansicon -P%ld", child_pi->dwProcessId );
|
2012-04-10 15:39:58 +10:00
|
|
|
ZeroMemory( &si, sizeof(si) );
|
|
|
|
si.cb = sizeof(si);
|
2014-02-08 01:10:51 +10:00
|
|
|
if (CreateProcess( DllName, args, NULL, NULL, FALSE, 0, NULL, NULL,
|
2012-04-10 15:39:58 +10:00
|
|
|
&si, &pi ))
|
|
|
|
{
|
|
|
|
WaitForSingleObject( pi.hProcess, INFINITE );
|
|
|
|
CloseHandle( pi.hProcess );
|
|
|
|
CloseHandle( pi.hThread );
|
|
|
|
}
|
|
|
|
else
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Could not execute %\"S (%u)", DllName, GetLastError() );
|
2014-02-08 01:10:51 +10:00
|
|
|
wcscpy( DllNameType, L"32.dll" );
|
2012-04-10 15:39:58 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2014-02-05 00:21:42 +10:00
|
|
|
InjectDLL( child_pi, base );
|
2010-11-08 15:31:01 +10:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dwCreationFlags & CREATE_SUSPENDED))
|
2012-06-12 14:38:00 +10:00
|
|
|
ResumeThread( child_pi->hThread );
|
2010-12-16 16:00:56 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
if (lpi != NULL)
|
2010-12-16 16:00:56 +10:00
|
|
|
{
|
2012-06-12 14:38:00 +10:00
|
|
|
memcpy( lpi, child_pi, sizeof(PROCESS_INFORMATION) );
|
2010-12-16 16:00:56 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-12 14:38:00 +10:00
|
|
|
CloseHandle( child_pi->hThread );
|
|
|
|
CloseHandle( child_pi->hProcess );
|
2010-12-16 16:00:56 +10:00
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI MyCreateProcessA( LPCSTR lpApplicationName,
|
|
|
|
LPSTR lpCommandLine,
|
|
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
|
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
|
|
|
BOOL bInheritHandles,
|
|
|
|
DWORD dwCreationFlags,
|
|
|
|
LPVOID lpEnvironment,
|
|
|
|
LPCSTR lpCurrentDirectory,
|
|
|
|
LPSTARTUPINFOA lpStartupInfo,
|
|
|
|
LPPROCESS_INFORMATION lpProcessInformation )
|
|
|
|
{
|
2012-06-12 14:38:00 +10:00
|
|
|
PROCESS_INFORMATION child_pi;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "CreateProcessA: %\"s, %#s", lpApplicationName, lpCommandLine );
|
2014-02-08 01:10:51 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
// May need to initialise the state, to propagate environment variables.
|
|
|
|
get_state();
|
2010-11-08 15:31:01 +10:00
|
|
|
if (!CreateProcessA( lpApplicationName,
|
|
|
|
lpCommandLine,
|
|
|
|
lpThreadAttributes,
|
|
|
|
lpProcessAttributes,
|
|
|
|
bInheritHandles,
|
|
|
|
dwCreationFlags | CREATE_SUSPENDED,
|
|
|
|
lpEnvironment,
|
|
|
|
lpCurrentDirectory,
|
|
|
|
lpStartupInfo,
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
&child_pi ))
|
2014-02-08 01:10:51 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, " Failed (%u)", GetLastError() );
|
2010-11-08 15:31:01 +10:00
|
|
|
return FALSE;
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2012-06-12 14:38:00 +10:00
|
|
|
Inject( dwCreationFlags, lpProcessInformation, &child_pi,
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
FALSE, lpApplicationName, lpCommandLine );
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI MyCreateProcessW( LPCWSTR lpApplicationName,
|
|
|
|
LPWSTR lpCommandLine,
|
|
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
|
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
|
|
|
BOOL bInheritHandles,
|
|
|
|
DWORD dwCreationFlags,
|
|
|
|
LPVOID lpEnvironment,
|
|
|
|
LPCWSTR lpCurrentDirectory,
|
|
|
|
LPSTARTUPINFOW lpStartupInfo,
|
|
|
|
LPPROCESS_INFORMATION lpProcessInformation )
|
|
|
|
{
|
2012-06-12 14:38:00 +10:00
|
|
|
PROCESS_INFORMATION child_pi;
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "CreateProcessW: %\"S, %#S", lpApplicationName, lpCommandLine );
|
2014-02-08 01:10:51 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
get_state();
|
2010-11-08 15:31:01 +10:00
|
|
|
if (!CreateProcessW( lpApplicationName,
|
|
|
|
lpCommandLine,
|
|
|
|
lpThreadAttributes,
|
|
|
|
lpProcessAttributes,
|
|
|
|
bInheritHandles,
|
|
|
|
dwCreationFlags | CREATE_SUSPENDED,
|
|
|
|
lpEnvironment,
|
|
|
|
lpCurrentDirectory,
|
|
|
|
lpStartupInfo,
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
&child_pi ))
|
2014-02-08 01:10:51 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, " Failed (%u)", GetLastError() );
|
2010-11-08 15:31:01 +10:00
|
|
|
return FALSE;
|
2014-02-08 01:10:51 +10:00
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2012-06-12 14:38:00 +10:00
|
|
|
Inject( dwCreationFlags, lpProcessInformation, &child_pi,
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
TRUE, lpApplicationName, lpCommandLine );
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-26 01:12:35 +10:00
|
|
|
FARPROC WINAPI MyGetProcAddress( HMODULE hModule, LPCSTR lpProcName )
|
|
|
|
{
|
|
|
|
PHookFn hook;
|
|
|
|
FARPROC proc;
|
|
|
|
|
|
|
|
proc = GetProcAddress( hModule, lpProcName );
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
if (proc != NULL)
|
2011-02-26 01:12:35 +10:00
|
|
|
{
|
|
|
|
if (hModule == hKernel)
|
|
|
|
{
|
|
|
|
// Ignore LoadLibrary so other hooks continue to work (our version
|
|
|
|
// might end up at a different address).
|
|
|
|
if (proc == Hooks[0].oldfunc || proc == Hooks[1].oldfunc)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, "GetProcAddress: %s (ignoring)", lpProcName );
|
2011-02-26 01:12:35 +10:00
|
|
|
return proc;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
}
|
2012-01-15 15:24:01 +10:00
|
|
|
for (hook = Hooks + 2; hook->name; ++hook)
|
2011-02-26 01:12:35 +10:00
|
|
|
{
|
|
|
|
if (proc == hook->oldfunc)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, "GetProcAddress: %s", lpProcName );
|
2011-02-26 01:12:35 +10:00
|
|
|
return hook->newfunc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-15 15:24:01 +10:00
|
|
|
else
|
2011-02-26 01:12:35 +10:00
|
|
|
{
|
2012-01-15 15:24:01 +10:00
|
|
|
PAPI_DATA api;
|
|
|
|
for (api = APIs; api->name; ++api)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
2012-01-15 15:24:01 +10:00
|
|
|
if (hModule == api->base)
|
2011-02-26 01:12:35 +10:00
|
|
|
{
|
2012-01-15 15:24:01 +10:00
|
|
|
if (proc == Hooks[0].apifunc || proc == Hooks[1].apifunc)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, "GetProcAddress: %s (ignoring)", lpProcName );
|
2012-01-15 15:24:01 +10:00
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
for (hook = Hooks + 2; hook->name; ++hook)
|
|
|
|
{
|
|
|
|
if (proc == hook->apifunc)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 3, "GetProcAddress: %s", lpProcName );
|
2012-01-15 15:24:01 +10:00
|
|
|
return hook->newfunc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2011-02-26 01:12:35 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
HMODULE WINAPI MyLoadLibraryA( LPCSTR lpFileName )
|
|
|
|
{
|
|
|
|
HMODULE hMod = LoadLibraryA( lpFileName );
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "LoadLibraryA %s", lpFileName );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, FALSE, TRUE );
|
2010-11-08 15:31:01 +10:00
|
|
|
return hMod;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HMODULE WINAPI MyLoadLibraryW( LPCWSTR lpFileName )
|
|
|
|
{
|
|
|
|
HMODULE hMod = LoadLibraryW( lpFileName );
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "LoadLibraryW %S", lpFileName );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, FALSE, TRUE );
|
2010-11-08 15:31:01 +10:00
|
|
|
return hMod;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HMODULE WINAPI MyLoadLibraryExA( LPCSTR lpFileName, HANDLE hFile,
|
|
|
|
DWORD dwFlags )
|
|
|
|
{
|
|
|
|
HMODULE hMod = LoadLibraryExA( lpFileName, hFile, dwFlags );
|
2014-01-25 23:43:41 +10:00
|
|
|
if (!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE |
|
|
|
|
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE |
|
|
|
|
LOAD_LIBRARY_AS_IMAGE_RESOURCE)))
|
2014-02-10 16:33:42 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "LoadLibraryExA %s", lpFileName );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, FALSE, TRUE );
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
return hMod;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HMODULE WINAPI MyLoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile,
|
|
|
|
DWORD dwFlags )
|
|
|
|
{
|
|
|
|
HMODULE hMod = LoadLibraryExW( lpFileName, hFile, dwFlags );
|
2014-01-25 23:43:41 +10:00
|
|
|
if (!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE |
|
|
|
|
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE |
|
|
|
|
LOAD_LIBRARY_AS_IMAGE_RESOURCE)))
|
2014-02-10 16:33:42 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "LoadLibraryExW %S", lpFileName );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, FALSE, TRUE );
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
return hMod;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-02 23:21:07 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// IsConsoleHandle
|
|
|
|
// Determine if the handle is writing to the console, with processed output.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL IsConsoleHandle( HANDLE h )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = 0; c < CACHE; ++c)
|
|
|
|
if (cache[c].h == h)
|
|
|
|
return (cache[c].mode & ENABLE_PROCESSED_OUTPUT);
|
|
|
|
|
|
|
|
while (--c > 0)
|
|
|
|
cache[c] = cache[c-1];
|
2013-08-02 23:21:07 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
cache[0].h = h;
|
|
|
|
cache[0].mode = 0;
|
|
|
|
if (!GetConsoleMode( h, &cache[0].mode ))
|
2013-08-02 23:21:07 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
// GetConsoleMode could fail if the console was not opened for reading
|
|
|
|
// (which is what Microsoft's conio output does). Verify the handle with
|
|
|
|
// WriteConsole (processed output is the default).
|
|
|
|
DWORD written;
|
|
|
|
if (WriteConsole( h, NULL, 0, &written, NULL ))
|
|
|
|
cache[0].mode = ENABLE_PROCESSED_OUTPUT;
|
2013-08-02 23:21:07 +10:00
|
|
|
}
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
return (cache[0].mode & ENABLE_PROCESSED_OUTPUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// MySetConsoleMode
|
|
|
|
// It seems GetConsoleMode is a relatively slow function, so call it once and
|
|
|
|
// keep track of changes directly.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
|
|
WINAPI MySetConsoleMode( HANDLE hCon, DWORD mode )
|
|
|
|
{
|
|
|
|
BOOL rc = SetConsoleMode( hCon, mode );
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
for (c = 0; c < CACHE; ++c)
|
|
|
|
{
|
|
|
|
// The mode is associated with the buffer, not the handle.
|
|
|
|
GetConsoleMode( cache[c].h, &cache[c].mode );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rc;
|
2013-08-02 23:21:07 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// MyWrite...
|
2013-08-02 23:21:07 +10:00
|
|
|
// The new functions that must replace the original Write... functions. These
|
|
|
|
// functions have exactly the same signature as the original ones. This
|
|
|
|
// module is not hooked, so we can still call the original functions ourselves.
|
2010-11-08 15:31:01 +10:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
static LPCSTR write_func;
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
BOOL
|
|
|
|
WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
|
|
|
|
DWORD nNumberOfCharsToWrite,
|
|
|
|
LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )
|
|
|
|
{
|
2010-11-13 14:49:27 +10:00
|
|
|
LPWSTR buf;
|
2017-07-25 18:18:34 +10:00
|
|
|
WCHAR wBuf[1024];
|
|
|
|
DWORD len, wlen;
|
|
|
|
UINT cp;
|
2010-11-13 14:49:27 +10:00
|
|
|
BOOL rc = TRUE;
|
2017-07-25 18:18:34 +10:00
|
|
|
LPCSTR aBuf;
|
|
|
|
static char mb[4];
|
|
|
|
static DWORD mb_len, mb_size;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
if (nNumberOfCharsToWrite != 0 && IsConsoleHandle( hCon ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 4, "%s: %u %\"<s",
|
|
|
|
write_func == NULL ? "WriteConsoleA" : write_func,
|
|
|
|
nNumberOfCharsToWrite, lpBuffer );
|
|
|
|
write_func = NULL;
|
|
|
|
aBuf = lpBuffer;
|
|
|
|
len = nNumberOfCharsToWrite;
|
|
|
|
wlen = 0;
|
|
|
|
cp = GetConsoleOutputCP();
|
|
|
|
// How to determine a multibyte character set? Cmd.Exe has IsDBCSCodePage,
|
|
|
|
// which tests code page numbers; ConHost has IsAvailableFarEastCodePage,
|
|
|
|
// which uses TranslateCharsetInfo; I used GetCPInfo in CMDRead. Let's use
|
|
|
|
// IsDBCSCodePage, as that avoids another API call.
|
|
|
|
if (cp == 932 || cp == 936 || cp == 949 || cp == 950)
|
|
|
|
{
|
|
|
|
if (mb_len == 1)
|
|
|
|
{
|
|
|
|
mb[1] = *aBuf++;
|
|
|
|
--len;
|
|
|
|
DEBUGSTR( 4, " %strail byte, removing & writing %\"*s",
|
|
|
|
(len == 0) ? "" : "starts with a ", 2, mb );
|
|
|
|
wlen = MultiByteToWideChar( cp, 0, mb, 2, wBuf, lenof(wBuf) );
|
|
|
|
ParseAndPrintString( hCon, wBuf, wlen, NULL );
|
|
|
|
mb_len = 0;
|
|
|
|
}
|
|
|
|
// A lead byte might also be a trail byte, so count all consecutive lead
|
|
|
|
// bytes - an even number means complete pairs, whilst an odd number
|
|
|
|
// means the last lead byte has been split.
|
|
|
|
if (len != 0 && IsDBCSLeadByteEx( cp, aBuf[len-1] ))
|
|
|
|
{
|
|
|
|
int lead = 1;
|
|
|
|
int pos = len - 1;
|
|
|
|
while (--pos >= 0 && IsDBCSLeadByteEx( cp, aBuf[pos] ))
|
|
|
|
++lead;
|
|
|
|
if (lead & 1)
|
|
|
|
{
|
|
|
|
mb[mb_len++] = aBuf[--len];
|
|
|
|
DEBUGSTR( 4, " %slead byte, removing",
|
|
|
|
(len == 0) ? "" : "ends with a " );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cp == CP_UTF8)
|
|
|
|
{
|
|
|
|
if (mb_len != 0)
|
|
|
|
{
|
|
|
|
while ((*aBuf & 0xC0) == 0x80)
|
|
|
|
{
|
|
|
|
mb[mb_len++] = *aBuf++;
|
|
|
|
--len;
|
|
|
|
if (mb_len == mb_size)
|
|
|
|
break;
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
DEBUGSTR( 4, " trail byte%s, removing",
|
|
|
|
(nNumberOfCharsToWrite == 1) ? "" : "s" );
|
|
|
|
if (lpNumberOfCharsWritten != NULL)
|
|
|
|
*lpNumberOfCharsWritten = 0;
|
|
|
|
goto check_written;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (log_level & 4)
|
|
|
|
{
|
|
|
|
DWORD tlen = nNumberOfCharsToWrite - len;
|
|
|
|
if (tlen == 0)
|
|
|
|
DEBUGSTR( 4, " incomplete UTF-8 sequence, writing %\"*s",
|
|
|
|
mb_len, mb );
|
|
|
|
else if (len == 0)
|
|
|
|
DEBUGSTR( 4, " trail byte%s, removing & writing %\"*s",
|
|
|
|
(tlen == 1) ? "" : "s", mb_len, mb );
|
|
|
|
else if (tlen == 1)
|
|
|
|
DEBUGSTR( 4, " starts with a trail byte, removing & writing %\"*s",
|
|
|
|
mb_len, mb );
|
|
|
|
else
|
|
|
|
DEBUGSTR( 4, " starts with %u trail bytes, removing & writing %\"*s",
|
|
|
|
tlen, mb_len, mb );
|
|
|
|
}
|
|
|
|
wlen = MultiByteToWideChar( cp, 0, mb, mb_len, wBuf, lenof(wBuf) );
|
|
|
|
ParseAndPrintString( hCon, wBuf, wlen, NULL );
|
|
|
|
mb_len = 0;
|
|
|
|
}
|
|
|
|
// In UTF-8, the high bit set means a lead or trail byte; if the next
|
|
|
|
// bit is clear, it's a trail byte; otherwise the number of set high bits
|
|
|
|
// counts the bytes in the sequence. The maximum legitimate sequence is
|
|
|
|
// four bytes.
|
|
|
|
if (len != 0 && (aBuf[len-1] & 0x80))
|
|
|
|
{
|
|
|
|
int pos = len;
|
|
|
|
while (--pos >= 0 && (aBuf[pos] & 0xC0) == 0x80)
|
|
|
|
;
|
|
|
|
if (pos >= 0 && (aBuf[pos] & 0x80) && len - pos < 4 &&
|
|
|
|
(pos == 0 || (aBuf[pos-1] & 0xC0) != 0xC0))
|
|
|
|
{
|
|
|
|
char lead = aBuf[pos];
|
|
|
|
mb_size = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
++mb_size;
|
|
|
|
lead <<= 1;
|
|
|
|
} while (lead & 0x80);
|
|
|
|
if (mb_size <= 4 && mb_size > len - pos)
|
|
|
|
{
|
|
|
|
mb_len = len - pos;
|
|
|
|
memcpy( mb, aBuf + pos, mb_len );
|
|
|
|
len = pos;
|
|
|
|
if (log_level & 4)
|
|
|
|
{
|
|
|
|
if (mb_len == nNumberOfCharsToWrite)
|
|
|
|
DEBUGSTR( 4, " lead byte%s, removing",
|
|
|
|
(mb_len == 1) ? "" : "s" );
|
|
|
|
else if (mb_len == 1)
|
|
|
|
DEBUGSTR( 4, " ends with a lead byte, removing" );
|
|
|
|
else
|
|
|
|
DEBUGSTR( 4, " ends with %u lead bytes, removing", mb_len );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (len == 0)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2010-12-04 15:19:36 +10:00
|
|
|
if (lpNumberOfCharsWritten != NULL)
|
2017-07-25 18:18:34 +10:00
|
|
|
*lpNumberOfCharsWritten = wlen;
|
|
|
|
goto check_written;
|
|
|
|
}
|
|
|
|
if (len <= lenof(wBuf))
|
|
|
|
buf = wBuf;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf = HeapAlloc( hHeap, 0, TSIZE(len) );
|
|
|
|
if (buf == NULL)
|
|
|
|
{
|
|
|
|
DEBUGSTR( 4, "HeapAlloc failed, using original function" );
|
|
|
|
rc = WriteConsoleA( hCon, aBuf,len, lpNumberOfCharsWritten,lpReserved );
|
|
|
|
goto check_written;
|
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
len = MultiByteToWideChar( cp, 0, aBuf, len, buf, len );
|
2010-11-13 14:49:27 +10:00
|
|
|
rc = ParseAndPrintString( hCon, buf, len, lpNumberOfCharsWritten );
|
2017-07-25 18:18:34 +10:00
|
|
|
if (wlen != 0 && rc && lpNumberOfCharsWritten != NULL)
|
|
|
|
*lpNumberOfCharsWritten += wlen;
|
|
|
|
if (buf != wBuf)
|
|
|
|
HeapFree( hHeap, 0, buf );
|
|
|
|
check_written:
|
2010-12-12 23:32:22 +10:00
|
|
|
if (rc && lpNumberOfCharsWritten != NULL &&
|
|
|
|
*lpNumberOfCharsWritten != nNumberOfCharsToWrite)
|
2010-11-15 22:14:17 +10:00
|
|
|
{
|
|
|
|
// Converting a multibyte character to Unicode results in a different
|
|
|
|
// "character" count. This causes some programs to think not everything
|
|
|
|
// was written, so the difference is sent again. Fudge the (presumably)
|
|
|
|
// correct count.
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
if (search_env( L"ANSICON_API", prog ))
|
|
|
|
*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
|
2010-11-15 22:14:17 +10:00
|
|
|
}
|
2010-11-08 15:31:01 +10:00
|
|
|
return rc;
|
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
|
|
|
return WriteConsoleA( hCon, lpBuffer, nNumberOfCharsToWrite,
|
|
|
|
lpNumberOfCharsWritten, lpReserved );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
WINAPI MyWriteConsoleW( HANDLE hCon, LPCVOID lpBuffer,
|
|
|
|
DWORD nNumberOfCharsToWrite,
|
|
|
|
LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (nNumberOfCharsToWrite != 0 && IsConsoleHandle( hCon ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 4, "WriteConsoleW: %u %\"<S",
|
|
|
|
nNumberOfCharsToWrite, lpBuffer );
|
2010-11-08 15:31:01 +10:00
|
|
|
return ParseAndPrintString( hCon, lpBuffer,
|
|
|
|
nNumberOfCharsToWrite,
|
|
|
|
lpNumberOfCharsWritten );
|
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
|
|
|
return WriteConsoleW( hCon, lpBuffer, nNumberOfCharsToWrite,
|
|
|
|
lpNumberOfCharsWritten, lpReserved );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
|
|
|
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (nNumberOfBytesToWrite != 0 && IsConsoleHandle( hFile ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (HandleToULong( hFile ) == STD_OUTPUT_HANDLE ||
|
|
|
|
HandleToULong( hFile ) == STD_ERROR_HANDLE)
|
|
|
|
hFile = GetStdHandle( HandleToULong( hFile ) );
|
|
|
|
|
|
|
|
write_func = "WriteFile";
|
|
|
|
MyWriteConsoleA( hFile, lpBuffer,nNumberOfBytesToWrite, NULL,lpOverlapped );
|
|
|
|
if (lpNumberOfBytesWritten != NULL)
|
|
|
|
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
|
|
|
|
return TRUE;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
|
|
|
return WriteFile( hFile, lpBuffer, nNumberOfBytesToWrite,
|
|
|
|
lpNumberOfBytesWritten, lpOverlapped );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define HHFILE (HANDLE)(DWORD_PTR)
|
|
|
|
|
|
|
|
UINT
|
|
|
|
WINAPI My_lwrite( HFILE hFile, LPCSTR lpBuffer, UINT uBytes )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (uBytes != 0 && IsConsoleHandle( HHFILE hFile ))
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
write_func = "_lwrite";
|
|
|
|
MyWriteConsoleA( HHFILE hFile, lpBuffer, uBytes, NULL, NULL );
|
|
|
|
return uBytes;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
|
|
|
return _lwrite( hFile, lpBuffer, uBytes );
|
|
|
|
}
|
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
// ========== Environment variable
|
|
|
|
|
|
|
|
void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )
|
|
|
|
{
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
2010-11-15 21:51:38 +10:00
|
|
|
TCHAR buf[64];
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
if (pcsbi == NULL)
|
|
|
|
{
|
|
|
|
HANDLE hConOut;
|
2010-11-15 21:51:38 +10:00
|
|
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
2017-07-25 18:18:34 +10:00
|
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
2010-11-08 15:31:01 +10:00
|
|
|
GetConsoleScreenBufferInfo( hConOut, &csbi );
|
|
|
|
CloseHandle( hConOut );
|
|
|
|
pcsbi = &csbi;
|
|
|
|
}
|
|
|
|
|
2010-11-15 21:51:38 +10:00
|
|
|
wsprintf( buf, L"%dx%d (%dx%d)",
|
2010-11-08 15:31:01 +10:00
|
|
|
pcsbi->dwSize.X, pcsbi->dwSize.Y,
|
|
|
|
pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1,
|
|
|
|
pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 );
|
2010-11-15 21:51:38 +10:00
|
|
|
SetEnvironmentVariable( L"ANSICON", buf );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (_stricmp( lpName, "ANSICON_VER" ) == 0)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
|
|
|
if (nSize < sizeof(PVEREA))
|
|
|
|
return sizeof(PVEREA);
|
|
|
|
memcpy( lpBuffer, PVEREA, sizeof(PVEREA) );
|
|
|
|
return sizeof(PVEREA) - 1;
|
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
if (_stricmp( lpName, "CLICOLOR" ) == 0)
|
|
|
|
{
|
|
|
|
if (nSize < 2)
|
|
|
|
return 2;
|
|
|
|
lpBuffer[0] = '1';
|
|
|
|
lpBuffer[1] = '\0';
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_stricmp( lpName, "ANSICON" ) == 0)
|
2010-11-08 15:31:01 +10:00
|
|
|
set_ansicon( NULL );
|
2012-02-24 12:53:07 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
return GetEnvironmentVariableA( lpName, lpBuffer, nSize );
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
if (_wcsicmp( lpName, L"ANSICON_VER" ) == 0)
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
{
|
|
|
|
if (nSize < lenof(PVERE))
|
|
|
|
return lenof(PVERE);
|
|
|
|
memcpy( lpBuffer, PVERE, sizeof(PVERE) );
|
|
|
|
return lenof(PVERE) - 1;
|
|
|
|
}
|
2012-02-24 12:53:07 +10:00
|
|
|
|
2017-07-25 18:18:34 +10:00
|
|
|
if (_wcsicmp( lpName, L"CLICOLOR" ) == 0)
|
|
|
|
{
|
|
|
|
if (nSize < 2)
|
|
|
|
return 2;
|
|
|
|
lpBuffer[0] = '1';
|
|
|
|
lpBuffer[1] = '\0';
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_wcsicmp( lpName, L"ANSICON" ) == 0)
|
2010-11-08 15:31:01 +10:00
|
|
|
set_ansicon( NULL );
|
2012-02-24 12:53:07 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
return GetEnvironmentVariableW( lpName, lpBuffer, nSize );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========== Initialisation
|
|
|
|
|
|
|
|
HookFn Hooks[] = {
|
2011-02-26 01:12:35 +10:00
|
|
|
// These two are expected first!
|
2014-02-10 16:33:42 +10:00
|
|
|
{ APILibraryLoader, "LoadLibraryA", (PROC)MyLoadLibraryA, NULL, NULL, NULL },
|
|
|
|
{ APILibraryLoader, "LoadLibraryW", (PROC)MyLoadLibraryW, NULL, NULL, NULL },
|
|
|
|
{ APIProcessThreads, "CreateProcessA", (PROC)MyCreateProcessA, NULL, NULL, NULL },
|
|
|
|
{ APIProcessThreads, "CreateProcessW", (PROC)MyCreateProcessW, NULL, NULL, NULL },
|
|
|
|
{ APIProcessEnvironment, "GetEnvironmentVariableA", (PROC)MyGetEnvironmentVariableA, NULL, NULL, NULL },
|
|
|
|
{ APIProcessEnvironment, "GetEnvironmentVariableW", (PROC)MyGetEnvironmentVariableW, NULL, NULL, NULL },
|
|
|
|
{ APILibraryLoader, "GetProcAddress", (PROC)MyGetProcAddress, NULL, NULL, NULL },
|
|
|
|
{ APILibraryLoader, "LoadLibraryExA", (PROC)MyLoadLibraryExA, NULL, NULL, NULL },
|
|
|
|
{ APILibraryLoader, "LoadLibraryExW", (PROC)MyLoadLibraryExW, NULL, NULL, NULL },
|
2017-07-25 18:18:34 +10:00
|
|
|
{ APIConsole, "SetConsoleMode", (PROC)MySetConsoleMode, NULL, NULL, NULL },
|
2014-02-10 16:33:42 +10:00
|
|
|
{ APIConsole, "WriteConsoleA", (PROC)MyWriteConsoleA, NULL, NULL, NULL },
|
|
|
|
{ APIConsole, "WriteConsoleW", (PROC)MyWriteConsoleW, NULL, NULL, NULL },
|
|
|
|
{ APIFile, "WriteFile", (PROC)MyWriteFile, NULL, NULL, NULL },
|
|
|
|
{ APIKernel, "_lwrite", (PROC)My_lwrite, NULL, NULL, NULL },
|
|
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL }
|
2010-11-08 15:31:01 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// OriginalAttr()
|
|
|
|
// Determine the original attributes for use by \e[m.
|
|
|
|
//-----------------------------------------------------------------------------
|
2014-02-08 12:04:43 +10:00
|
|
|
void OriginalAttr( PVOID lpReserved )
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
|
|
|
HANDLE hConOut;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
|
2010-11-15 21:51:38 +10:00
|
|
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
2017-07-25 18:18:34 +10:00
|
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
2010-11-08 15:31:01 +10:00
|
|
|
if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))
|
|
|
|
csbi.wAttributes = 7;
|
|
|
|
|
2014-02-08 12:04:43 +10:00
|
|
|
// If we were loaded dynamically, remember the current attributes to restore
|
|
|
|
// upon unloading. However, if we're the 64-bit DLL, but the image is 32-
|
|
|
|
// bit, then the dynamic load was due to injecting into AnyCPU.
|
2014-02-10 16:33:42 +10:00
|
|
|
if (lpReserved == NULL)
|
2014-02-08 12:04:43 +10:00
|
|
|
{
|
|
|
|
#ifdef _WIN64
|
2014-02-10 16:33:42 +10:00
|
|
|
PIMAGE_DOS_HEADER pDosHeader;
|
|
|
|
PIMAGE_NT_HEADERS pNTHeader;
|
|
|
|
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle( NULL );
|
|
|
|
pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );
|
|
|
|
if (pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
2014-02-08 12:04:43 +10:00
|
|
|
#endif
|
|
|
|
orgattr = csbi.wAttributes;
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
GetConsoleMode( hConOut, &orgmode );
|
|
|
|
GetConsoleCursorInfo( hConOut, &orgcci );
|
2014-02-08 12:04:43 +10:00
|
|
|
}
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
CloseHandle( hConOut );
|
2014-02-08 12:04:43 +10:00
|
|
|
|
2014-02-08 18:30:53 +10:00
|
|
|
get_state();
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// DllMain()
|
|
|
|
// Function called by the system when processes and threads are initialized
|
|
|
|
// and terminated.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2014-02-05 00:21:42 +10:00
|
|
|
// Need to export something for static loading to work, this is as good as any.
|
|
|
|
__declspec(dllexport)
|
2010-11-08 15:31:01 +10:00
|
|
|
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
|
|
|
{
|
|
|
|
BOOL bResult = TRUE;
|
|
|
|
PHookFn hook;
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
TCHAR logstr[4];
|
2014-02-10 16:33:42 +10:00
|
|
|
typedef LONG (WINAPI *PNTQIT)( HANDLE, int, PVOID, ULONG, PULONG );
|
|
|
|
static PNTQIT NtQueryInformationThread;
|
2010-11-08 15:31:01 +10:00
|
|
|
|
|
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
hHeap = HeapCreate( 0, 0, 128 * 1024 );
|
|
|
|
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
*logstr = '\0';
|
|
|
|
GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
|
|
|
|
log_level = _wtoi( logstr );
|
|
|
|
prog = get_program_name( NULL );
|
2012-04-10 15:39:58 +10:00
|
|
|
#if defined(_WIN64) || defined(W32ON64)
|
2014-02-08 01:10:51 +10:00
|
|
|
DllNameType = DllName - 6 +
|
2014-02-05 00:21:42 +10:00
|
|
|
#endif
|
2014-02-08 01:10:51 +10:00
|
|
|
GetModuleFileName( hInstance, DllName, lenof(DllName) );
|
|
|
|
set_ansi_dll();
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
hDllInstance = hInstance; // save Dll instance handle
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "hDllInstance = %p", hDllInstance );
|
2014-01-27 14:03:53 +10:00
|
|
|
|
2010-11-08 15:31:01 +10:00
|
|
|
// Get the entry points to the original functions.
|
|
|
|
hKernel = GetModuleHandleA( APIKernel );
|
|
|
|
for (hook = Hooks; hook->name; ++hook)
|
|
|
|
hook->oldfunc = GetProcAddress( hKernel, hook->name );
|
|
|
|
|
2014-02-10 16:33:42 +10:00
|
|
|
// Get my import addresses, to detect if anyone's hooked me.
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "Storing my imports" );
|
|
|
|
HookAPIOneMod( NULL, Hooks, FALSE, "" );
|
2014-02-10 16:33:42 +10:00
|
|
|
|
|
|
|
bResult = HookAPIAllMod( Hooks, FALSE, FALSE );
|
2014-02-08 12:04:43 +10:00
|
|
|
OriginalAttr( lpReserved );
|
2014-02-10 16:33:42 +10:00
|
|
|
|
|
|
|
NtQueryInformationThread = (PNTQIT)GetProcAddress(
|
|
|
|
GetModuleHandle( L"ntdll.dll" ), "NtQueryInformationThread" );
|
|
|
|
if (NtQueryInformationThread == NULL)
|
|
|
|
DisableThreadLibraryCalls( hInstance );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2010-12-16 16:00:56 +10:00
|
|
|
else if (dwReason == DLL_PROCESS_DETACH)
|
2010-11-08 15:31:01 +10:00
|
|
|
{
|
2010-12-16 16:00:56 +10:00
|
|
|
if (lpReserved == NULL)
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Unloading" );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, TRUE, FALSE );
|
2010-12-16 16:00:56 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 1, "Terminating" );
|
2010-12-16 16:00:56 +10:00
|
|
|
}
|
2014-02-08 12:04:43 +10:00
|
|
|
if (orgattr != 0)
|
|
|
|
{
|
|
|
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
2017-07-25 18:18:34 +10:00
|
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
2014-02-08 12:04:43 +10:00
|
|
|
SetConsoleTextAttribute( hConOut, orgattr );
|
Recognise more sequences; ignore newline immediately after wrap.
Added support for CHT & CBT (move forward/backward by tabs), DECAWM (don't
wrap at EOL), CRM (display control characters, but still perform newline)
and REP (repeat last character, including BEL, BS, TAB, LF and CR).
It always bugged me that newline would add an unneeded blank line due to
wrap, but not enough to do anything about it. For some reason, adding CRM
got me to thinking about it, so I finally did it.
Stopped \e[K from erasing the first character of the next line.
Restore cursor visibility on unload.
2014-02-26 21:18:45 +10:00
|
|
|
SetConsoleMode( hConOut, orgmode );
|
|
|
|
SetConsoleCursorInfo( hConOut, &orgcci );
|
2014-02-08 12:04:43 +10:00
|
|
|
CloseHandle( hConOut );
|
|
|
|
}
|
2017-07-25 18:18:34 +10:00
|
|
|
if (hMap != NULL)
|
|
|
|
{
|
|
|
|
UnmapViewOfFile( pState );
|
|
|
|
CloseHandle( hMap );
|
|
|
|
}
|
|
|
|
HeapDestroy( hHeap );
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|
2014-02-10 16:33:42 +10:00
|
|
|
else if (dwReason == DLL_THREAD_DETACH)
|
|
|
|
{
|
|
|
|
PVOID start;
|
|
|
|
if (NtQueryInformationThread( GetCurrentThread(),
|
|
|
|
9 /* ThreadQuerySetWin32StartAddress */,
|
|
|
|
&start, sizeof(start), NULL ) == 0
|
|
|
|
&& (start == Hooks[0].oldfunc || start == Hooks[1].oldfunc
|
|
|
|
|| start == Hooks[0].apifunc || start == Hooks[1].apifunc))
|
|
|
|
{
|
2017-07-25 18:18:34 +10:00
|
|
|
DEBUGSTR( 2, "Injection detected" );
|
2014-02-10 16:33:42 +10:00
|
|
|
HookAPIAllMod( Hooks, FALSE, TRUE );
|
|
|
|
}
|
|
|
|
}
|
Exclude modules from being hooked; hook only selected GUI programs.
Added environment variable ANSICON_EXC to specify modules that should not be
hooked. This should work around the nvd3d9wrap.dll issue. Since it helps to
know what the modules are, logging is now always available, controlled by -l
or ANSICON_LOG. A side-effect caused debugstr.c to move to util.c.
GUI programs are once again not hooked, unless run by "ansicon" directly or in
the ANSICON_GUI environment variable. Since not hooking still leaves ANSICON in
the environment, created ANSICON_VER as a dynamic-only variable, which can also
serve as a version check.
Due to an email requesting a reverse video option, realised I always take the
current attributes as default. This means if you turned on reverse and ran a
program, it would take the reverse as its default. Created ANSICON_DEF variable
to explicitly set the default attribute, using the current if it doesn't exist.
The reverse video option is done via a "negative" attribute (e.g. "-m-f0" is
reversed black on white, meaning you'll get white on black, with foreground
sequences changing the background). (The difference from "\e[7m" is that it
won't be reset on "\e[m".)
A child program will inherit the parent's modes (but not shift); the parent will
read the child's modes on exit (but not unload). The exception is "ansicon",
which will always start with the default modes and leave the parent unchanged.
Improved the AutoRun entry, only running "ansicon" if ANSICON_VER doesn't exist.
The "ansicon" command is always first.
Stopped -u implying -p; return the program's exit code; don't restore the
original color when just using -p; output error messages to stderr.
2011-12-14 20:53:51 +10:00
|
|
|
return bResult;
|
2010-11-08 15:31:01 +10:00
|
|
|
}
|