SDB: Upgraded ansicon version 1.66 95/22395/3
authorshingil.kang <shingil.kang@samsung.com>
Tue, 3 Jun 2014 02:17:56 +0000 (11:17 +0900)
committershingil.kang <shingil.kang@samsung.com>
Tue, 3 Jun 2014 02:54:54 +0000 (11:54 +0900)
Change-Id: I29e7ebda52c434e5949b0b76ab3b2eeef60442c0
Signed-off-by: shingil.kang <shingil.kang@samsung.com>
24 files changed:
ansicon/ANSI-LLW.c [deleted file]
ansicon/ANSI.c [changed mode: 0755->0644]
ansicon/COPYING.MinGW-w64-runtime.txt [deleted file]
ansicon/G1.bat [changed mode: 0755->0644]
ansicon/G1.txt [changed mode: 0755->0644]
ansicon/LICENSE.txt [new file with mode: 0644]
ansicon/ansi.rc [changed mode: 0755->0644]
ansicon/ansicon.c [changed mode: 0755->0644]
ansicon/ansicon.h [changed mode: 0755->0644]
ansicon/ansicon.rc [changed mode: 0755->0644]
ansicon/injdll32.c [changed mode: 0755->0644]
ansicon/injdll64.c [changed mode: 0755->0644]
ansicon/makefile [deleted file]
ansicon/makefile.gcc [new file with mode: 0644]
ansicon/makefile.vc [changed mode: 0755->0644]
ansicon/proctype.c [changed mode: 0755->0644]
ansicon/readme.txt [changed mode: 0755->0644]
ansicon/sequences.txt [new file with mode: 0644]
ansicon/util.c [changed mode: 0755->0644]
ansicon/version.h [changed mode: 0755->0644]
ansicon/wow64.h [changed mode: 0755->0644]
ansicon/x86/ANSI32.dll [new file with mode: 0644]
ansicon/x86/ansicon.exe [new file with mode: 0644]
package/build.windows

diff --git a/ansicon/ANSI-LLW.c b/ansicon/ANSI-LLW.c
deleted file mode 100755 (executable)
index 28991f0..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-  ANSI-LLW.c - Output the 32-bit address of LoadLibraryW.
-
-  Jason Hood, 13 November, 2010 (LLA version 5 September, 2010).
-
-  I don't know of a method to retrieve the 32-bit address of a function in
-  64-bit code, so this is a simple workaround.
-
-  18 December, 2010: Initially I used GetProcAddress, but then I thought that
-  was silly, why don't I just return LoadLibraryW directly?  That worked fine
-  for TDM64 and VC, but MinGW32 would return the address of the jump to the
-  function, not the function itself.  Not so silly after all.
-*/
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-int main( void )
-{
-  return (DWORD)GetProcAddress( GetModuleHandle( "kernel32.dll" ),
-                               "LoadLibraryW" );
-}
old mode 100755 (executable)
new mode 100644 (file)
index 3907252..c5b08a7
-/*
-  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.
-
-  v1.31, 13 & 19 November, 2010:
-    fix multibyte conversion problems.
-
-  v1.32, 4 to 22 December, 2010:
-    test for lpNumberOfCharsWritten/lpNumberOfBytesWritten being NULL;
-    recognise DSR and xterm window title;
-    ignore sequences starting with \e[? & \e[>;
-    close the handles opened by CreateProcess.
-
-  v1.40, 25 & 26 February, 1 March, 2011:
-    hook GetProcAddress, addresses issues with .NET (work with PowerShell);
-    implement SO & SI to use the DEC Special Graphics Character Set (enables
-     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).
-
-  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.
-
-  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.
-
-  v1.52, 10 April, 1 & 2 June, 2012:
-    use ansicon.exe to enable 32-bit to inject into 64-bit;
-    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).
-
-  v1.53, 12 June, 2012:
-    fixed Update_GRM when running multiple processes (e.g. "cl /MP").
-*/
-
-#include "ansicon.h"
-#include "version.h"
-#include <tlhelp32.h>
-
-#define isdigit(c) ('0' <= (c) && (c) <= '9')
-
-#ifdef __GNUC__
-#define SHARED __attribute__((shared, section(".share")))
-#else
-#pragma section(".shared", read,write,shared)
-#define SHARED __declspec(allocate(".shared"))
-#endif
-
-
-// ========== Global variables and constants
-
-HANDLE   hConOut;              // handle to CONOUT$
-
-#define ESC    '\x1B'          // ESCape character
-#define BEL    '\x07'
-#define SO     '\x0E'          // Shift Out
-#define SI     '\x0F'          // Shift In
-
-#define MAX_ARG 16             // max number of args in an escape sequence
-int   state;                   // automata state
-TCHAR prefix;                  // escape sequence prefix ( '[', ']' or '(' );
-TCHAR prefix2;                 // secondary prefix ( '?' or '>' );
-TCHAR suffix;                  // escape sequence suffix
-int   es_argc;                 // escape sequence args count
-int   es_argv[MAX_ARG];        // escape sequence args
-TCHAR Pt_arg[MAX_PATH*2];      // text parameter for Operating System Command
-int   Pt_len;
-BOOL  shifted;
-
-
-// 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[] =
-{
-  ' ',          // _ - blank
-  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  '~'
-
-
-// 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
-
-const BYTE foregroundcolor[8] =
-{
-  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
-};
-
-const BYTE backgroundcolor[8] =
-{
-  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
-};
-
-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
-};
-
-GRM grm;
-
-// saved cursor position
-COORD SavePos;
-
-// Variables to enable copying attributes between processes.
-SHARED DWORD s_pid;
-SHARED GRM   s_grm;
-SHARED DWORD s_flag;
-#define GRM_INIT 1
-#define GRM_EXIT 2
-
-
-
-// Wait for the child process to finish, then update our GRM to the child's.
-DWORD WINAPI UpdateGRM( LPVOID child_pi )
-{
-  DWORD  pid  = ((LPPROCESS_INFORMATION)child_pi)->dwProcessId;
-  HANDLE proc = ((LPPROCESS_INFORMATION)child_pi)->hProcess;
-  free( child_pi );
-
-  WaitForSingleObject( proc, INFINITE );
-  CloseHandle( proc );
-
-  if (s_flag == GRM_EXIT && s_pid == pid)
-  {
-    s_flag = 0;
-    grm = s_grm;
-  }
-
-  return 0;
-}
-
-
-// Search an environment variable for a string.
-BOOL search_env( LPCTSTR var, LPCTSTR val )
-{
-  static LPTSTR env;
-  static DWORD env_len;
-  DWORD len;
-  BOOL not;
-
-  len = GetEnvironmentVariable( var, env, env_len );
-  if (len == 0)
-    return FALSE;
-
-  if (len > env_len)
-  {
-    LPTSTR tmp = realloc( env, TSIZE(len) );
-    if (tmp == NULL)
-      return FALSE;
-    env = tmp;
-    env_len = len;
-    GetEnvironmentVariable( var, env, env_len );
-  }
-
-  not = (*env == '!');
-  if (not && env[1] == '\0')
-    return TRUE;
-
-  for (var = wcstok( env + not, L";" ); var; var = wcstok( NULL, L";" ))
-    if (_wcsicmp( val, var ) == 0)
-      return !not;
-
-  return not;
-}
-
-
-// ========== Print Buffer functions
-
-#define BUFFER_SIZE 2048
-
-int   nCharInBuffer;
-WCHAR ChBuffer[BUFFER_SIZE];
-
-//-----------------------------------------------------------------------------
-//   FlushBuffer()
-// Writes the buffer to the console and empties it.
-//-----------------------------------------------------------------------------
-
-void FlushBuffer( void )
-{
-  DWORD nWritten;
-  if (nCharInBuffer <= 0) return;
-  WriteConsole( hConOut, ChBuffer, nCharInBuffer, &nWritten, NULL );
-  nCharInBuffer = 0;
-}
-
-//-----------------------------------------------------------------------------
-//   PushBuffer( WCHAR c )
-// Adds a character in the buffer.
-//-----------------------------------------------------------------------------
-
-void PushBuffer( WCHAR c )
-{
-  if (shifted && c >= FIRST_G1 && c <= LAST_G1)
-    c = G1[c-FIRST_G1];
-  ChBuffer[nCharInBuffer] = c;
-  if (++nCharInBuffer == BUFFER_SIZE)
-    FlushBuffer();
-}
-
-//-----------------------------------------------------------------------------
-//   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 );
-
-  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;
-  for (; *seq; ++seq)
-  {
-    in.Event.KeyEvent.uChar.UnicodeChar = *seq;
-    WriteConsoleInput( hStdIn, &in, 1, &out );
-  }
-}
-
-// ========== 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;
-  CONSOLE_CURSOR_INFO CursInfo;
-  DWORD len, NumberOfCharsWritten;
-  COORD Pos;
-  SMALL_RECT Rect;
-  CHAR_INFO  CharInfo;
-
-  if (prefix == '[')
-  {
-    if (prefix2 == '?' && (suffix == 'h' || suffix == 'l'))
-    {
-      if (es_argc == 1 && es_argv[0] == 25)
-      {
-       GetConsoleCursorInfo( hConOut, &CursInfo );
-       CursInfo.bVisible = (suffix == 'h');
-       SetConsoleCursorInfo( hConOut, &CursInfo );
-       return;
-      }
-    }
-    // Ignore any other \e[? or \e[> sequences.
-    if (prefix2 != 0)
-      return;
-
-    GetConsoleScreenBufferInfo( hConOut, &Info );
-    switch (suffix)
-    {
-      case 'm':
-       if (es_argc == 0) es_argv[es_argc++] = 0;
-       for (i = 0; i < es_argc; i++)
-       {
-         if (30 <= es_argv[i] && es_argv[i] <= 37)
-           grm.foreground = es_argv[i] - 30;
-         else if (40 <= es_argv[i] && es_argv[i] <= 47)
-           grm.background = es_argv[i] - 40;
-         else switch (es_argv[i])
-         {
-           case 0:
-           case 39:
-           case 49:
-           {
-             TCHAR def[4];
-             int   a;
-             *def = '7'; def[1] = '\0';
-             GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) );
-             a = wcstol( def, NULL, 16 );
-             grm.reverse = FALSE;
-             if (a < 0)
-             {
-               grm.reverse = TRUE;
-               a = -a;
-             }
-             if (es_argv[i] != 49)
-               grm.foreground = attr2ansi[a & 7];
-             if (es_argv[i] != 39)
-               grm.background = attr2ansi[(a >> 4) & 7];
-             if (es_argv[i] == 0)
-             {
-               if (es_argc == 1)
-               {
-                 grm.bold      = a & FOREGROUND_INTENSITY;
-                 grm.underline = a & BACKGROUND_INTENSITY;
-               }
-               else
-               {
-                 grm.bold      = 0;
-                 grm.underline = 0;
-               }
-               grm.rvideo    = 0;
-               grm.concealed = 0;
-             }
-           }
-           break;
-
-           case  1: grm.bold      = FOREGROUND_INTENSITY; break;
-           case  5: // blink
-           case  4: grm.underline = BACKGROUND_INTENSITY; break;
-           case  7: grm.rvideo    = 1; break;
-           case  8: grm.concealed = 1; break;
-           case 21: // oops, this actually turns on double underline
-           case 22: grm.bold      = 0; break;
-           case 25:
-           case 24: grm.underline = 0; break;
-           case 27: grm.rvideo    = 0; break;
-           case 28: grm.concealed = 0; break;
-         }
-       }
-       if (grm.concealed)
-       {
-         if (grm.rvideo)
-         {
-           attribut = foregroundcolor[grm.foreground]
-                    | backgroundcolor[grm.foreground];
-           if (grm.bold)
-             attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
-         }
-         else
-         {
-           attribut = foregroundcolor[grm.background]
-                    | backgroundcolor[grm.background];
-           if (grm.underline)
-             attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
-         }
-       }
-       else if (grm.rvideo)
-       {
-         attribut = foregroundcolor[grm.background]
-                  | backgroundcolor[grm.foreground];
-         if (grm.bold)
-           attribut |= BACKGROUND_INTENSITY;
-         if (grm.underline)
-           attribut |= FOREGROUND_INTENSITY;
-       }
-       else
-         attribut = foregroundcolor[grm.foreground] | grm.bold
-                  | backgroundcolor[grm.background] | grm.underline;
-       if (grm.reverse)
-         attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4);
-       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])
-       {
-         case 0:               // ESC[0J erase from cursor to end of display
-           len = (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X
-                 + Info.dwSize.X - Info.dwCursorPosition.X - 1;
-           FillConsoleOutputCharacter( hConOut, ' ', len,
-                                       Info.dwCursorPosition,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,
-                                       Info.dwCursorPosition,
-                                       &NumberOfCharsWritten );
-         return;
-
-         case 1:               // ESC[1J erase from start to cursor.
-           Pos.X = 0;
-           Pos.Y = 0;
-           len   = Info.dwCursorPosition.Y * Info.dwSize.X
-                   + Info.dwCursorPosition.X + 1;
-           FillConsoleOutputCharacter( hConOut, ' ', len, Pos,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,
-                                       &NumberOfCharsWritten );
-           return;
-
-         case 2:               // ESC[2J Clear screen and home cursor
-           Pos.X = 0;
-           Pos.Y = 0;
-           len   = Info.dwSize.X * Info.dwSize.Y;
-           FillConsoleOutputCharacter( hConOut, ' ', len, Pos,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,
-                                       &NumberOfCharsWritten );
-           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])
-       {
-         case 0:               // ESC[0K Clear to end of line
-           len = Info.srWindow.Right - Info.dwCursorPosition.X + 1;
-           FillConsoleOutputCharacter( hConOut, ' ', len,
-                                       Info.dwCursorPosition,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,
-                                       Info.dwCursorPosition,
-                                       &NumberOfCharsWritten );
-         return;
-
-         case 1:               // ESC[1K Clear from start of line to cursor
-           Pos.X = 0;
-           Pos.Y = Info.dwCursorPosition.Y;
-           FillConsoleOutputCharacter( hConOut, ' ',
-                                       Info.dwCursorPosition.X + 1, Pos,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes,
-                                       Info.dwCursorPosition.X + 1, Pos,
-                                       &NumberOfCharsWritten );
-         return;
-
-         case 2:               // ESC[2K Clear whole line.
-           Pos.X = 0;
-           Pos.Y = Info.dwCursorPosition.Y;
-           FillConsoleOutputCharacter( hConOut, ' ', Info.dwSize.X, Pos,
-                                       &NumberOfCharsWritten );
-           FillConsoleOutputAttribute( hConOut, Info.wAttributes,
-                                       Info.dwSize.X, Pos,
-                                       &NumberOfCharsWritten );
-         return;
-
-         default:
-         return;
-       }
-
-      case 'X':                 // ESC[#X Erase # characters.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X
-       if (es_argc != 1) return;
-       FillConsoleOutputCharacter( hConOut, ' ', es_argv[0],
-                                   Info.dwCursorPosition,
-                                   &NumberOfCharsWritten );
-       FillConsoleOutputAttribute( hConOut, Info.wAttributes, es_argv[0],
-                                   Info.dwCursorPosition,
-                                   &NumberOfCharsWritten );
-      return;
-
-      case 'L':                 // ESC[#L Insert # blank lines.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L
-       if (es_argc != 1) return;
-       Rect.Left   = 0;
-       Rect.Top    = Info.dwCursorPosition.Y;
-       Rect.Right  = Info.dwSize.X - 1;
-       Rect.Bottom = Info.dwSize.Y - 1;
-       Pos.X = 0;
-       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];
-       CharInfo.Char.UnicodeChar = ' ';
-       CharInfo.Attributes = Info.wAttributes;
-       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );
-      return;
-
-      case 'M':                 // ESC[#M Delete # lines.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M
-       if (es_argc != 1) return;
-       if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y)
-         es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y;
-       Rect.Left   = 0;
-       Rect.Top    = Info.dwCursorPosition.Y + es_argv[0];
-       Rect.Right  = Info.dwSize.X - 1;
-       Rect.Bottom = Info.dwSize.Y - 1;
-       Pos.X = 0;
-       Pos.Y = Info.dwCursorPosition.Y;
-       CharInfo.Char.UnicodeChar = ' ';
-       CharInfo.Attributes = Info.wAttributes;
-       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );
-      return;
-
-      case 'P':                 // ESC[#P Delete # characters.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P
-       if (es_argc != 1) return;
-       if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1)
-         es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X;
-       Rect.Left   = Info.dwCursorPosition.X + es_argv[0];
-       Rect.Top    = Info.dwCursorPosition.Y;
-       Rect.Right  = Info.dwSize.X - 1;
-       Rect.Bottom = Info.dwCursorPosition.Y;
-       CharInfo.Char.UnicodeChar = ' ';
-       CharInfo.Attributes = Info.wAttributes;
-       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Info.dwCursorPosition,
-                                  &CharInfo );
-      return;
-
-      case '@':                 // ESC[#@ Insert # blank characters.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@
-       if (es_argc != 1) return;
-       if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1)
-         es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X;
-       Rect.Left   = Info.dwCursorPosition.X;
-       Rect.Top    = Info.dwCursorPosition.Y;
-       Rect.Right  = Info.dwSize.X - 1 - es_argv[0];
-       Rect.Bottom = Info.dwCursorPosition.Y;
-       Pos.X = Info.dwCursorPosition.X + es_argv[0];
-       Pos.Y = Info.dwCursorPosition.Y;
-       CharInfo.Char.UnicodeChar = ' ';
-       CharInfo.Attributes = Info.wAttributes;
-       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );
-      return;
-
-      case 'k':                 // ESC[#k
-      case 'A':                 // ESC[#A Moves cursor up # lines
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A
-       if (es_argc != 1) return;
-       Pos.Y = Info.dwCursorPosition.Y - es_argv[0];
-       if (Pos.Y < 0) Pos.Y = 0;
-       Pos.X = Info.dwCursorPosition.X;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'e':                 // ESC[#e
-      case 'B':                 // ESC[#B Moves cursor down # lines
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B
-       if (es_argc != 1) return;
-       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];
-       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;
-       Pos.X = Info.dwCursorPosition.X;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'a':                 // ESC[#a
-      case 'C':                 // ESC[#C Moves cursor forward # spaces
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C
-       if (es_argc != 1) return;
-       Pos.X = Info.dwCursorPosition.X + es_argv[0];
-       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;
-       Pos.Y = Info.dwCursorPosition.Y;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'j':                 // ESC[#j
-      case 'D':                 // ESC[#D Moves cursor back # spaces
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D
-       if (es_argc != 1) return;
-       Pos.X = Info.dwCursorPosition.X - es_argv[0];
-       if (Pos.X < 0) Pos.X = 0;
-       Pos.Y = Info.dwCursorPosition.Y;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'E':                 // ESC[#E Moves cursor down # lines, column 1.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E
-       if (es_argc != 1) return;
-       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];
-       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;
-       Pos.X = 0;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'F':                 // ESC[#F Moves cursor up # lines, column 1.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F
-       if (es_argc != 1) return;
-       Pos.Y = Info.dwCursorPosition.Y - es_argv[0];
-       if (Pos.Y < 0) Pos.Y = 0;
-       Pos.X = 0;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case '`':                 // ESC[#`
-      case 'G':                 // ESC[#G Moves cursor column # in current row.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G
-       if (es_argc != 1) return;
-       Pos.X = es_argv[0] - 1;
-       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;
-       if (Pos.X < 0) Pos.X = 0;
-       Pos.Y = Info.dwCursorPosition.Y;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'd':                 // ESC[#d Moves cursor row #, current column.
-       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d
-       if (es_argc != 1) return;
-       Pos.Y = es_argv[0] - 1;
-       if (Pos.Y < 0) Pos.Y = 0;
-       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 'f':                 // ESC[#;#f
-      case 'H':                 // ESC[#;#H Moves cursor to line #, column #
-       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;
-       if (Pos.X < 0) Pos.X = 0;
-       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;
-       Pos.Y = es_argv[0] - 1;
-       if (Pos.Y < 0) Pos.Y = 0;
-       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;
-       SetConsoleCursorPosition( hConOut, Pos );
-      return;
-
-      case 's':                 // ESC[s Saves cursor position for recall later
-       if (es_argc != 0) return;
-       SavePos = Info.dwCursorPosition;
-      return;
-
-      case 'u':                 // ESC[u Return to saved cursor position
-       if (es_argc != 0) return;
-       SetConsoleCursorPosition( hConOut, SavePos );
-      return;
-
-      case 'n':                 // ESC[#n Device status report
-       if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored
-       switch (es_argv[0])
-       {
-         case 5:               // ESC[5n Report status
-           SendSequence( L"\33[0n" ); // "OK"
-         return;
-
-         case 6:               // ESC[6n Report cursor position
-         {
-           TCHAR buf[32];
-           wsprintf( buf, L"\33[%d;%dR", Info.dwCursorPosition.Y + 1,
-                                         Info.dwCursorPosition.X + 1 );
-           SendSequence( buf );
-         }
-         return;
-
-         default:
-         return;
-       }
-
-      case 't':                 // ESC[#t Window manipulation
-       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;
-
-      default:
-      return;
-    }
-  }
-  else // (prefix == ']')
-  {
-    // Ignore any \e]? or \e]> sequences.
-    if (prefix2 != 0)
-      return;
-
-    if (es_argc == 1 && es_argv[0] == 0) // ESC]0;titleST
-    {
-      SetConsoleTitle( Pt_arg );
-    }
-  }
-}
-
-//-----------------------------------------------------------------------------
-//   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
-                    )
-{
-  DWORD   i;
-  LPCTSTR s;
-
-  if (hDev != hConOut) // reinit if device has changed
-  {
-    hConOut = hDev;
-    state = 1;
-    shifted = FALSE;
-  }
-  for (i = nNumberOfBytesToWrite, s = (LPCTSTR)lpBuffer; i > 0; i--, s++)
-  {
-    if (state == 1)
-    {
-      if (*s == ESC) state = 2;
-      else if (*s == SO) shifted = TRUE;
-      else if (*s == SI) shifted = FALSE;
-      else PushBuffer( *s );
-    }
-    else if (state == 2)
-    {
-      if (*s == ESC) ; // \e\e...\e == \e
-      else if ((*s == '[') || (*s == ']'))
-      {
-       FlushBuffer();
-       prefix = *s;
-       prefix2 = 0;
-       state = 3;
-       Pt_len = 0;
-       *Pt_arg = '\0';
-      }
-      else if (*s == ')' || *s == '(') state = 6;
-      else state = 1;
-    }
-    else if (state == 3)
-    {
-      if (isdigit( *s ))
-      {
-        es_argc = 0;
-       es_argv[0] = *s - '0';
-        state = 4;
-      }
-      else if (*s == ';')
-      {
-        es_argc = 1;
-        es_argv[0] = 0;
-       es_argv[1] = 0;
-        state = 4;
-      }
-      else if (*s == '?' || *s == '>')
-      {
-       prefix2 = *s;
-      }
-      else
-      {
-        es_argc = 0;
-        suffix = *s;
-        InterpretEscSeq();
-        state = 1;
-      }
-    }
-    else if (state == 4)
-    {
-      if (isdigit( *s ))
-      {
-       es_argv[es_argc] = 10 * es_argv[es_argc] + (*s - '0');
-      }
-      else if (*s == ';')
-      {
-        if (es_argc < MAX_ARG-1) es_argc++;
-       es_argv[es_argc] = 0;
-       if (prefix == ']')
-         state = 5;
-      }
-      else
-      {
-       es_argc++;
-        suffix = *s;
-        InterpretEscSeq();
-        state = 1;
-      }
-    }
-    else if (state == 5)
-    {
-      if (*s == BEL)
-      {
-       Pt_arg[Pt_len] = '\0';
-        InterpretEscSeq();
-        state = 1;
-      }
-      else if (*s == '\\' && Pt_len > 0 && Pt_arg[Pt_len-1] == ESC)
-      {
-       Pt_arg[--Pt_len] = '\0';
-        InterpretEscSeq();
-        state = 1;
-      }
-      else if (Pt_len < lenof(Pt_arg)-1)
-       Pt_arg[Pt_len++] = *s;
-    }
-    else if (state == 6)
-    {
-      // Ignore it (ESC ) 0 is implicit; nothing else is supported).
-      state = 1;
-    }
-  }
-  FlushBuffer();
-  if (lpNumberOfBytesWritten != NULL)
-    *lpNumberOfBytesWritten = nNumberOfBytesToWrite - i;
-  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.
-
-// Macro for adding pointers/DWORDs together without C arithmetic interfering
-#define MakeVA( cast, offset ) (cast)((DWORD_PTR)(pDosHeader)+(DWORD)(offset))
-
-
-const char APIKernel[]            = "kernel32.dll";
-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-";
-
-typedef struct
-{
-  PCSTR   name;
-  DWORD   len;
-  HMODULE base;
-} API_DATA, *PAPI_DATA;
-
-API_DATA APIs[] =
-{
-  { 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 }
-};
-
-
-HMODULE   hKernel;             // Kernel32 module handle
-HINSTANCE hDllInstance;        // Dll instance handle
-TCHAR    hDllName[MAX_PATH];   // Dll file name
-#if defined(_WIN64) || defined(W32ON64)
-LPTSTR   hDllNameType;         // pointer to process type within above
-#endif
-
-typedef struct
-{
-  PCSTR lib;
-  PSTR name;
-  PROC newfunc;
-  PROC oldfunc;
-  PROC apifunc;
-} HookFn, *PHookFn;
-
-HookFn Hooks[];
-
-const WCHAR zIgnoring[]  = L"Ignoring";
-const WCHAR zHooking[]  = L"Hooking";
-const WCHAR zUnhooking[] = L"Unhooking";
-
-
-//-----------------------------------------------------------------------------
-//   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
-    BOOL    restore            // Restore the original functions
-    )
-{
-  PIMAGE_DOS_HEADER       pDosHeader;
-  PIMAGE_NT_HEADERS       pNTHeader;
-  PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
-  PIMAGE_THUNK_DATA       pThunk;
-  PHookFn                 hook;
-
-  // 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)
-  {
-    DEBUGSTR( 1, L"Image has no DOS header!" );
-    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)
-  {
-    DEBUGSTR( 1, L"Image has no NT header!" );
-    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,
-                       pNTHeader->OptionalHeader.
-                        DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
-                         VirtualAddress );
-
-  // 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++)
-  {
-    BOOL kernel = TRUE;
-    PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );
-    if (_stricmp( pszModName, APIKernel ) != 0)
-    {
-      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)
-         DEBUGSTR( 2, L" %s %S", zIgnoring, pszModName );
-       continue;
-      }
-      kernel = FALSE;
-    }
-    if (log_level & 16)
-      DEBUGSTR( 2, L" Scanning %S", pszModName );
-
-    // 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)
-           patch = (kernel) ? hook->oldfunc : hook->apifunc;
-       }
-       else if ((PROC)pThunk->u1.Function == hook->oldfunc ||
-                (PROC)pThunk->u1.Function == hook->apifunc)
-       {
-         patch = hook->newfunc;
-       }
-       if (patch)
-       {
-         DWORD flOldProtect, flNewProtect, flDummy;
-         MEMORY_BASIC_INFORMATION mbi;
-
-         DEBUGSTR( 3, L"  %S", hook->name );
-         // Get the current protection attributes.
-         VirtualQuery( &pThunk->u1.Function, &mbi, sizeof(mbi) );
-         // Take the access protection flags.
-         flNewProtect = mbi.Protect;
-         // Remove ReadOnly and ExecuteRead flags.
-         flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
-         // Add on ReadWrite flag
-         flNewProtect |= (PAGE_READWRITE);
-         // Change the access protection on the region of committed pages in the
-         // virtual address space of the current process.
-         VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),
-                         flNewProtect, &flOldProtect );
-
-         // Overwrite the original address with the address of the new function.
-         if (!WriteProcessMemory( GetCurrentProcess(),
-                                  &pThunk->u1.Function,
-                                  &patch, sizeof(patch), NULL ))
-         {
-           DEBUGSTR( 1, L"Could not patch!" );
-           return FALSE;
-         }
-
-         // Put the page attributes back the way they were.
-         VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),
-                         flOldProtect, &flDummy );
-       }
-      }
-      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.
-//-----------------------------------------------------------------------------
-
-BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore )
-{
-  HANDLE       hModuleSnap;
-  MODULEENTRY32 me;
-  BOOL         fOk;
-
-  // Take a snapshot of all modules in the current process.
-  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,
-                                         GetCurrentProcessId() );
-
-  if (hModuleSnap == INVALID_HANDLE_VALUE)
-  {
-    DEBUGSTR( 1, L"Failed to create snapshot!" );
-    return FALSE;
-  }
-
-  // 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.
-    if (me.hModule != hDllInstance && me.hModule != hKernel)
-    {
-      if (search_env( L"ANSICON_EXC", me.szModule ))
-      {
-       DEBUGSTR( 2, L"%s %s", zIgnoring, me.szModule );
-       continue;
-      }
-      DEBUGSTR( 2, L"%s %s", (restore) ? zUnhooking : zHooking, me.szModule );
-      // Hook this function in this module.
-      if (!HookAPIOneMod( me.hModule, Hooks, restore ))
-      {
-       CloseHandle( hModuleSnap );
-       return FALSE;
-      }
-    }
-  }
-  CloseHandle( hModuleSnap );
-  DEBUGSTR( 2, L"%s completed", (restore) ? zUnhooking : zHooking );
-  return TRUE;
-}
-
-
-// ========== Child process injection
-
-// 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;
-  BOOL  gui;
-
-  type = ProcessType( child_pi, &gui );
-  if (gui)
-  {
-    TCHAR   app[MAX_PATH];
-    LPTSTR  name;
-    LPCTSTR term = L" \t";
-
-    app[MAX_PATH-1] = '\0';
-    if (lpApp == NULL)
-    {
-      // Extract the program from the command line.  I would use
-      // GetModuleFileNameEx, but it doesn't work when a process is created
-      // suspended and setting up a delay until it does work sometimes
-      // prevents the process running at all.  GetProcessImageFileName works,
-      // but it's not supported in 2K.
-      if (wide)
-      {
-       LPCTSTR pos;
-       for (pos = lpCmd; *pos == ' ' || *pos == '\t'; ++pos) ;
-       if (*pos == '"')
-       {
-         term = L"\"";
-         ++pos;
-       }
-       wcsncpy( app, pos, MAX_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_PATH );
-      }
-      // 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 );
-      if (name)
-       *name = '\0';
-    }
-    else
-    {
-      if (wide)
-       wcsncpy( app, lpApp, MAX_PATH-1 );
-      else
-       MultiByteToWideChar( CP_ACP, 0, lpApp, -1, app, MAX_PATH );
-    }
-    name = get_program_name( app );
-    if (!search_env( L"ANSICON_GUI", name ))
-    {
-      DEBUGSTR( 1, L"  %s", zIgnoring );
-      type = 0;
-    }
-  }
-  if (type != 0)
-  {
-#ifdef _WIN64
-    if (type == 32)
-    {
-      hDllNameType[0] = '3';
-      hDllNameType[1] = '2';
-      InjectDLL32( child_pi, hDllName );
-    }
-    else
-    {
-      hDllNameType[0] = '6';
-      hDllNameType[1] = '4';
-      InjectDLL64( child_pi, hDllName );
-    }
-#else
-#ifdef W32ON64
-    if (type == 64)
-    {
-      TCHAR args[64];
-      STARTUPINFO si;
-      PROCESS_INFORMATION pi;
-      wcscpy( hDllNameType, L"CON.exe" );
-      wsprintf( args, L"ansicon -P%lu:%lu",
-                     child_pi->dwProcessId, child_pi->dwThreadId );
-      ZeroMemory( &si, sizeof(si) );
-      si.cb = sizeof(si);
-      if (CreateProcess( hDllName, args, NULL, NULL, FALSE, 0, NULL, NULL,
-                        &si, &pi ))
-      {
-       WaitForSingleObject( pi.hProcess, INFINITE );
-       CloseHandle( pi.hProcess );
-       CloseHandle( pi.hThread );
-      }
-      else
-       DEBUGSTR( 1, L"Could not execute \"%s\"", hDllName );
-      wcscpy( hDllNameType, L"32.dll" );
-    }
-    else
-#endif
-    InjectDLL32( child_pi, hDllName );
-#endif
-    if (!gui && !(dwCreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
-    {
-      LPPROCESS_INFORMATION cpi;
-      s_pid = child_pi->dwProcessId;
-      s_grm = grm;
-      s_flag = GRM_INIT;
-      cpi = malloc( sizeof(*cpi) );
-      cpi->dwProcessId = child_pi->dwProcessId;
-      DuplicateHandle( GetCurrentProcess(), child_pi->hProcess,
-                      GetCurrentProcess(), &cpi->hProcess, 0, FALSE,
-                      DUPLICATE_SAME_ACCESS );
-      CloseHandle( CreateThread( NULL, 4096, UpdateGRM, cpi, 0, NULL ) );
-    }
-  }
-
-  if (!(dwCreationFlags & CREATE_SUSPENDED))
-    ResumeThread( child_pi->hThread );
-
-  if (lpi)
-  {
-    memcpy( lpi, child_pi, sizeof(PROCESS_INFORMATION) );
-  }
-  else
-  {
-    CloseHandle( child_pi->hThread );
-    CloseHandle( child_pi->hProcess );
-  }
-}
-
-
-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 )
-{
-  PROCESS_INFORMATION child_pi;
-
-  if (!CreateProcessA( lpApplicationName,
-                      lpCommandLine,
-                      lpThreadAttributes,
-                      lpProcessAttributes,
-                      bInheritHandles,
-                      dwCreationFlags | CREATE_SUSPENDED,
-                      lpEnvironment,
-                      lpCurrentDirectory,
-                      lpStartupInfo,
-                      &child_pi ))
-    return FALSE;
-
-  DEBUGSTR( 1, L"CreateProcessA: (%lu) \"%S\", \"%S\"",
-           child_pi.dwProcessId,
-           (lpApplicationName == NULL) ? "" : lpApplicationName,
-           (lpCommandLine == NULL) ? "" : lpCommandLine );
-  Inject( dwCreationFlags, lpProcessInformation, &child_pi,
-         FALSE, lpApplicationName, lpCommandLine );
-
-  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 )
-{
-  PROCESS_INFORMATION child_pi;
-
-  if (!CreateProcessW( lpApplicationName,
-                      lpCommandLine,
-                      lpThreadAttributes,
-                      lpProcessAttributes,
-                      bInheritHandles,
-                      dwCreationFlags | CREATE_SUSPENDED,
-                      lpEnvironment,
-                      lpCurrentDirectory,
-                      lpStartupInfo,
-                      &child_pi ))
-    return FALSE;
-
-  DEBUGSTR( 1, L"CreateProcessW: (%lu) \"%s\", \"%s\"",
-           child_pi.dwProcessId,
-           (lpApplicationName == NULL) ? L"" : lpApplicationName,
-           (lpCommandLine == NULL) ? L"" : lpCommandLine );
-  Inject( dwCreationFlags, lpProcessInformation, &child_pi,
-         TRUE, lpApplicationName, lpCommandLine );
-
-  return TRUE;
-}
-
-
-FARPROC WINAPI MyGetProcAddress( HMODULE hModule, LPCSTR lpProcName )
-{
-  PHookFn hook;
-  FARPROC proc;
-
-  proc = GetProcAddress( hModule, lpProcName );
-
-  if (proc)
-  {
-    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)
-      {
-       DEBUGSTR( 3, L"GetProcAddress: %S (ignoring)", lpProcName );
-       return proc;
-      }
-      for (hook = Hooks + 2; hook->name; ++hook)
-      {
-       if (proc == hook->oldfunc)
-       {
-         DEBUGSTR( 3, L"GetProcAddress: %S", lpProcName );
-         return hook->newfunc;
-       }
-      }
-    }
-    else
-    {
-      PAPI_DATA api;
-      for (api = APIs; api->name; ++api)
-      {
-       if (hModule == api->base)
-       {
-         if (proc == Hooks[0].apifunc || proc == Hooks[1].apifunc)
-         {
-           DEBUGSTR( 3, L"GetProcAddress: %S (ignoring)", lpProcName );
-           return proc;
-         }
-         for (hook = Hooks + 2; hook->name; ++hook)
-         {
-           if (proc == hook->apifunc)
-           {
-             DEBUGSTR( 3, L"GetProcAddress: %S", lpProcName );
-             return hook->newfunc;
-           }
-         }
-         break;
-       }
-      }
-    }
-  }
-
-  return proc;
-}
-
-
-void HookLibrary( HMODULE hMod, LPCVOID lpFileName, BOOL wide, LPCSTR funcName )
-{
-  LPCWSTR name;
-  WCHAR   wname[MAX_PATH];
-
-  if (hMod && hMod != hKernel)
-  {
-    if (!wide)
-    {
-      MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
-                          lpFileName, -1, wname, MAX_PATH );
-      lpFileName = wname;
-    }
-    name = wcsrchr( lpFileName, '\\' );
-    if (name == NULL)
-      name = lpFileName;
-    else
-      ++name;
-    if (search_env( L"ANSICON_EXC", name ))
-      DEBUGSTR( 2, L"%s %s (%S)", zIgnoring, lpFileName, funcName );
-    else
-    {
-      DEBUGSTR( 2, L"%s %s (%S)", zHooking, lpFileName, funcName );
-      HookAPIOneMod( hMod, Hooks, FALSE );
-    }
-  }
-}
-
-
-HMODULE WINAPI MyLoadLibraryA( LPCSTR lpFileName )
-{
-  HMODULE hMod = LoadLibraryA( lpFileName );
-  HookLibrary( hMod, lpFileName, FALSE, "LoadLibraryA" );
-  return hMod;
-}
-
-
-HMODULE WINAPI MyLoadLibraryW( LPCWSTR lpFileName )
-{
-  HMODULE hMod = LoadLibraryW( lpFileName );
-  HookLibrary( hMod, lpFileName, TRUE, "LoadLibraryW" );
-  return hMod;
-}
-
-
-HMODULE WINAPI MyLoadLibraryExA( LPCSTR lpFileName, HANDLE hFile,
-                                DWORD dwFlags )
-{
-  HMODULE hMod = LoadLibraryExA( lpFileName, hFile, dwFlags );
-  if (!(dwFlags & LOAD_LIBRARY_AS_DATAFILE))
-    HookLibrary( hMod, lpFileName, FALSE, "LoadLibraryExA" );
-  return hMod;
-}
-
-
-HMODULE WINAPI MyLoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile,
-                                DWORD dwFlags )
-{
-  HMODULE hMod = LoadLibraryExW( lpFileName, hFile, dwFlags );
-  if (!(dwFlags & LOAD_LIBRARY_AS_DATAFILE))
-    HookLibrary( hMod, lpFileName, TRUE, "LoadLibraryExW" );
-  return hMod;
-}
-
-
-//-----------------------------------------------------------------------------
-//   MyWrite...
-// It is the new function that must replace the original Write... function.
-// This function have exactly the same signature as the original one.
-//-----------------------------------------------------------------------------
-
-BOOL
-WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
-                       DWORD nNumberOfCharsToWrite,
-                       LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )
-{
-  DWORD  Mode;
-  LPWSTR buf;
-  DWORD  len;
-  BOOL  rc = TRUE;
-
-  // if we write in a console buffer with processed output
-  if (GetConsoleMode( hCon, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
-  {
-    UINT cp = GetConsoleOutputCP();
-    DEBUGSTR( 4, L"\33WriteConsoleA: %lu \"%.*S\"",
-             nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
-    len = MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, NULL,0 );
-    buf = malloc( TSIZE(len) );
-    if (buf == NULL)
-    {
-      if (lpNumberOfCharsWritten != NULL)
-       *lpNumberOfCharsWritten = 0;
-      return (nNumberOfCharsToWrite == 0);
-    }
-    MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, buf, len );
-    rc = ParseAndPrintString( hCon, buf, len, lpNumberOfCharsWritten );
-    free( buf );
-    if (rc && lpNumberOfCharsWritten != NULL &&
-             *lpNumberOfCharsWritten != nNumberOfCharsToWrite)
-    {
-      // 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.
-      if (search_env( L"ANSICON_API", prog ))
-       *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
-    }
-    return rc;
-  }
-
-  return WriteConsoleA( hCon, lpBuffer, nNumberOfCharsToWrite,
-                       lpNumberOfCharsWritten, lpReserved );
-
-}
-
-BOOL
-WINAPI MyWriteConsoleW( HANDLE hCon, LPCVOID lpBuffer,
-                       DWORD nNumberOfCharsToWrite,
-                       LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )
-{
-  DWORD Mode;
-  if (GetConsoleMode( hCon, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
-  {
-    DEBUGSTR( 4, L"\33WriteConsoleW: %lu \"%.*s\"",
-             nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
-    return ParseAndPrintString( hCon, lpBuffer,
-                               nNumberOfCharsToWrite,
-                               lpNumberOfCharsWritten );
-  }
-
-  return WriteConsoleW( hCon, lpBuffer, nNumberOfCharsToWrite,
-                       lpNumberOfCharsWritten, lpReserved );
-}
-
-BOOL
-WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
-                   LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped )
-{
-  DWORD Mode;
-  if (GetConsoleMode( hFile, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
-  {
-    DEBUGSTR( 4, L"WriteFile->" );
-    return MyWriteConsoleA( hFile, lpBuffer,
-                           nNumberOfBytesToWrite,
-                           lpNumberOfBytesWritten,
-                           lpOverlapped );
-  }
-
-  // here, WriteFile is the old function (this module is not hooked)
-  return WriteFile( hFile, lpBuffer, nNumberOfBytesToWrite,
-                   lpNumberOfBytesWritten, lpOverlapped );
-}
-
-
-#define HHFILE (HANDLE)(DWORD_PTR)
-
-UINT
-WINAPI My_lwrite( HFILE hFile, LPCSTR lpBuffer, UINT uBytes )
-{
-  DWORD Mode, written;
-  if (GetConsoleMode( HHFILE hFile, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
-  {
-    DEBUGSTR( 4, L"_lwrite->" );
-    MyWriteConsoleA( HHFILE hFile, lpBuffer, uBytes, &written, NULL );
-    return written;
-  }
-
-  return _lwrite( hFile, lpBuffer, uBytes );
-}
-
-long
-WINAPI My_hwrite( HFILE hFile, LPCSTR lpBuffer, long lBytes )
-{
-  DWORD Mode, written;
-  if (GetConsoleMode( HHFILE hFile, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
-  {
-    DEBUGSTR( 4, L"_hwrite->" );
-    MyWriteConsoleA( HHFILE hFile, lpBuffer, lBytes, &written, NULL );
-    return written;
-  }
-
-  return _hwrite( hFile, lpBuffer, lBytes );
-}
-
-
-// ========== Environment variable
-
-void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )
-{
-  CONSOLE_SCREEN_BUFFER_INFO csbi;
-  TCHAR buf[64];
-
-  if (pcsbi == NULL)
-  {
-    HANDLE hConOut;
-    hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
-                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                     NULL, OPEN_EXISTING, 0, 0 );
-    GetConsoleScreenBufferInfo( hConOut, &csbi );
-    CloseHandle( hConOut );
-    pcsbi = &csbi;
-  }
-
-  wsprintf( buf, L"%dx%d (%dx%d)",
-           pcsbi->dwSize.X, pcsbi->dwSize.Y,
-           pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1,
-           pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 );
-  SetEnvironmentVariable( L"ANSICON", buf );
-}
-
-DWORD
-WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
-{
-  if (lstrcmpiA( lpName, "ANSICON_VER" ) == 0)
-  {
-    if (nSize < sizeof(PVEREA))
-      return sizeof(PVEREA);
-    memcpy( lpBuffer, PVEREA, sizeof(PVEREA) );
-    return sizeof(PVEREA) - 1;
-  }
-
-  if (lstrcmpiA( lpName, "ANSICON" ) == 0)
-    set_ansicon( NULL );
-
-  return GetEnvironmentVariableA( lpName, lpBuffer, nSize );
-}
-
-DWORD
-WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
-{
-  if (lstrcmpi( lpName, L"ANSICON_VER" ) == 0)
-  {
-    if (nSize < lenof(PVERE))
-      return lenof(PVERE);
-    memcpy( lpBuffer, PVERE, sizeof(PVERE) );
-    return lenof(PVERE) - 1;
-  }
-
-  if (lstrcmpi( lpName, L"ANSICON" ) == 0)
-    set_ansicon( NULL );
-
-  return GetEnvironmentVariableW( lpName, lpBuffer, nSize );
-}
-
-
-// ========== Initialisation
-
-HookFn Hooks[] = {
-  // These two are expected first!
-  { APILibraryLoader,     "LoadLibraryA",            (PROC)MyLoadLibraryA,            NULL, NULL },
-  { APILibraryLoader,     "LoadLibraryW",            (PROC)MyLoadLibraryW,            NULL, NULL },
-  { APIProcessThreads,    "CreateProcessA",          (PROC)MyCreateProcessA,          NULL, NULL },
-  { APIProcessThreads,    "CreateProcessW",          (PROC)MyCreateProcessW,          NULL, NULL },
-  { APIProcessEnvironment, "GetEnvironmentVariableA", (PROC)MyGetEnvironmentVariableA, NULL, NULL },
-  { APIProcessEnvironment, "GetEnvironmentVariableW", (PROC)MyGetEnvironmentVariableW, NULL, NULL },
-  { APILibraryLoader,     "GetProcAddress",          (PROC)MyGetProcAddress,          NULL, NULL },
-  { APILibraryLoader,     "LoadLibraryExA",          (PROC)MyLoadLibraryExA,          NULL, NULL },
-  { APILibraryLoader,     "LoadLibraryExW",          (PROC)MyLoadLibraryExW,          NULL, NULL },
-  { APIConsole,           "WriteConsoleA",           (PROC)MyWriteConsoleA,           NULL, NULL },
-  { APIConsole,           "WriteConsoleW",           (PROC)MyWriteConsoleW,           NULL, NULL },
-  { APIFile,              "WriteFile",               (PROC)MyWriteFile,               NULL, NULL },
-  { APIKernel,            "_lwrite",                 (PROC)My_lwrite,                 NULL, NULL },
-  { APIKernel,            "_hwrite",                 (PROC)My_hwrite,                 NULL, NULL },
-  { NULL, NULL, NULL, NULL, NULL }
-};
-
-//-----------------------------------------------------------------------------
-//   OriginalAttr()
-// Determine the original attributes for use by \e[m.
-//-----------------------------------------------------------------------------
-void OriginalAttr( void )
-{
-  HANDLE hConOut;
-  CONSOLE_SCREEN_BUFFER_INFO csbi;
-
-  hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
-                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                   NULL, OPEN_EXISTING, 0, 0 );
-  if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))
-    csbi.wAttributes = 7;
-  CloseHandle( hConOut );
-
-  if (s_flag == GRM_INIT && s_pid == GetCurrentProcessId())
-  {
-    s_flag = 0;
-    grm = s_grm;
-  }
-  else
-  {
-    if (GetEnvironmentVariable( L"ANSICON_REVERSE", NULL, 0 ))
-    {
-      SetEnvironmentVariable( L"ANSICON_REVERSE", NULL );
-      grm.reverse = TRUE;
-      grm.foreground = attr2ansi[(csbi.wAttributes >> 4) & 7];
-      grm.background = attr2ansi[csbi.wAttributes & 7];
-      grm.bold      = (csbi.wAttributes & BACKGROUND_INTENSITY) >> 4;
-      grm.underline  = (csbi.wAttributes & FOREGROUND_INTENSITY) << 4;
-    }
-    else
-    {
-      grm.foreground = attr2ansi[csbi.wAttributes & 7];
-      grm.background = attr2ansi[(csbi.wAttributes >> 4) & 7];
-      grm.bold      = csbi.wAttributes & FOREGROUND_INTENSITY;
-      grm.underline  = csbi.wAttributes & BACKGROUND_INTENSITY;
-    }
-  }
-  if (!GetEnvironmentVariable( L"ANSICON_DEF", NULL, 0 ))
-  {
-    TCHAR  def[4];
-    LPTSTR a = def;
-    if (grm.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 );
-}
-
-
-//-----------------------------------------------------------------------------
-//   DllMain()
-// Function called by the system when processes and threads are initialized
-// and terminated.
-//-----------------------------------------------------------------------------
-
-__declspec(dllexport) // to stop MinGW exporting everything
-BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
-{
-  BOOL   bResult = TRUE;
-  PHookFn hook;
-  TCHAR   logstr[4];
-
-  if (dwReason == DLL_PROCESS_ATTACH)
-  {
-    *logstr = '\0';
-    GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
-    log_level = _wtoi( logstr );
-    prog = get_program_name( NULL );
-#if defined(_WIN64) || defined(W32ON64)
-    hDllNameType = hDllName - 6 +
-#endif
-    GetModuleFileName( hInstance, hDllName, lenof(hDllName) );
-
-    hDllInstance = hInstance; // save Dll instance handle
-    DEBUGSTR( 1, L"hDllInstance = %p", hDllInstance );
-
-    // Get the entry points to the original functions.
-    hKernel = GetModuleHandleA( APIKernel );
-    for (hook = Hooks; hook->name; ++hook)
-      hook->oldfunc = GetProcAddress( hKernel, hook->name );
-
-    bResult = HookAPIAllMod( Hooks, FALSE );
-    OriginalAttr();
-    DisableThreadLibraryCalls( hInstance );
-  }
-  else if (dwReason == DLL_PROCESS_DETACH)
-  {
-    if (lpReserved == NULL)
-    {
-      DEBUGSTR( 1, L"Unloading" );
-      HookAPIAllMod( Hooks, TRUE );
-    }
-    else
-    {
-      DEBUGSTR( 1, L"Terminating" );
-      s_pid = GetCurrentProcessId();
-      s_grm = grm;
-      s_flag = GRM_EXIT;
-    }
-  }
-
-  return bResult;
-}
+/*\r
+  ANSI.c - ANSI escape sequence console driver.\r
+\r
+  Jason Hood, 21 & 22 October, 2005.\r
+\r
+  Derived from ANSI.xs by Jean-Louis Morel, from his Perl package\r
+  Win32::Console::ANSI.  I removed the codepage conversion ("\e(") and added\r
+  WriteConsole hooking.\r
+\r
+  v1.01, 11 & 12 March, 2006:\r
+    disable when console has disabled processed output;\r
+    \e[5m (blink) is the same as \e[4m (underline);\r
+    do not conceal control characters (0 to 31);\r
+    \e[m will restore original color.\r
+\r
+  v1.10, 22 February, 2009:\r
+    fix MyWriteConsoleW for strings longer than the buffer;\r
+    initialise attributes to current;\r
+    hook into child processes.\r
+\r
+  v1.11, 28 February, 2009:\r
+    fix hooking into child processes (only do console executables).\r
+\r
+  v1.12, 9 March, 2009:\r
+    really fix hooking (I didn't realise MinGW didn't generate relocations).\r
+\r
+  v1.13, 21 & 27 March, 2009:\r
+    alternate injection method, to work with DEP;\r
+    use Unicode and the current output code page (not OEMCP).\r
+\r
+  v1.14, 3 April, 2009:\r
+    fix test for empty import section.\r
+\r
+  v1.15, 17 May, 2009:\r
+    properly update lpNumberOfCharsWritten in MyWriteConsoleA.\r
+\r
+  v1.20, 26 & 29 May, 17 to 21 June, 2009:\r
+    create an ANSICON environment variable;\r
+    hook GetEnvironmentVariable to create ANSICON dynamically;\r
+    use another injection method.\r
+\r
+  v1.22, 5 October, 2009:\r
+    hook LoadLibrary to intercept the newly loaded functions.\r
+\r
+  v1.23, 11 November, 2009:\r
+    unload gracefully;\r
+    conceal characters by making foreground same as background;\r
+    reverse the bold/underline attributes, too.\r
+\r
+  v1.25, 15, 20 & 21 July, 2010:\r
+    hook LoadLibraryEx (now cscript works);\r
+    Win7 support.\r
+\r
+  v1.30, 3 August to 7 September, 2010:\r
+    x64 support.\r
+\r
+  v1.31, 13 & 19 November, 2010:\r
+    fix multibyte conversion problems.\r
+\r
+  v1.32, 4 to 22 December, 2010:\r
+    test for lpNumberOfCharsWritten/lpNumberOfBytesWritten being NULL;\r
+    recognise DSR and xterm window title;\r
+    ignore sequences starting with \e[? & \e[>;\r
+    close the handles opened by CreateProcess.\r
+\r
+  v1.40, 25 & 26 February, 1 March, 2011:\r
+    hook GetProcAddress, addresses issues with .NET (work with PowerShell);\r
+    implement SO & SI to use the DEC Special Graphics Character Set (enables\r
+     line drawing via ASCII); ignore \e(X & \e)X (where X is any character);\r
+    add \e[?25h & \e[?25l to show/hide the cursor (DECTCEM).\r
+\r
+  v1.50, 7 to 14 December, 2011:\r
+    added dynamic environment variable ANSICON_VER to return version;\r
+    read ANSICON_EXC environment variable to exclude selected modules;\r
+    read ANSICON_GUI environment variable to hook selected GUI programs;\r
+    read ANSICON_DEF environment variable to set the default GR;\r
+    transfer current GR to child, read it on exit.\r
+\r
+  v1.51, 15 January, 5, 22 & 24 February, 2012:\r
+    added log mask 16 to log all the imported modules of imported modules;\r
+    ignore the version within the core API DLL names;\r
+    fix 32-bit process trying to identify 64-bit process;\r
+    hook _lwrite & _hwrite.\r
+\r
+  v1.52, 10 April, 1 & 2 June, 2012:\r
+    use ansicon.exe to enable 32-bit to inject into 64-bit;\r
+    implement \e[39m & \e[49m (only setting color, nothing else);\r
+    added the character/line equivalents (keaj`) of the cursor movement\r
+     sequences (ABCDG), as well as vertical absolute (d) and erase characters\r
+     (X).\r
+\r
+  v1.53, 12 June, 2012:\r
+    fixed Update_GRM when running multiple processes (e.g. "cl /MP").\r
+\r
+  v1.60, 22 to 24 November, 2012:\r
+    alternative method to obtain LLW for 64->32 injection;\r
+    support for VC6 (remove section pragma, rename isdigit to is_digit).\r
+\r
+  v1.61, 14 February, 2013:\r
+    go back to using ANSI-LLW.exe for 64->32 injection.\r
+\r
+  v1.62, 17 & 18 July, 2013:\r
+    another method to obtain LLW for 64->32 injection.\r
+\r
+  v1.64, 2 August, 2013:\r
+    better method of determining a console handle (see IsConsoleHandle).\r
+\r
+  v1.65, 28 August, 2013:\r
+    fix \e[K (was using window, not buffer).\r
+*/\r
+\r
+#include "ansicon.h"\r
+#include "version.h"\r
+#include <tlhelp32.h>\r
+\r
+#define is_digit(c) ('0' <= (c) && (c) <= '9')\r
+\r
+#ifdef __GNUC__\r
+#define SHARED __attribute__((shared, section(".shared")))\r
+#else\r
+#pragma data_seg(".shared", "read,write,shared")\r
+#pragma data_seg()\r
+#define SHARED __declspec(allocate(".shared"))\r
+#endif\r
+\r
+\r
+// ========== Global variables and constants\r
+\r
+HANDLE   hConOut;              // handle to CONOUT$\r
+\r
+#define ESC    '\x1B'          // ESCape character\r
+#define BEL    '\x07'\r
+#define SO     '\x0E'          // Shift Out\r
+#define SI     '\x0F'          // Shift In\r
+\r
+#define MAX_ARG 16             // max number of args in an escape sequence\r
+int   state;                   // automata state\r
+TCHAR prefix;                  // escape sequence prefix ( '[', ']' or '(' );\r
+TCHAR prefix2;                 // secondary prefix ( '?' or '>' );\r
+TCHAR suffix;                  // escape sequence suffix\r
+int   es_argc;                 // escape sequence args count\r
+int   es_argv[MAX_ARG];        // escape sequence args\r
+TCHAR Pt_arg[MAX_PATH*2];      // text parameter for Operating System Command\r
+int   Pt_len;\r
+BOOL  shifted;\r
+\r
+\r
+// DEC Special Graphics Character Set from\r
+// http://vt100.net/docs/vt220-rm/table2-4.html\r
+// Some of these may not look right, depending on the font and code page (in\r
+// particular, the Control Pictures probably won't work at all).\r
+const WCHAR G1[] =\r
+{\r
+  ' ',          // _ - blank\r
+  L'\x2666',    // ` - Black Diamond Suit\r
+  L'\x2592',    // a - Medium Shade\r
+  L'\x2409',    // b - HT\r
+  L'\x240c',    // c - FF\r
+  L'\x240d',    // d - CR\r
+  L'\x240a',    // e - LF\r
+  L'\x00b0',    // f - Degree Sign\r
+  L'\x00b1',    // g - Plus-Minus Sign\r
+  L'\x2424',    // h - NL\r
+  L'\x240b',    // i - VT\r
+  L'\x2518',    // j - Box Drawings Light Up And Left\r
+  L'\x2510',    // k - Box Drawings Light Down And Left\r
+  L'\x250c',    // l - Box Drawings Light Down And Right\r
+  L'\x2514',    // m - Box Drawings Light Up And Right\r
+  L'\x253c',    // n - Box Drawings Light Vertical And Horizontal\r
+  L'\x00af',    // o - SCAN 1 - Macron\r
+  L'\x25ac',    // p - SCAN 3 - Black Rectangle\r
+  L'\x2500',    // q - SCAN 5 - Box Drawings Light Horizontal\r
+  L'_',         // r - SCAN 7 - Low Line\r
+  L'_',         // s - SCAN 9 - Low Line\r
+  L'\x251c',    // t - Box Drawings Light Vertical And Right\r
+  L'\x2524',    // u - Box Drawings Light Vertical And Left\r
+  L'\x2534',    // v - Box Drawings Light Up And Horizontal\r
+  L'\x252c',    // w - Box Drawings Light Down And Horizontal\r
+  L'\x2502',    // x - Box Drawings Light Vertical\r
+  L'\x2264',    // y - Less-Than Or Equal To\r
+  L'\x2265',    // z - Greater-Than Or Equal To\r
+  L'\x03c0',    // { - Greek Small Letter Pi\r
+  L'\x2260',    // | - Not Equal To\r
+  L'\x00a3',    // } - Pound Sign\r
+  L'\x00b7',    // ~ - Middle Dot\r
+};\r
+\r
+#define FIRST_G1 '_'\r
+#define LAST_G1  '~'\r
+\r
+\r
+// color constants\r
+\r
+#define FOREGROUND_BLACK 0\r
+#define FOREGROUND_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE\r
+\r
+#define BACKGROUND_BLACK 0\r
+#define BACKGROUND_WHITE BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE\r
+\r
+const BYTE foregroundcolor[8] =\r
+{\r
+  FOREGROUND_BLACK,                    // black foreground\r
+  FOREGROUND_RED,                      // red foreground\r
+  FOREGROUND_GREEN,                    // green foreground\r
+  FOREGROUND_RED | FOREGROUND_GREEN,   // yellow foreground\r
+  FOREGROUND_BLUE,                     // blue foreground\r
+  FOREGROUND_BLUE | FOREGROUND_RED,    // magenta foreground\r
+  FOREGROUND_BLUE | FOREGROUND_GREEN,  // cyan foreground\r
+  FOREGROUND_WHITE                     // white foreground\r
+};\r
+\r
+const BYTE backgroundcolor[8] =\r
+{\r
+  BACKGROUND_BLACK,                    // black background\r
+  BACKGROUND_RED,                      // red background\r
+  BACKGROUND_GREEN,                    // green background\r
+  BACKGROUND_RED | BACKGROUND_GREEN,   // yellow background\r
+  BACKGROUND_BLUE,                     // blue background\r
+  BACKGROUND_BLUE | BACKGROUND_RED,    // magenta background\r
+  BACKGROUND_BLUE | BACKGROUND_GREEN,  // cyan background\r
+  BACKGROUND_WHITE,                    // white background\r
+};\r
+\r
+const BYTE attr2ansi[8] =              // map console attribute to ANSI number\r
+{\r
+  0,                                   // black\r
+  4,                                   // blue\r
+  2,                                   // green\r
+  6,                                   // cyan\r
+  1,                                   // red\r
+  5,                                   // magenta\r
+  3,                                   // yellow\r
+  7                                    // white\r
+};\r
+\r
+GRM grm;\r
+\r
+// saved cursor position\r
+COORD SavePos;\r
+\r
+// Variables to enable copying attributes between processes.\r
+SHARED DWORD s_pid;\r
+SHARED GRM   s_grm;\r
+SHARED DWORD s_flag;\r
+#define GRM_INIT 1\r
+#define GRM_EXIT 2\r
+\r
+#ifdef _WIN64\r
+SHARED DWORD LLW32;\r
+#endif\r
+\r
+\r
+// Wait for the child process to finish, then update our GRM to the child's.\r
+DWORD WINAPI UpdateGRM( LPVOID child_pi )\r
+{\r
+  DWORD  pid  = ((LPPROCESS_INFORMATION)child_pi)->dwProcessId;\r
+  HANDLE proc = ((LPPROCESS_INFORMATION)child_pi)->hProcess;\r
+  free( child_pi );\r
+\r
+  WaitForSingleObject( proc, INFINITE );\r
+  CloseHandle( proc );\r
+\r
+  if (s_flag == GRM_EXIT && s_pid == pid)\r
+  {\r
+    s_flag = 0;\r
+    grm = s_grm;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+// Search an environment variable for a string.\r
+BOOL search_env( LPCTSTR var, LPCTSTR val )\r
+{\r
+  static LPTSTR env;\r
+  static DWORD env_len;\r
+  DWORD len;\r
+  BOOL not;\r
+\r
+  len = GetEnvironmentVariable( var, env, env_len );\r
+  if (len == 0)\r
+    return FALSE;\r
+\r
+  if (len > env_len)\r
+  {\r
+    LPTSTR tmp = realloc( env, TSIZE(len) );\r
+    if (tmp == NULL)\r
+      return FALSE;\r
+    env = tmp;\r
+    env_len = len;\r
+    GetEnvironmentVariable( var, env, env_len );\r
+  }\r
+\r
+  not = (*env == '!');\r
+  if (not && env[1] == '\0')\r
+    return TRUE;\r
+\r
+  for (var = wcstok( env + not, L";" ); var; var = wcstok( NULL, L";" ))\r
+    if (_wcsicmp( val, var ) == 0)\r
+      return !not;\r
+\r
+  return not;\r
+}\r
+\r
+\r
+// ========== Print Buffer functions\r
+\r
+#define BUFFER_SIZE 2048\r
+\r
+int   nCharInBuffer;\r
+WCHAR ChBuffer[BUFFER_SIZE];\r
+\r
+//-----------------------------------------------------------------------------\r
+//   FlushBuffer()\r
+// Writes the buffer to the console and empties it.\r
+//-----------------------------------------------------------------------------\r
+\r
+void FlushBuffer( void )\r
+{\r
+  DWORD nWritten;\r
+  if (nCharInBuffer <= 0) return;\r
+  WriteConsole( hConOut, ChBuffer, nCharInBuffer, &nWritten, NULL );\r
+  nCharInBuffer = 0;\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+//   PushBuffer( WCHAR c )\r
+// Adds a character in the buffer.\r
+//-----------------------------------------------------------------------------\r
+\r
+void PushBuffer( WCHAR c )\r
+{\r
+  if (shifted && c >= FIRST_G1 && c <= LAST_G1)\r
+    c = G1[c-FIRST_G1];\r
+  ChBuffer[nCharInBuffer] = c;\r
+  if (++nCharInBuffer == BUFFER_SIZE)\r
+    FlushBuffer();\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+//   SendSequence( LPTSTR seq )\r
+// Send the string to the input buffer.\r
+//-----------------------------------------------------------------------------\r
+\r
+void SendSequence( LPTSTR seq )\r
+{\r
+  DWORD out;\r
+  INPUT_RECORD in;\r
+  HANDLE hStdIn = GetStdHandle( STD_INPUT_HANDLE );\r
+\r
+  in.EventType = KEY_EVENT;\r
+  in.Event.KeyEvent.bKeyDown = TRUE;\r
+  in.Event.KeyEvent.wRepeatCount = 1;\r
+  in.Event.KeyEvent.wVirtualKeyCode = 0;\r
+  in.Event.KeyEvent.wVirtualScanCode = 0;\r
+  in.Event.KeyEvent.dwControlKeyState = 0;\r
+  for (; *seq; ++seq)\r
+  {\r
+    in.Event.KeyEvent.uChar.UnicodeChar = *seq;\r
+    WriteConsoleInput( hStdIn, &in, 1, &out );\r
+  }\r
+}\r
+\r
+// ========== Print functions\r
+\r
+//-----------------------------------------------------------------------------\r
+//   InterpretEscSeq()\r
+// Interprets the last escape sequence scanned by ParseAndPrintString\r
+//   prefix             escape sequence prefix\r
+//   es_argc            escape sequence args count\r
+//   es_argv[]          escape sequence args array\r
+//   suffix             escape sequence suffix\r
+//\r
+// for instance, with \e[33;45;1m we have\r
+// prefix = '[',\r
+// es_argc = 3, es_argv[0] = 33, es_argv[1] = 45, es_argv[2] = 1\r
+// suffix = 'm'\r
+//-----------------------------------------------------------------------------\r
+\r
+void InterpretEscSeq( void )\r
+{\r
+  int  i;\r
+  WORD attribut;\r
+  CONSOLE_SCREEN_BUFFER_INFO Info;\r
+  CONSOLE_CURSOR_INFO CursInfo;\r
+  DWORD len, NumberOfCharsWritten;\r
+  COORD Pos;\r
+  SMALL_RECT Rect;\r
+  CHAR_INFO  CharInfo;\r
+\r
+  if (prefix == '[')\r
+  {\r
+    if (prefix2 == '?' && (suffix == 'h' || suffix == 'l'))\r
+    {\r
+      if (es_argc == 1 && es_argv[0] == 25)\r
+      {\r
+       GetConsoleCursorInfo( hConOut, &CursInfo );\r
+       CursInfo.bVisible = (suffix == 'h');\r
+       SetConsoleCursorInfo( hConOut, &CursInfo );\r
+       return;\r
+      }\r
+    }\r
+    // Ignore any other \e[? or \e[> sequences.\r
+    if (prefix2 != 0)\r
+      return;\r
+\r
+    GetConsoleScreenBufferInfo( hConOut, &Info );\r
+    switch (suffix)\r
+    {\r
+      case 'm':\r
+       if (es_argc == 0) es_argv[es_argc++] = 0;\r
+       for (i = 0; i < es_argc; i++)\r
+       {\r
+         if (30 <= es_argv[i] && es_argv[i] <= 37)\r
+           grm.foreground = es_argv[i] - 30;\r
+         else if (40 <= es_argv[i] && es_argv[i] <= 47)\r
+           grm.background = es_argv[i] - 40;\r
+         else switch (es_argv[i])\r
+         {\r
+           case 0:\r
+           case 39:\r
+           case 49:\r
+           {\r
+             TCHAR def[4];\r
+             int   a;\r
+             *def = '7'; def[1] = '\0';\r
+             GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) );\r
+             a = wcstol( def, NULL, 16 );\r
+             grm.reverse = FALSE;\r
+             if (a < 0)\r
+             {\r
+               grm.reverse = TRUE;\r
+               a = -a;\r
+             }\r
+             if (es_argv[i] != 49)\r
+               grm.foreground = attr2ansi[a & 7];\r
+             if (es_argv[i] != 39)\r
+               grm.background = attr2ansi[(a >> 4) & 7];\r
+             if (es_argv[i] == 0)\r
+             {\r
+               if (es_argc == 1)\r
+               {\r
+                 grm.bold      = a & FOREGROUND_INTENSITY;\r
+                 grm.underline = a & BACKGROUND_INTENSITY;\r
+               }\r
+               else\r
+               {\r
+                 grm.bold      = 0;\r
+                 grm.underline = 0;\r
+               }\r
+               grm.rvideo    = 0;\r
+               grm.concealed = 0;\r
+             }\r
+           }\r
+           break;\r
+\r
+           case  1: grm.bold      = FOREGROUND_INTENSITY; break;\r
+           case  5: // blink\r
+           case  4: grm.underline = BACKGROUND_INTENSITY; break;\r
+           case  7: grm.rvideo    = 1; break;\r
+           case  8: grm.concealed = 1; break;\r
+           case 21: // oops, this actually turns on double underline\r
+           case 22: grm.bold      = 0; break;\r
+           case 25:\r
+           case 24: grm.underline = 0; break;\r
+           case 27: grm.rvideo    = 0; break;\r
+           case 28: grm.concealed = 0; break;\r
+         }\r
+       }\r
+       if (grm.concealed)\r
+       {\r
+         if (grm.rvideo)\r
+         {\r
+           attribut = foregroundcolor[grm.foreground]\r
+                    | backgroundcolor[grm.foreground];\r
+           if (grm.bold)\r
+             attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;\r
+         }\r
+         else\r
+         {\r
+           attribut = foregroundcolor[grm.background]\r
+                    | backgroundcolor[grm.background];\r
+           if (grm.underline)\r
+             attribut |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;\r
+         }\r
+       }\r
+       else if (grm.rvideo)\r
+       {\r
+         attribut = foregroundcolor[grm.background]\r
+                  | backgroundcolor[grm.foreground];\r
+         if (grm.bold)\r
+           attribut |= BACKGROUND_INTENSITY;\r
+         if (grm.underline)\r
+           attribut |= FOREGROUND_INTENSITY;\r
+       }\r
+       else\r
+         attribut = foregroundcolor[grm.foreground] | grm.bold\r
+                  | backgroundcolor[grm.background] | grm.underline;\r
+       if (grm.reverse)\r
+         attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4);\r
+       SetConsoleTextAttribute( hConOut, attribut );\r
+      return;\r
+\r
+      case 'J':\r
+       if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[J == ESC[0J\r
+       if (es_argc != 1) return;\r
+       switch (es_argv[0])\r
+       {\r
+         case 0:               // ESC[0J erase from cursor to end of display\r
+           len = (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X\r
+                 + Info.dwSize.X - Info.dwCursorPosition.X - 1;\r
+           FillConsoleOutputCharacter( hConOut, ' ', len,\r
+                                       Info.dwCursorPosition,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,\r
+                                       Info.dwCursorPosition,\r
+                                       &NumberOfCharsWritten );\r
+         return;\r
+\r
+         case 1:               // ESC[1J erase from start to cursor.\r
+           Pos.X = 0;\r
+           Pos.Y = 0;\r
+           len   = Info.dwCursorPosition.Y * Info.dwSize.X\r
+                   + Info.dwCursorPosition.X + 1;\r
+           FillConsoleOutputCharacter( hConOut, ' ', len, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           return;\r
+\r
+         case 2:               // ESC[2J Clear screen and home cursor\r
+           Pos.X = 0;\r
+           Pos.Y = 0;\r
+           len   = Info.dwSize.X * Info.dwSize.Y;\r
+           FillConsoleOutputCharacter( hConOut, ' ', len, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           SetConsoleCursorPosition( hConOut, Pos );\r
+         return;\r
+\r
+         default:\r
+         return;\r
+       }\r
+\r
+      case 'K':\r
+       if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[K == ESC[0K\r
+       if (es_argc != 1) return;\r
+       switch (es_argv[0])\r
+       {\r
+         case 0:               // ESC[0K Clear to end of line\r
+           len = Info.dwSize.X - Info.dwCursorPosition.X + 1;\r
+           FillConsoleOutputCharacter( hConOut, ' ', len,\r
+                                       Info.dwCursorPosition,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,\r
+                                       Info.dwCursorPosition,\r
+                                       &NumberOfCharsWritten );\r
+         return;\r
+\r
+         case 1:               // ESC[1K Clear from start of line to cursor\r
+           Pos.X = 0;\r
+           Pos.Y = Info.dwCursorPosition.Y;\r
+           FillConsoleOutputCharacter( hConOut, ' ',\r
+                                       Info.dwCursorPosition.X + 1, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes,\r
+                                       Info.dwCursorPosition.X + 1, Pos,\r
+                                       &NumberOfCharsWritten );\r
+         return;\r
+\r
+         case 2:               // ESC[2K Clear whole line.\r
+           Pos.X = 0;\r
+           Pos.Y = Info.dwCursorPosition.Y;\r
+           FillConsoleOutputCharacter( hConOut, ' ', Info.dwSize.X, Pos,\r
+                                       &NumberOfCharsWritten );\r
+           FillConsoleOutputAttribute( hConOut, Info.wAttributes,\r
+                                       Info.dwSize.X, Pos,\r
+                                       &NumberOfCharsWritten );\r
+         return;\r
+\r
+         default:\r
+         return;\r
+       }\r
+\r
+      case 'X':                 // ESC[#X Erase # characters.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X\r
+       if (es_argc != 1) return;\r
+       FillConsoleOutputCharacter( hConOut, ' ', es_argv[0],\r
+                                   Info.dwCursorPosition,\r
+                                   &NumberOfCharsWritten );\r
+       FillConsoleOutputAttribute( hConOut, Info.wAttributes, es_argv[0],\r
+                                   Info.dwCursorPosition,\r
+                                   &NumberOfCharsWritten );\r
+      return;\r
+\r
+      case 'L':                 // ESC[#L Insert # blank lines.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L\r
+       if (es_argc != 1) return;\r
+       Rect.Left   = 0;\r
+       Rect.Top    = Info.dwCursorPosition.Y;\r
+       Rect.Right  = Info.dwSize.X - 1;\r
+       Rect.Bottom = Info.dwSize.Y - 1;\r
+       Pos.X = 0;\r
+       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];\r
+       CharInfo.Char.UnicodeChar = ' ';\r
+       CharInfo.Attributes = Info.wAttributes;\r
+       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );\r
+      return;\r
+\r
+      case 'M':                 // ESC[#M Delete # lines.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M\r
+       if (es_argc != 1) return;\r
+       if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y)\r
+         es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y;\r
+       Rect.Left   = 0;\r
+       Rect.Top    = Info.dwCursorPosition.Y + es_argv[0];\r
+       Rect.Right  = Info.dwSize.X - 1;\r
+       Rect.Bottom = Info.dwSize.Y - 1;\r
+       Pos.X = 0;\r
+       Pos.Y = Info.dwCursorPosition.Y;\r
+       CharInfo.Char.UnicodeChar = ' ';\r
+       CharInfo.Attributes = Info.wAttributes;\r
+       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );\r
+      return;\r
+\r
+      case 'P':                 // ESC[#P Delete # characters.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P\r
+       if (es_argc != 1) return;\r
+       if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1)\r
+         es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X;\r
+       Rect.Left   = Info.dwCursorPosition.X + es_argv[0];\r
+       Rect.Top    = Info.dwCursorPosition.Y;\r
+       Rect.Right  = Info.dwSize.X - 1;\r
+       Rect.Bottom = Info.dwCursorPosition.Y;\r
+       CharInfo.Char.UnicodeChar = ' ';\r
+       CharInfo.Attributes = Info.wAttributes;\r
+       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Info.dwCursorPosition,\r
+                                  &CharInfo );\r
+      return;\r
+\r
+      case '@':                 // ESC[#@ Insert # blank characters.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@\r
+       if (es_argc != 1) return;\r
+       if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1)\r
+         es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X;\r
+       Rect.Left   = Info.dwCursorPosition.X;\r
+       Rect.Top    = Info.dwCursorPosition.Y;\r
+       Rect.Right  = Info.dwSize.X - 1 - es_argv[0];\r
+       Rect.Bottom = Info.dwCursorPosition.Y;\r
+       Pos.X = Info.dwCursorPosition.X + es_argv[0];\r
+       Pos.Y = Info.dwCursorPosition.Y;\r
+       CharInfo.Char.UnicodeChar = ' ';\r
+       CharInfo.Attributes = Info.wAttributes;\r
+       ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo );\r
+      return;\r
+\r
+      case 'k':                 // ESC[#k\r
+      case 'A':                 // ESC[#A Moves cursor up # lines\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A\r
+       if (es_argc != 1) return;\r
+       Pos.Y = Info.dwCursorPosition.Y - es_argv[0];\r
+       if (Pos.Y < 0) Pos.Y = 0;\r
+       Pos.X = Info.dwCursorPosition.X;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'e':                 // ESC[#e\r
+      case 'B':                 // ESC[#B Moves cursor down # lines\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B\r
+       if (es_argc != 1) return;\r
+       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];\r
+       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;\r
+       Pos.X = Info.dwCursorPosition.X;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'a':                 // ESC[#a\r
+      case 'C':                 // ESC[#C Moves cursor forward # spaces\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C\r
+       if (es_argc != 1) return;\r
+       Pos.X = Info.dwCursorPosition.X + es_argv[0];\r
+       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;\r
+       Pos.Y = Info.dwCursorPosition.Y;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'j':                 // ESC[#j\r
+      case 'D':                 // ESC[#D Moves cursor back # spaces\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D\r
+       if (es_argc != 1) return;\r
+       Pos.X = Info.dwCursorPosition.X - es_argv[0];\r
+       if (Pos.X < 0) Pos.X = 0;\r
+       Pos.Y = Info.dwCursorPosition.Y;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'E':                 // ESC[#E Moves cursor down # lines, column 1.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E\r
+       if (es_argc != 1) return;\r
+       Pos.Y = Info.dwCursorPosition.Y + es_argv[0];\r
+       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;\r
+       Pos.X = 0;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'F':                 // ESC[#F Moves cursor up # lines, column 1.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F\r
+       if (es_argc != 1) return;\r
+       Pos.Y = Info.dwCursorPosition.Y - es_argv[0];\r
+       if (Pos.Y < 0) Pos.Y = 0;\r
+       Pos.X = 0;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case '`':                 // ESC[#`\r
+      case 'G':                 // ESC[#G Moves cursor column # in current row.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G\r
+       if (es_argc != 1) return;\r
+       Pos.X = es_argv[0] - 1;\r
+       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;\r
+       if (Pos.X < 0) Pos.X = 0;\r
+       Pos.Y = Info.dwCursorPosition.Y;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'd':                 // ESC[#d Moves cursor row #, current column.\r
+       if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d\r
+       if (es_argc != 1) return;\r
+       Pos.Y = es_argv[0] - 1;\r
+       if (Pos.Y < 0) Pos.Y = 0;\r
+       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 'f':                 // ESC[#;#f\r
+      case 'H':                 // ESC[#;#H Moves cursor to line #, column #\r
+       if (es_argc == 0)\r
+         es_argv[es_argc++] = 1; // ESC[H == ESC[1;1H\r
+       if (es_argc == 1)\r
+         es_argv[es_argc++] = 1; // ESC[#H == ESC[#;1H\r
+       if (es_argc > 2) return;\r
+       Pos.X = es_argv[1] - 1;\r
+       if (Pos.X < 0) Pos.X = 0;\r
+       if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1;\r
+       Pos.Y = es_argv[0] - 1;\r
+       if (Pos.Y < 0) Pos.Y = 0;\r
+       if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1;\r
+       SetConsoleCursorPosition( hConOut, Pos );\r
+      return;\r
+\r
+      case 's':                 // ESC[s Saves cursor position for recall later\r
+       if (es_argc != 0) return;\r
+       SavePos = Info.dwCursorPosition;\r
+      return;\r
+\r
+      case 'u':                 // ESC[u Return to saved cursor position\r
+       if (es_argc != 0) return;\r
+       SetConsoleCursorPosition( hConOut, SavePos );\r
+      return;\r
+\r
+      case 'n':                 // ESC[#n Device status report\r
+       if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored\r
+       switch (es_argv[0])\r
+       {\r
+         case 5:               // ESC[5n Report status\r
+           SendSequence( L"\33[0n" ); // "OK"\r
+         return;\r
+\r
+         case 6:               // ESC[6n Report cursor position\r
+         {\r
+           TCHAR buf[32];\r
+           wsprintf( buf, L"\33[%d;%dR", Info.dwCursorPosition.Y + 1,\r
+                                         Info.dwCursorPosition.X + 1 );\r
+           SendSequence( buf );\r
+         }\r
+         return;\r
+\r
+         default:\r
+         return;\r
+       }\r
+\r
+      case 't':                 // ESC[#t Window manipulation\r
+       if (es_argc != 1) return;\r
+       if (es_argv[0] == 21)   // ESC[21t Report xterm window's title\r
+       {\r
+         TCHAR buf[MAX_PATH*2];\r
+         DWORD len = GetConsoleTitle( buf+3, lenof(buf)-3-2 );\r
+         // Too bad if it's too big or fails.\r
+         buf[0] = ESC;\r
+         buf[1] = ']';\r
+         buf[2] = 'l';\r
+         buf[3+len] = ESC;\r
+         buf[3+len+1] = '\\';\r
+         buf[3+len+2] = '\0';\r
+         SendSequence( buf );\r
+       }\r
+      return;\r
+\r
+      default:\r
+      return;\r
+    }\r
+  }\r
+  else // (prefix == ']')\r
+  {\r
+    // Ignore any \e]? or \e]> sequences.\r
+    if (prefix2 != 0)\r
+      return;\r
+\r
+    if (es_argc == 1 && es_argv[0] == 0) // ESC]0;titleST\r
+    {\r
+      SetConsoleTitle( Pt_arg );\r
+    }\r
+  }\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+//   ParseAndPrintString(hDev, lpBuffer, nNumberOfBytesToWrite)\r
+// Parses the string lpBuffer, interprets the escapes sequences and prints the\r
+// characters in the device hDev (console).\r
+// The lexer is a three states automata.\r
+// If the number of arguments es_argc > MAX_ARG, only the MAX_ARG-1 firsts and\r
+// the last arguments are processed (no es_argv[] overflow).\r
+//-----------------------------------------------------------------------------\r
+\r
+BOOL\r
+ParseAndPrintString( HANDLE hDev,\r
+                    LPCVOID lpBuffer,\r
+                    DWORD nNumberOfBytesToWrite,\r
+                    LPDWORD lpNumberOfBytesWritten\r
+                    )\r
+{\r
+  DWORD   i;\r
+  LPCTSTR s;\r
+\r
+  if (hDev != hConOut) // reinit if device has changed\r
+  {\r
+    hConOut = hDev;\r
+    state = 1;\r
+    shifted = FALSE;\r
+  }\r
+  for (i = nNumberOfBytesToWrite, s = (LPCTSTR)lpBuffer; i > 0; i--, s++)\r
+  {\r
+    if (state == 1)\r
+    {\r
+      if (*s == ESC) state = 2;\r
+      else if (*s == SO) shifted = TRUE;\r
+      else if (*s == SI) shifted = FALSE;\r
+      else PushBuffer( *s );\r
+    }\r
+    else if (state == 2)\r
+    {\r
+      if (*s == ESC) ; // \e\e...\e == \e\r
+      else if ((*s == '[') || (*s == ']'))\r
+      {\r
+       FlushBuffer();\r
+       prefix = *s;\r
+       prefix2 = 0;\r
+       state = 3;\r
+       Pt_len = 0;\r
+       *Pt_arg = '\0';\r
+      }\r
+      else if (*s == ')' || *s == '(') state = 6;\r
+      else state = 1;\r
+    }\r
+    else if (state == 3)\r
+    {\r
+      if (is_digit( *s ))\r
+      {\r
+        es_argc = 0;\r
+       es_argv[0] = *s - '0';\r
+        state = 4;\r
+      }\r
+      else if (*s == ';')\r
+      {\r
+        es_argc = 1;\r
+        es_argv[0] = 0;\r
+       es_argv[1] = 0;\r
+        state = 4;\r
+      }\r
+      else if (*s == '?' || *s == '>')\r
+      {\r
+       prefix2 = *s;\r
+      }\r
+      else\r
+      {\r
+        es_argc = 0;\r
+        suffix = *s;\r
+        InterpretEscSeq();\r
+        state = 1;\r
+      }\r
+    }\r
+    else if (state == 4)\r
+    {\r
+      if (is_digit( *s ))\r
+      {\r
+       es_argv[es_argc] = 10 * es_argv[es_argc] + (*s - '0');\r
+      }\r
+      else if (*s == ';')\r
+      {\r
+        if (es_argc < MAX_ARG-1) es_argc++;\r
+       es_argv[es_argc] = 0;\r
+       if (prefix == ']')\r
+         state = 5;\r
+      }\r
+      else\r
+      {\r
+       es_argc++;\r
+        suffix = *s;\r
+        InterpretEscSeq();\r
+        state = 1;\r
+      }\r
+    }\r
+    else if (state == 5)\r
+    {\r
+      if (*s == BEL)\r
+      {\r
+       Pt_arg[Pt_len] = '\0';\r
+        InterpretEscSeq();\r
+        state = 1;\r
+      }\r
+      else if (*s == '\\' && Pt_len > 0 && Pt_arg[Pt_len-1] == ESC)\r
+      {\r
+       Pt_arg[--Pt_len] = '\0';\r
+        InterpretEscSeq();\r
+        state = 1;\r
+      }\r
+      else if (Pt_len < lenof(Pt_arg)-1)\r
+       Pt_arg[Pt_len++] = *s;\r
+    }\r
+    else if (state == 6)\r
+    {\r
+      // Ignore it (ESC ) 0 is implicit; nothing else is supported).\r
+      state = 1;\r
+    }\r
+  }\r
+  FlushBuffer();\r
+  if (lpNumberOfBytesWritten != NULL)\r
+    *lpNumberOfBytesWritten = nNumberOfBytesToWrite - i;\r
+  return (i == 0);\r
+}\r
+\r
+\r
+// ========== Hooking API functions\r
+//\r
+// References about API hooking (and dll injection):\r
+// - Matt Pietrek ~ Windows 95 System Programming Secrets.\r
+// - Jeffrey Richter ~ Programming Applications for Microsoft Windows 4th ed.\r
+\r
+// Macro for adding pointers/DWORDs together without C arithmetic interfering\r
+#define MakeVA( cast, offset ) (cast)((DWORD_PTR)(pDosHeader)+(DWORD)(offset))\r
+\r
+\r
+const char APIKernel[]            = "kernel32.dll";\r
+const char APIConsole[]           = "API-MS-Win-Core-Console-";\r
+const char APIProcessThreads[]    = "API-MS-Win-Core-ProcessThreads-";\r
+const char APIProcessEnvironment[] = "API-MS-Win-Core-ProcessEnvironment-";\r
+const char APILibraryLoader[]     = "API-MS-Win-Core-LibraryLoader-";\r
+const char APIFile[]              = "API-MS-Win-Core-File-";\r
+\r
+typedef struct\r
+{\r
+  PCSTR   name;\r
+  DWORD   len;\r
+  HMODULE base;\r
+} API_DATA, *PAPI_DATA;\r
+\r
+API_DATA APIs[] =\r
+{\r
+  { APIConsole,           sizeof(APIConsole) - 1,            NULL },\r
+  { APIProcessThreads,    sizeof(APIProcessThreads) - 1,     NULL },\r
+  { APIProcessEnvironment, sizeof(APIProcessEnvironment) - 1, NULL },\r
+  { APILibraryLoader,     sizeof(APILibraryLoader) - 1,      NULL },\r
+  { APIFile,              sizeof(APIFile) - 1,               NULL },\r
+  { NULL,                 0,                                 NULL }\r
+};\r
+\r
+\r
+HMODULE   hKernel;             // Kernel32 module handle\r
+HINSTANCE hDllInstance;        // Dll instance handle\r
+TCHAR    hDllName[MAX_PATH];   // Dll file name\r
+#if defined(_WIN64) || defined(W32ON64)\r
+LPTSTR   hDllNameType;         // pointer to process type within above\r
+#endif\r
+\r
+typedef struct\r
+{\r
+  PCSTR lib;\r
+  PSTR name;\r
+  PROC newfunc;\r
+  PROC oldfunc;\r
+  PROC apifunc;\r
+} HookFn, *PHookFn;\r
+\r
+HookFn Hooks[];\r
+\r
+const WCHAR zIgnoring[]  = L"Ignoring";\r
+const WCHAR zHooking[]  = L"Hooking";\r
+const WCHAR zUnhooking[] = L"Unhooking";\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+//   HookAPIOneMod\r
+// Substitute a new function in the Import Address Table (IAT) of the\r
+// specified module.\r
+// Return FALSE on error and TRUE on success.\r
+//-----------------------------------------------------------------------------\r
+\r
+BOOL HookAPIOneMod(\r
+    HMODULE hFromModule,       // Handle of the module to intercept calls from\r
+    PHookFn Hooks,             // Functions to replace\r
+    BOOL    restore            // Restore the original functions\r
+    )\r
+{\r
+  PIMAGE_DOS_HEADER       pDosHeader;\r
+  PIMAGE_NT_HEADERS       pNTHeader;\r
+  PIMAGE_IMPORT_DESCRIPTOR pImportDesc;\r
+  PIMAGE_THUNK_DATA       pThunk;\r
+  PHookFn                 hook;\r
+\r
+  // Tests to make sure we're looking at a module image (the 'MZ' header)\r
+  pDosHeader = (PIMAGE_DOS_HEADER)hFromModule;\r
+  if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)\r
+  {\r
+    DEBUGSTR( 1, L"Image has no DOS header!" );\r
+    return FALSE;\r
+  }\r
+\r
+  // The MZ header has a pointer to the PE header\r
+  pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );\r
+\r
+  // One more test to make sure we're looking at a "PE" image\r
+  if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)\r
+  {\r
+    DEBUGSTR( 1, L"Image has no NT header!" );\r
+    return FALSE;\r
+  }\r
+\r
+  // We now have a valid pointer to the module's PE header.\r
+  // Get a pointer to its imports section.\r
+  pImportDesc = MakeVA( PIMAGE_IMPORT_DESCRIPTOR,\r
+                       pNTHeader->OptionalHeader.\r
+                        DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].\r
+                         VirtualAddress );\r
+\r
+  // Bail out if the RVA of the imports section is 0 (it doesn't exist)\r
+  if (pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pDosHeader)\r
+    return TRUE;\r
+\r
+  // Iterate through the array of imported module descriptors, looking\r
+  // for the module whose name matches the pszFunctionModule parameter.\r
+  for (; pImportDesc->Name; pImportDesc++)\r
+  {\r
+    BOOL kernel = TRUE;\r
+    PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );\r
+    if (_stricmp( pszModName, APIKernel ) != 0)\r
+    {\r
+      PAPI_DATA lib;\r
+      for (lib = APIs; lib->name; ++lib)\r
+      {\r
+       if (_strnicmp( pszModName, lib->name, lib->len ) == 0)\r
+       {\r
+         if (lib->base == NULL)\r
+         {\r
+           lib->base = GetModuleHandleA( pszModName );\r
+           for (hook = Hooks; hook->name; ++hook)\r
+             if (hook->lib == lib->name)\r
+               hook->apifunc = GetProcAddress( lib->base, hook->name );\r
+         }\r
+         break;\r
+       }\r
+      }\r
+      if (lib->name == NULL)\r
+      {\r
+       if (log_level & 16)\r
+         DEBUGSTR( 2, L" %s %S", zIgnoring, pszModName );\r
+       continue;\r
+      }\r
+      kernel = FALSE;\r
+    }\r
+    if (log_level & 16)\r
+      DEBUGSTR( 2, L" Scanning %S", pszModName );\r
+\r
+    // Get a pointer to the found module's import address table (IAT).\r
+    pThunk = MakeVA( PIMAGE_THUNK_DATA, pImportDesc->FirstThunk );\r
+\r
+    // Blast through the table of import addresses, looking for the ones\r
+    // that match the original addresses.\r
+    while (pThunk->u1.Function)\r
+    {\r
+      for (hook = Hooks; hook->name; ++hook)\r
+      {\r
+       PROC patch = 0;\r
+       if (restore)\r
+       {\r
+         if ((PROC)pThunk->u1.Function == hook->newfunc)\r
+           patch = (kernel) ? hook->oldfunc : hook->apifunc;\r
+       }\r
+       else if ((PROC)pThunk->u1.Function == hook->oldfunc ||\r
+                (PROC)pThunk->u1.Function == hook->apifunc)\r
+       {\r
+         patch = hook->newfunc;\r
+       }\r
+       if (patch)\r
+       {\r
+         DWORD flOldProtect, flNewProtect, flDummy;\r
+         MEMORY_BASIC_INFORMATION mbi;\r
+\r
+         DEBUGSTR( 3, L"  %S", hook->name );\r
+         // Get the current protection attributes.\r
+         VirtualQuery( &pThunk->u1.Function, &mbi, sizeof(mbi) );\r
+         // Take the access protection flags.\r
+         flNewProtect = mbi.Protect;\r
+         // Remove ReadOnly and ExecuteRead flags.\r
+         flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);\r
+         // Add on ReadWrite flag\r
+         flNewProtect |= (PAGE_READWRITE);\r
+         // Change the access protection on the region of committed pages in the\r
+         // virtual address space of the current process.\r
+         VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),\r
+                         flNewProtect, &flOldProtect );\r
+\r
+         // Overwrite the original address with the address of the new function.\r
+         if (!WriteProcessMemory( GetCurrentProcess(),\r
+                                  &pThunk->u1.Function,\r
+                                  &patch, sizeof(patch), NULL ))\r
+         {\r
+           DEBUGSTR( 1, L"Could not patch!" );\r
+           return FALSE;\r
+         }\r
+\r
+         // Put the page attributes back the way they were.\r
+         VirtualProtect( &pThunk->u1.Function, sizeof(PVOID),\r
+                         flOldProtect, &flDummy );\r
+       }\r
+      }\r
+      pThunk++; // Advance to next imported function address\r
+    }\r
+  }\r
+\r
+  return TRUE; // Function not found\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+//   HookAPIAllMod\r
+// Substitute a new function in the Import Address Table (IAT) of all\r
+// the modules in the current process.\r
+// Return FALSE on error and TRUE on success.\r
+//-----------------------------------------------------------------------------\r
+\r
+BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore )\r
+{\r
+  HANDLE       hModuleSnap;\r
+  MODULEENTRY32 me;\r
+  BOOL         fOk;\r
+\r
+  // Take a snapshot of all modules in the current process.\r
+  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,\r
+                                         GetCurrentProcessId() );\r
+\r
+  if (hModuleSnap == INVALID_HANDLE_VALUE)\r
+  {\r
+    DEBUGSTR( 1, L"Failed to create snapshot!" );\r
+    return FALSE;\r
+  }\r
+\r
+  // Fill the size of the structure before using it.\r
+  me.dwSize = sizeof(MODULEENTRY32);\r
+\r
+  // Walk the module list of the modules.\r
+  for (fOk = Module32First( hModuleSnap, &me ); fOk;\r
+       fOk = Module32Next( hModuleSnap, &me ))\r
+  {\r
+    // We don't hook functions in our own module.\r
+    if (me.hModule != hDllInstance && me.hModule != hKernel)\r
+    {\r
+      if (search_env( L"ANSICON_EXC", me.szModule ))\r
+      {\r
+       DEBUGSTR( 2, L"%s %s", zIgnoring, me.szModule );\r
+       continue;\r
+      }\r
+      DEBUGSTR( 2, L"%s %s", (restore) ? zUnhooking : zHooking, me.szModule );\r
+      // Hook this function in this module.\r
+      if (!HookAPIOneMod( me.hModule, Hooks, restore ))\r
+      {\r
+       CloseHandle( hModuleSnap );\r
+       return FALSE;\r
+      }\r
+    }\r
+  }\r
+  CloseHandle( hModuleSnap );\r
+  DEBUGSTR( 2, L"%s completed", (restore) ? zUnhooking : zHooking );\r
+  return TRUE;\r
+}\r
+\r
+\r
+// ========== Child process injection\r
+\r
+// Inject code into the target process to load our DLL.\r
+void Inject( DWORD dwCreationFlags, LPPROCESS_INFORMATION lpi,\r
+            LPPROCESS_INFORMATION child_pi,\r
+            BOOL wide, LPCVOID lpApp, LPCVOID lpCmd )\r
+{\r
+  int   type;\r
+  BOOL  gui;\r
+\r
+  type = ProcessType( child_pi, &gui );\r
+  if (gui)\r
+  {\r
+    TCHAR   app[MAX_PATH];\r
+    LPTSTR  name;\r
+    LPCTSTR term = L" \t";\r
+\r
+    app[MAX_PATH-1] = '\0';\r
+    if (lpApp == NULL)\r
+    {\r
+      // Extract the program from the command line.  I would use\r
+      // GetModuleFileNameEx, but it doesn't work when a process is created\r
+      // suspended and setting up a delay until it does work sometimes\r
+      // prevents the process running at all.  GetProcessImageFileName works,\r
+      // but it's not supported in 2K.\r
+      if (wide)\r
+      {\r
+       LPCTSTR pos;\r
+       for (pos = lpCmd; *pos == ' ' || *pos == '\t'; ++pos) ;\r
+       if (*pos == '"')\r
+       {\r
+         term = L"\"";\r
+         ++pos;\r
+       }\r
+       wcsncpy( app, pos, MAX_PATH-1 );\r
+      }\r
+      else\r
+      {\r
+       LPCSTR pos;\r
+       for (pos = lpCmd; *pos == ' ' || *pos == '\t'; ++pos) ;\r
+       if (*pos == '"')\r
+       {\r
+         term = L"\"";\r
+         ++pos;\r
+       }\r
+       MultiByteToWideChar( CP_ACP, 0, pos, -1, app, MAX_PATH );\r
+      }\r
+      // CreateProcess only works with surrounding quotes ('"a name"' works, but\r
+      // 'a" "name' fails), so that's all I'll test, too.  However, it also\r
+      // tests for a file at each separator ('a name' tries "a.exe" before\r
+      // "a name.exe") which I won't do.\r
+      name = wcspbrk( app, term );\r
+      if (name)\r
+       *name = '\0';\r
+    }\r
+    else\r
+    {\r
+      if (wide)\r
+       wcsncpy( app, lpApp, MAX_PATH-1 );\r
+      else\r
+       MultiByteToWideChar( CP_ACP, 0, lpApp, -1, app, MAX_PATH );\r
+    }\r
+    name = get_program_name( app );\r
+    if (!search_env( L"ANSICON_GUI", name ))\r
+    {\r
+      DEBUGSTR( 1, L"  %s", zIgnoring );\r
+      type = 0;\r
+    }\r
+  }\r
+  if (type != 0)\r
+  {\r
+#ifdef _WIN64\r
+    if (type == 32)\r
+    {\r
+      hDllNameType[0] = '3';\r
+      hDllNameType[1] = '2';\r
+      InjectDLL32( child_pi, hDllName );\r
+    }\r
+    else\r
+    {\r
+      hDllNameType[0] = '6';\r
+      hDllNameType[1] = '4';\r
+      InjectDLL64( child_pi, hDllName );\r
+    }\r
+#else\r
+#ifdef W32ON64\r
+    if (type == 64)\r
+    {\r
+      TCHAR args[64];\r
+      STARTUPINFO si;\r
+      PROCESS_INFORMATION pi;\r
+      wcscpy( hDllNameType, L"CON.exe" );\r
+      wsprintf( args, L"ansicon -P%lu:%lu",\r
+                     child_pi->dwProcessId, child_pi->dwThreadId );\r
+      ZeroMemory( &si, sizeof(si) );\r
+      si.cb = sizeof(si);\r
+      if (CreateProcess( hDllName, args, NULL, NULL, FALSE, 0, NULL, NULL,\r
+                        &si, &pi ))\r
+      {\r
+       WaitForSingleObject( pi.hProcess, INFINITE );\r
+       CloseHandle( pi.hProcess );\r
+       CloseHandle( pi.hThread );\r
+      }\r
+      else\r
+       DEBUGSTR( 1, L"Could not execute \"%s\"", hDllName );\r
+      wcscpy( hDllNameType, L"32.dll" );\r
+    }\r
+    else\r
+#endif\r
+    InjectDLL32( child_pi, hDllName );\r
+#endif\r
+    if (!gui && !(dwCreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))\r
+    {\r
+      LPPROCESS_INFORMATION cpi;\r
+      s_pid = child_pi->dwProcessId;\r
+      s_grm = grm;\r
+      s_flag = GRM_INIT;\r
+      cpi = malloc( sizeof(*cpi) );\r
+      cpi->dwProcessId = child_pi->dwProcessId;\r
+      DuplicateHandle( GetCurrentProcess(), child_pi->hProcess,\r
+                      GetCurrentProcess(), &cpi->hProcess, 0, FALSE,\r
+                      DUPLICATE_SAME_ACCESS );\r
+      CloseHandle( CreateThread( NULL, 4096, UpdateGRM, cpi, 0, NULL ) );\r
+    }\r
+  }\r
+\r
+  if (!(dwCreationFlags & CREATE_SUSPENDED))\r
+    ResumeThread( child_pi->hThread );\r
+\r
+  if (lpi)\r
+  {\r
+    memcpy( lpi, child_pi, sizeof(PROCESS_INFORMATION) );\r
+  }\r
+  else\r
+  {\r
+    CloseHandle( child_pi->hThread );\r
+    CloseHandle( child_pi->hProcess );\r
+  }\r
+}\r
+\r
+\r
+BOOL WINAPI MyCreateProcessA( LPCSTR lpApplicationName,\r
+                             LPSTR lpCommandLine,\r
+                             LPSECURITY_ATTRIBUTES lpThreadAttributes,\r
+                             LPSECURITY_ATTRIBUTES lpProcessAttributes,\r
+                             BOOL bInheritHandles,\r
+                             DWORD dwCreationFlags,\r
+                             LPVOID lpEnvironment,\r
+                             LPCSTR lpCurrentDirectory,\r
+                             LPSTARTUPINFOA lpStartupInfo,\r
+                             LPPROCESS_INFORMATION lpProcessInformation )\r
+{\r
+  PROCESS_INFORMATION child_pi;\r
+\r
+  if (!CreateProcessA( lpApplicationName,\r
+                      lpCommandLine,\r
+                      lpThreadAttributes,\r
+                      lpProcessAttributes,\r
+                      bInheritHandles,\r
+                      dwCreationFlags | CREATE_SUSPENDED,\r
+                      lpEnvironment,\r
+                      lpCurrentDirectory,\r
+                      lpStartupInfo,\r
+                      &child_pi ))\r
+    return FALSE;\r
+\r
+  DEBUGSTR( 1, L"CreateProcessA: (%lu) \"%S\", \"%S\"",\r
+           child_pi.dwProcessId,\r
+           (lpApplicationName == NULL) ? "" : lpApplicationName,\r
+           (lpCommandLine == NULL) ? "" : lpCommandLine );\r
+  Inject( dwCreationFlags, lpProcessInformation, &child_pi,\r
+         FALSE, lpApplicationName, lpCommandLine );\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+BOOL WINAPI MyCreateProcessW( LPCWSTR lpApplicationName,\r
+                             LPWSTR lpCommandLine,\r
+                             LPSECURITY_ATTRIBUTES lpThreadAttributes,\r
+                             LPSECURITY_ATTRIBUTES lpProcessAttributes,\r
+                             BOOL bInheritHandles,\r
+                             DWORD dwCreationFlags,\r
+                             LPVOID lpEnvironment,\r
+                             LPCWSTR lpCurrentDirectory,\r
+                             LPSTARTUPINFOW lpStartupInfo,\r
+                             LPPROCESS_INFORMATION lpProcessInformation )\r
+{\r
+  PROCESS_INFORMATION child_pi;\r
+\r
+  if (!CreateProcessW( lpApplicationName,\r
+                      lpCommandLine,\r
+                      lpThreadAttributes,\r
+                      lpProcessAttributes,\r
+                      bInheritHandles,\r
+                      dwCreationFlags | CREATE_SUSPENDED,\r
+                      lpEnvironment,\r
+                      lpCurrentDirectory,\r
+                      lpStartupInfo,\r
+                      &child_pi ))\r
+    return FALSE;\r
+\r
+  DEBUGSTR( 1, L"CreateProcessW: (%lu) \"%s\", \"%s\"",\r
+           child_pi.dwProcessId,\r
+           (lpApplicationName == NULL) ? L"" : lpApplicationName,\r
+           (lpCommandLine == NULL) ? L"" : lpCommandLine );\r
+  Inject( dwCreationFlags, lpProcessInformation, &child_pi,\r
+         TRUE, lpApplicationName, lpCommandLine );\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+FARPROC WINAPI MyGetProcAddress( HMODULE hModule, LPCSTR lpProcName )\r
+{\r
+  PHookFn hook;\r
+  FARPROC proc;\r
+\r
+  proc = GetProcAddress( hModule, lpProcName );\r
+\r
+  if (proc)\r
+  {\r
+    if (hModule == hKernel)\r
+    {\r
+      // Ignore LoadLibrary so other hooks continue to work (our version\r
+      // might end up at a different address).\r
+      if (proc == Hooks[0].oldfunc || proc == Hooks[1].oldfunc)\r
+      {\r
+       DEBUGSTR( 3, L"GetProcAddress: %S (ignoring)", lpProcName );\r
+       return proc;\r
+      }\r
+      for (hook = Hooks + 2; hook->name; ++hook)\r
+      {\r
+       if (proc == hook->oldfunc)\r
+       {\r
+         DEBUGSTR( 3, L"GetProcAddress: %S", lpProcName );\r
+         return hook->newfunc;\r
+       }\r
+      }\r
+    }\r
+    else\r
+    {\r
+      PAPI_DATA api;\r
+      for (api = APIs; api->name; ++api)\r
+      {\r
+       if (hModule == api->base)\r
+       {\r
+         if (proc == Hooks[0].apifunc || proc == Hooks[1].apifunc)\r
+         {\r
+           DEBUGSTR( 3, L"GetProcAddress: %S (ignoring)", lpProcName );\r
+           return proc;\r
+         }\r
+         for (hook = Hooks + 2; hook->name; ++hook)\r
+         {\r
+           if (proc == hook->apifunc)\r
+           {\r
+             DEBUGSTR( 3, L"GetProcAddress: %S", lpProcName );\r
+             return hook->newfunc;\r
+           }\r
+         }\r
+         break;\r
+       }\r
+      }\r
+    }\r
+  }\r
+\r
+  return proc;\r
+}\r
+\r
+\r
+void HookLibrary( HMODULE hMod, LPCVOID lpFileName, BOOL wide, LPCSTR funcName )\r
+{\r
+  LPCWSTR name;\r
+  WCHAR   wname[MAX_PATH];\r
+\r
+  if (hMod && hMod != hKernel)\r
+  {\r
+    if (!wide)\r
+    {\r
+      MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,\r
+                          lpFileName, -1, wname, MAX_PATH );\r
+      lpFileName = wname;\r
+    }\r
+    name = wcsrchr( lpFileName, '\\' );\r
+    if (name == NULL)\r
+      name = lpFileName;\r
+    else\r
+      ++name;\r
+    if (search_env( L"ANSICON_EXC", name ))\r
+      DEBUGSTR( 2, L"%s %s (%S)", zIgnoring, lpFileName, funcName );\r
+    else\r
+    {\r
+      DEBUGSTR( 2, L"%s %s (%S)", zHooking, lpFileName, funcName );\r
+      HookAPIOneMod( hMod, Hooks, FALSE );\r
+    }\r
+  }\r
+}\r
+\r
+\r
+HMODULE WINAPI MyLoadLibraryA( LPCSTR lpFileName )\r
+{\r
+  HMODULE hMod = LoadLibraryA( lpFileName );\r
+  HookLibrary( hMod, lpFileName, FALSE, "LoadLibraryA" );\r
+  return hMod;\r
+}\r
+\r
+\r
+HMODULE WINAPI MyLoadLibraryW( LPCWSTR lpFileName )\r
+{\r
+  HMODULE hMod = LoadLibraryW( lpFileName );\r
+  HookLibrary( hMod, lpFileName, TRUE, "LoadLibraryW" );\r
+  return hMod;\r
+}\r
+\r
+\r
+HMODULE WINAPI MyLoadLibraryExA( LPCSTR lpFileName, HANDLE hFile,\r
+                                DWORD dwFlags )\r
+{\r
+  HMODULE hMod = LoadLibraryExA( lpFileName, hFile, dwFlags );\r
+  if (!(dwFlags & LOAD_LIBRARY_AS_DATAFILE))\r
+    HookLibrary( hMod, lpFileName, FALSE, "LoadLibraryExA" );\r
+  return hMod;\r
+}\r
+\r
+\r
+HMODULE WINAPI MyLoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile,\r
+                                DWORD dwFlags )\r
+{\r
+  HMODULE hMod = LoadLibraryExW( lpFileName, hFile, dwFlags );\r
+  if (!(dwFlags & LOAD_LIBRARY_AS_DATAFILE))\r
+    HookLibrary( hMod, lpFileName, TRUE, "LoadLibraryExW" );\r
+  return hMod;\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+//   IsConsoleHandle\r
+// Determine if the handle is writing to the console, with processed output.\r
+//-----------------------------------------------------------------------------\r
+BOOL IsConsoleHandle( HANDLE h )\r
+{\r
+  DWORD mode;\r
+\r
+  if (!GetConsoleMode( h, &mode ))\r
+  {\r
+    // This fails if the handle isn't opened for reading.  Fortunately, it\r
+    // seems WriteConsole tests the handle before it tests the length.\r
+    return WriteConsole( h, NULL, 0, &mode, NULL );\r
+  }\r
+\r
+  return (mode & ENABLE_PROCESSED_OUTPUT);\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+//   MyWrite...\r
+// The new functions that must replace the original Write... functions.  These\r
+// functions have exactly the same signature as the original ones.  This\r
+// module is not hooked, so we can still call the original functions ourselves.\r
+//-----------------------------------------------------------------------------\r
+\r
+BOOL\r
+WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,\r
+                       DWORD nNumberOfCharsToWrite,\r
+                       LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )\r
+{\r
+  LPWSTR buf;\r
+  DWORD  len;\r
+  BOOL  rc = TRUE;\r
+\r
+  if (IsConsoleHandle( hCon ))\r
+  {\r
+    UINT cp = GetConsoleOutputCP();\r
+    DEBUGSTR( 4, L"\33WriteConsoleA: %lu \"%.*S\"",\r
+             nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );\r
+    len = MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, NULL,0 );\r
+    buf = malloc( TSIZE(len) );\r
+    if (buf == NULL)\r
+    {\r
+      if (lpNumberOfCharsWritten != NULL)\r
+       *lpNumberOfCharsWritten = 0;\r
+      return (nNumberOfCharsToWrite == 0);\r
+    }\r
+    MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, buf, len );\r
+    rc = ParseAndPrintString( hCon, buf, len, lpNumberOfCharsWritten );\r
+    free( buf );\r
+    if (rc && lpNumberOfCharsWritten != NULL &&\r
+             *lpNumberOfCharsWritten != nNumberOfCharsToWrite)\r
+    {\r
+      // Converting a multibyte character to Unicode results in a different\r
+      // "character" count.  This causes some programs to think not everything\r
+      // was written, so the difference is sent again. Fudge the (presumably)\r
+      // correct count.\r
+      if (search_env( L"ANSICON_API", prog ))\r
+       *lpNumberOfCharsWritten = nNumberOfCharsToWrite;\r
+    }\r
+    return rc;\r
+  }\r
+\r
+  return WriteConsoleA( hCon, lpBuffer, nNumberOfCharsToWrite,\r
+                       lpNumberOfCharsWritten, lpReserved );\r
+\r
+}\r
+\r
+BOOL\r
+WINAPI MyWriteConsoleW( HANDLE hCon, LPCVOID lpBuffer,\r
+                       DWORD nNumberOfCharsToWrite,\r
+                       LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved )\r
+{\r
+  if (IsConsoleHandle( hCon ))\r
+  {\r
+    DEBUGSTR( 4, L"\33WriteConsoleW: %lu \"%.*s\"",\r
+             nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );\r
+    return ParseAndPrintString( hCon, lpBuffer,\r
+                               nNumberOfCharsToWrite,\r
+                               lpNumberOfCharsWritten );\r
+  }\r
+\r
+  return WriteConsoleW( hCon, lpBuffer, nNumberOfCharsToWrite,\r
+                       lpNumberOfCharsWritten, lpReserved );\r
+}\r
+\r
+BOOL\r
+WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,\r
+                   LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped )\r
+{\r
+  if (IsConsoleHandle( hFile ))\r
+  {\r
+    DEBUGSTR( 4, L"WriteFile->" );\r
+    return MyWriteConsoleA( hFile, lpBuffer,\r
+                           nNumberOfBytesToWrite,\r
+                           lpNumberOfBytesWritten,\r
+                           lpOverlapped );\r
+  }\r
+\r
+  return WriteFile( hFile, lpBuffer, nNumberOfBytesToWrite,\r
+                   lpNumberOfBytesWritten, lpOverlapped );\r
+}\r
+\r
+\r
+#define HHFILE (HANDLE)(DWORD_PTR)\r
+\r
+UINT\r
+WINAPI My_lwrite( HFILE hFile, LPCSTR lpBuffer, UINT uBytes )\r
+{\r
+  if (IsConsoleHandle( HHFILE hFile ))\r
+  {\r
+    DWORD written;\r
+    DEBUGSTR( 4, L"_lwrite->" );\r
+    MyWriteConsoleA( HHFILE hFile, lpBuffer, uBytes, &written, NULL );\r
+    return written;\r
+  }\r
+\r
+  return _lwrite( hFile, lpBuffer, uBytes );\r
+}\r
+\r
+long\r
+WINAPI My_hwrite( HFILE hFile, LPCSTR lpBuffer, long lBytes )\r
+{\r
+  if (IsConsoleHandle( HHFILE hFile ))\r
+  {\r
+    DWORD written;\r
+    DEBUGSTR( 4, L"_hwrite->" );\r
+    MyWriteConsoleA( HHFILE hFile, lpBuffer, lBytes, &written, NULL );\r
+    return written;\r
+  }\r
+\r
+  return _hwrite( hFile, lpBuffer, lBytes );\r
+}\r
+\r
+\r
+// ========== Environment variable\r
+\r
+void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )\r
+{\r
+  CONSOLE_SCREEN_BUFFER_INFO csbi;\r
+  TCHAR buf[64];\r
+\r
+  if (pcsbi == NULL)\r
+  {\r
+    HANDLE hConOut;\r
+    hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,\r
+                                     FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+                                     NULL, OPEN_EXISTING, 0, 0 );\r
+    GetConsoleScreenBufferInfo( hConOut, &csbi );\r
+    CloseHandle( hConOut );\r
+    pcsbi = &csbi;\r
+  }\r
+\r
+  wsprintf( buf, L"%dx%d (%dx%d)",\r
+           pcsbi->dwSize.X, pcsbi->dwSize.Y,\r
+           pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1,\r
+           pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 );\r
+  SetEnvironmentVariable( L"ANSICON", buf );\r
+}\r
+\r
+DWORD\r
+WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )\r
+{\r
+  if (lstrcmpiA( lpName, "ANSICON_VER" ) == 0)\r
+  {\r
+    if (nSize < sizeof(PVEREA))\r
+      return sizeof(PVEREA);\r
+    memcpy( lpBuffer, PVEREA, sizeof(PVEREA) );\r
+    return sizeof(PVEREA) - 1;\r
+  }\r
+\r
+  if (lstrcmpiA( lpName, "ANSICON" ) == 0)\r
+    set_ansicon( NULL );\r
+\r
+  return GetEnvironmentVariableA( lpName, lpBuffer, nSize );\r
+}\r
+\r
+DWORD\r
+WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )\r
+{\r
+  if (lstrcmpi( lpName, L"ANSICON_VER" ) == 0)\r
+  {\r
+    if (nSize < lenof(PVERE))\r
+      return lenof(PVERE);\r
+    memcpy( lpBuffer, PVERE, sizeof(PVERE) );\r
+    return lenof(PVERE) - 1;\r
+  }\r
+\r
+  if (lstrcmpi( lpName, L"ANSICON" ) == 0)\r
+    set_ansicon( NULL );\r
+\r
+  return GetEnvironmentVariableW( lpName, lpBuffer, nSize );\r
+}\r
+\r
+\r
+// ========== Initialisation\r
+\r
+HookFn Hooks[] = {\r
+  // These two are expected first!\r
+  { APILibraryLoader,     "LoadLibraryA",            (PROC)MyLoadLibraryA,            NULL, NULL },\r
+  { APILibraryLoader,     "LoadLibraryW",            (PROC)MyLoadLibraryW,            NULL, NULL },\r
+  { APIProcessThreads,    "CreateProcessA",          (PROC)MyCreateProcessA,          NULL, NULL },\r
+  { APIProcessThreads,    "CreateProcessW",          (PROC)MyCreateProcessW,          NULL, NULL },\r
+  { APIProcessEnvironment, "GetEnvironmentVariableA", (PROC)MyGetEnvironmentVariableA, NULL, NULL },\r
+  { APIProcessEnvironment, "GetEnvironmentVariableW", (PROC)MyGetEnvironmentVariableW, NULL, NULL },\r
+  { APILibraryLoader,     "GetProcAddress",          (PROC)MyGetProcAddress,          NULL, NULL },\r
+  { APILibraryLoader,     "LoadLibraryExA",          (PROC)MyLoadLibraryExA,          NULL, NULL },\r
+  { APILibraryLoader,     "LoadLibraryExW",          (PROC)MyLoadLibraryExW,          NULL, NULL },\r
+  { APIConsole,           "WriteConsoleA",           (PROC)MyWriteConsoleA,           NULL, NULL },\r
+  { APIConsole,           "WriteConsoleW",           (PROC)MyWriteConsoleW,           NULL, NULL },\r
+  { APIFile,              "WriteFile",               (PROC)MyWriteFile,               NULL, NULL },\r
+  { APIKernel,            "_lwrite",                 (PROC)My_lwrite,                 NULL, NULL },\r
+  { APIKernel,            "_hwrite",                 (PROC)My_hwrite,                 NULL, NULL },\r
+  { NULL, NULL, NULL, NULL, NULL }\r
+};\r
+\r
+//-----------------------------------------------------------------------------\r
+//   OriginalAttr()\r
+// Determine the original attributes for use by \e[m.\r
+//-----------------------------------------------------------------------------\r
+void OriginalAttr( void )\r
+{\r
+  HANDLE hConOut;\r
+  CONSOLE_SCREEN_BUFFER_INFO csbi;\r
+\r
+  hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,\r
+                                   FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+                                   NULL, OPEN_EXISTING, 0, 0 );\r
+  if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))\r
+    csbi.wAttributes = 7;\r
+  CloseHandle( hConOut );\r
+\r
+  if (s_flag == GRM_INIT && s_pid == GetCurrentProcessId())\r
+  {\r
+    s_flag = 0;\r
+    grm = s_grm;\r
+  }\r
+  else\r
+  {\r
+    if (GetEnvironmentVariable( L"ANSICON_REVERSE", NULL, 0 ))\r
+    {\r
+      SetEnvironmentVariable( L"ANSICON_REVERSE", NULL );\r
+      grm.reverse = TRUE;\r
+      grm.foreground = attr2ansi[(csbi.wAttributes >> 4) & 7];\r
+      grm.background = attr2ansi[csbi.wAttributes & 7];\r
+      grm.bold      = (csbi.wAttributes & BACKGROUND_INTENSITY) >> 4;\r
+      grm.underline  = (csbi.wAttributes & FOREGROUND_INTENSITY) << 4;\r
+    }\r
+    else\r
+    {\r
+      grm.foreground = attr2ansi[csbi.wAttributes & 7];\r
+      grm.background = attr2ansi[(csbi.wAttributes >> 4) & 7];\r
+      grm.bold      = csbi.wAttributes & FOREGROUND_INTENSITY;\r
+      grm.underline  = csbi.wAttributes & BACKGROUND_INTENSITY;\r
+    }\r
+  }\r
+  if (!GetEnvironmentVariable( L"ANSICON_DEF", NULL, 0 ))\r
+  {\r
+    TCHAR  def[4];\r
+    LPTSTR a = def;\r
+    if (grm.reverse)\r
+    {\r
+      *a++ = '-';\r
+      csbi.wAttributes = ((csbi.wAttributes >> 4) & 15)\r
+                      | ((csbi.wAttributes & 15) << 4);\r
+    }\r
+    wsprintf( a, L"%X", csbi.wAttributes & 255 );\r
+    SetEnvironmentVariable( L"ANSICON_DEF", def );\r
+  }\r
+  set_ansicon( &csbi );\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+//   DllMain()\r
+// Function called by the system when processes and threads are initialized\r
+// and terminated.\r
+//-----------------------------------------------------------------------------\r
+\r
+__declspec(dllexport) // just to stop MinGW exporting everything\r
+BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )\r
+{\r
+  BOOL   bResult = TRUE;\r
+  PHookFn hook;\r
+  TCHAR   logstr[4];\r
+\r
+  if (dwReason == DLL_PROCESS_ATTACH)\r
+  {\r
+    *logstr = '\0';\r
+    GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );\r
+    log_level = _wtoi( logstr );\r
+    prog = get_program_name( NULL );\r
+#if defined(_WIN64) || defined(W32ON64)\r
+    hDllNameType = hDllName - 6 +\r
+#endif\r
+    GetModuleFileName( hInstance, hDllName, lenof(hDllName) );\r
+\r
+    hDllInstance = hInstance; // save Dll instance handle\r
+    DEBUGSTR( 1, L"hDllInstance = %p", hDllInstance );\r
+\r
+    // Get the entry points to the original functions.\r
+    hKernel = GetModuleHandleA( APIKernel );\r
+    for (hook = Hooks; hook->name; ++hook)\r
+      hook->oldfunc = GetProcAddress( hKernel, hook->name );\r
+\r
+    bResult = HookAPIAllMod( Hooks, FALSE );\r
+    OriginalAttr();\r
+    DisableThreadLibraryCalls( hInstance );\r
+  }\r
+  else if (dwReason == DLL_PROCESS_DETACH)\r
+  {\r
+    if (lpReserved == NULL)\r
+    {\r
+      DEBUGSTR( 1, L"Unloading" );\r
+      HookAPIAllMod( Hooks, TRUE );\r
+    }\r
+    else\r
+    {\r
+      DEBUGSTR( 1, L"Terminating" );\r
+      s_pid = GetCurrentProcessId();\r
+      s_grm = grm;\r
+      s_flag = GRM_EXIT;\r
+    }\r
+  }\r
+\r
+  return bResult;\r
+}\r
diff --git a/ansicon/COPYING.MinGW-w64-runtime.txt b/ansicon/COPYING.MinGW-w64-runtime.txt
deleted file mode 100755 (executable)
index 3d11e87..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-MinGW-w64 runtime licensing
-***************************
-
-This program or library was built using MinGW-w64 and statically
-linked against the MinGW-w64 runtime. Some parts of the runtime
-are under licenses which require that the copyright and license
-notices are included when distributing the code in binary form.
-These notices are listed below.
-
-
-========================
-Overall copyright notice
-========================
-
-Copyright (c) 2009, 2010 by the mingw-w64 project
-
-This license has been certified as open source. It has also been designated
-as GPL compatible by the Free Software Foundation (FSF).
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-   1. Redistributions in source code must retain the accompanying copyright
-      notice, this list of conditions, and the following disclaimer.
-   2. Redistributions in binary form must reproduce the accompanying
-      copyright notice, this list of conditions, and the following disclaimer
-      in the documentation and/or other materials provided with the
-      distribution.
-   3. Names of the copyright holders must not be used to endorse or promote
-      products derived from this software without prior written permission
-      from the copyright holders.
-   4. The right to distribute this software or to use it for any purpose does
-      not give you the right to use Servicemarks (sm) or Trademarks (tm) of
-      the copyright holders.  Use of them is covered by separate agreement
-      with the copyright holders.
-   5. If any files are modified, you must cause the modified files to carry
-      prominent notices stating that you changed the files and the date of
-      any change.
-
-Disclaimer
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
-OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
-OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-======================================== 
-getopt, getopt_long, and getop_long_only
-======================================== 
-
-Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> 
-Permission to use, copy, modify, and distribute this software for any 
-purpose with or without fee is hereby granted, provided that the above 
-copyright notice and this permission notice appear in all copies. 
-        
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Sponsored in part by the Defense Advanced Research Projects
-Agency (DARPA) and Air Force Research Laboratory, Air Force
-Materiel Command, USAF, under agreement number F39502-99-1-0512.
-
-        *       *       *       *       *       *       * 
-
-Copyright (c) 2000 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Dieter Baron and Thomas Klausner.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- 1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-
-===============================================================
-gdtoa: Converting between IEEE floating point numbers and ASCII
-===============================================================
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1997, 1998, 1999, 2000, 2001 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
-        *       *       *       *       *       *       *
-
-The author of this software is David M. Gay.
-
-Copyright (C) 2005 by David M. Gay
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that the copyright notice and this permission notice and warranty
-disclaimer appear in supporting documentation, and that the name of
-the author or any of his current or former employers not be used in
-advertising or publicity pertaining to distribution of the software
-without specific, written prior permission.
-
-THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN
-NO EVENT SHALL THE AUTHOR OR ANY OF HIS CURRENT OR FORMER EMPLOYERS BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-        *       *       *       *       *       *       *
-
-The author of this software is David M. Gay.
-
-Copyright (C) 2004 by David M. Gay.
-All Rights Reserved
-Based on material in the rest of /netlib/fp/gdota.tar.gz,
-which is copyright (C) 1998, 2000 by Lucent Technologies.
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
-
-=========================
-Parts of the math library
-=========================
-
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
-        *       *       *       *       *       *       *
-
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
-        *       *       *       *       *       *       *
-
-FIXME: Cephes math lib
-Copyright (C) 1984-1998 Stephen L. Moshier
-
-It sounds vague, but as to be found at
-<http://lists.debian.org/debian-legal/2004/12/msg00295.html>, it gives an
-impression that the author could be willing to give an explicit
-permission to distribute those files e.g. under a BSD style license. So
-probably there is no problem here, although it could be good to get a
-permission from the author and then add a license into the Cephes files
-in MinGW runtime. At least on follow-up it is marked that debian sees the
-version a-like BSD one. As MinGW.org (where those cephes parts are coming
-from) distributes them now over 6 years, it should be fine.
-
-===================================
-Headers and IDLs imported from Wine
-===================================
-
-Some header and IDL files were imported from the Wine project. These files
-are prominent maked in source. Their copyright belongs to contributors and
-they are distributed under LGPL license.
-
-Disclaimer
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
old mode 100755 (executable)
new mode 100644 (file)
index 37a6bb8..88b4fdb
@@ -1,18 +1,18 @@
-@echo off & setlocal
-
-::Extract the current code page.  Hopefully this method will work with other
-::languages.  CHCP outputs: "Active code page: #".  Take the last five
-::characters (the longest code) and delete up to and including the space.
-for /f "delims=" %%j in ('chcp') do set CP=%%j
-set CP=%CP:~-5%
-set CP=%CP:* =%
-
-x86\ansicon -e The DEC Special Graphics Character Set according to code page %CP%:^
-
-^
-
-       _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { ^| } ~^
-
-^
-
-\ e      _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { ^| } ~\ f
+@echo off & setlocal\r
+\r
+::Extract the current code page.  Hopefully this method will work with other\r
+::languages.  CHCP outputs: "Active code page: #".  Take the last five\r
+::characters (the longest code) and delete up to and including the space.\r
+for /f "delims=" %%j in ('chcp') do set CP=%%j\r
+set CP=%CP:~-5%\r
+set CP=%CP:* =%\r
+\r
+x86\ansicon -e The DEC Special Graphics Character Set according to code page %CP%:^\r
+\r
+^\r
+\r
+       _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { ^| } ~^\r
+\r
+^\r
+\r
+\ e      _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { ^| } ~\ f\r
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/ansicon/LICENSE.txt b/ansicon/LICENSE.txt
new file mode 100644 (file)
index 0000000..bc565e3
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright (C) 2005-2013 Jason Hood\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty.  In no event will the author be held liable for any damages\r
+arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any purpose,\r
+including commercial applications, and to alter it and redistribute it\r
+freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; you must not\r
+   claim that you wrote the original software. If you use this software\r
+   in a product, an acknowledgment in the product documentation would be\r
+   appreciated but is not required.\r
+2. Altered source versions must be plainly marked as such, and must not be\r
+   misrepresented as being the original software.\r
+3. This notice may not be removed or altered from any source distribution.\r
+\r
+Jason Hood\r
+jadoxa@yahoo.com.au\r
old mode 100755 (executable)
new mode 100644 (file)
index 16a4585..18e9eec
@@ -1,42 +1,36 @@
-/*
-  ansi.rc - Version resource for ANSI{32,64}.dll.
-
-  Jason Hood, 11 November, 2009.
-*/
-
-#include <winver.h>
-#include "version.h"
-
-#ifdef _WIN64
-# define BITS "64"
-#else
-# define BITS "32"
-#endif
-
-1 VERSIONINFO
-FILEVERSION    PVERB
-PRODUCTVERSION PVERB
-FILEOS         VOS_NT
-FILETYPE       VFT_DLL
-{
-  BLOCK "StringFileInfo"
-  {
-    BLOCK "040904B0"
-    {
-      VALUE "Comments",         "http://ansicon.adoxa.cjb.net/"
-      VALUE "CompanyName",      "Jason Hood"
-      VALUE "FileDescription",  "ANSI Console"
-      VALUE "FileVersion",      PVERSA
-      VALUE "InternalName",     "ANSI" BITS
-      VALUE "LegalCopyright",   "Freeware"
-      VALUE "OriginalFilename", "ANSI" BITS ".dll"
-      VALUE "ProductName",      "ANSICON"
-      VALUE "ProductVersion",   PVERSA
-    }
-  }
-
-  BLOCK "VarFileInfo"
-  {
-    VALUE "Translation", 0x0409, 0x04B0
-  }
-}
+/*\r
+  ansi.rc - Version resource for ANSI{32,64}.dll.\r
+\r
+  Jason Hood, 11 November, 2009.\r
+*/\r
+\r
+#include <winver.h>\r
+#include "version.h"\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+FILEVERSION    PVERB\r
+PRODUCTVERSION PVERB\r
+FILEOS         VOS_NT\r
+FILETYPE       VFT_DLL\r
+{\r
+  BLOCK "StringFileInfo"\r
+  {\r
+    BLOCK "040904B0"\r
+    {\r
+      VALUE "Comments",         "http://ansicon.adoxa.vze.com/"\r
+      VALUE "CompanyName",      "Jason Hood"\r
+      VALUE "FileDescription",  "ANSI Console"\r
+      VALUE "FileVersion",      PVERSA\r
+      VALUE "InternalName",     "ANSI" BITS\r
+      VALUE "LegalCopyright",   "Freeware"\r
+      VALUE "OriginalFilename", ANSIDLL\r
+      VALUE "ProductName",      "ANSICON"\r
+      VALUE "ProductVersion",   PVERSA\r
+    }\r
+  }\r
+\r
+  BLOCK "VarFileInfo"\r
+  {\r
+    VALUE "Translation", 0x0409, 0x04B0\r
+  }\r
+}\r
old mode 100755 (executable)
new mode 100644 (file)
index 2b87abe..4368a55
-/*
-  ANSICON.c - ANSI escape sequence console driver.
-
-  Jason Hood, 21 to 23 October, 2005.
-
-  Original injection code was derived from Console Manager by Sergey Oblomov
-  (hoopoepg).  Use of FlushInstructionCache came from www.catch22.net.
-  Additional information came from "Process-wide API spying - an ultimate hack",
-  Anton Bassov's article in "The Code Project" (use of OpenThread).
-
-  v1.01, 11 & 12 March, 2006:
-    -m option to set "monochrome" (grey on black);
-    restore original color on exit.
-
-  v1.10, 22 February, 2009:
-    ignore Ctrl+C/Ctrl+Break.
-
-  v1.13, 21 & 27 March, 2009:
-    alternate injection method, to work with DEP;
-    use Unicode.
-
-  v1.20, 17 to 21 June, 2009:
-    use a combination of the two injection methods;
-    test if ANSICON is already installed;
-    added -e (and -E) option to echo the command line (without newline);
-    added -t (and -T) option to type (display) files (with file name).
-
-  v1.21, 23 September, 2009:
-    added -i (and -u) to add (remove) ANSICON to AutoRun.
-
-  v1.24, 6 & 7 January, 2010:
-    no arguments to -t, or using "-" for the name, will read from stdin;
-    fix -t and -e when ANSICON was already loaded.
-
-  v1.25, 22 July, 2010:
-    added -IU for HKLM.
-
-  v1.30, 3 August to 7 September, 2010:
-    x64 support.
-
-  v1.31, 13 & 15 November, 2010:
-    use LLW to fix potential Unicode path problems;
-    VC compatibility (2008 Express for 32-bit, PSDK 2003 R2 for 64-bit);
-    explicitly use wide characters (stick with TCHAR, but not <tchar.h>).
-
-  v1.32, 4 to 22 December, 2010:
-    make -p more robust;
-    inject into GUI processes;
-    -i implies -p.
-
-  v1.50, 7 to 14 December, 2011:
-    -u does not imply -p;
-    add the PID to the debugging output;
-    use ANSICON_VER to test if already installed;
-    always place first in AutoRun;
-    logging is always available, controlled by ANSICON_LOG environment variable;
-    only restore the original color after program/echo/type;
-    return program's exit code.
-
-  7 January, 2012:
-    fixed installing into a piped CMD.EXE;
-    added a log message indicating all imports have been processed.
-
-  v1.52, 10 April, 2012:
-    fixed running "cmd" if "ComSpec" is not defined;
-    pass process & thread identifiers on the command line (for x86->x64).
-*/
-
-#define PDATE L"12 June, 2012"
-
-#include "ansicon.h"
-#include "version.h"
-#include <tlhelp32.h>
-#include <ctype.h>
-#include <io.h>
-
-#ifdef __MINGW32__
-int _CRT_glob = 0;
-#endif
-
-
-#ifdef _WIN64
-# define BITS L"64"
-#else
-# define BITS L"32"
-#endif
-
-
-#define CMDKEY L"Software\\Microsoft\\Command Processor"
-#define AUTORUN L"AutoRun"
-
-
-void   help( void );
-
-void   display( LPCTSTR, BOOL );
-void   print_error( LPCTSTR, ... );
-LPTSTR skip_spaces( LPTSTR );
-void   get_arg( LPTSTR, LPTSTR*, LPTSTR* );
-
-void   process_autorun( TCHAR );
-
-BOOL   find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe );
-BOOL   GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR );
-
-
-// Find the name of the DLL and inject it.
-BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app )
-{
-  DWORD len;
-  WCHAR dll[MAX_PATH];
-  int  type;
-
-  DEBUGSTR( 1, L"%s (%lu)", app, ppi->dwProcessId );
-  type = ProcessType( ppi, gui );
-  if (type == 0)
-  {
-    fwprintf( stderr, L"ANSICON: %s: unsupported process.\n", app );
-    return FALSE;
-  }
-
-  len = (DWORD)(prog - prog_path);
-  memcpy( dll, prog_path, TSIZE(len) );
-#ifdef _WIN64
-  wsprintf( dll + len, L"ANSI%d.dll", type );
-  if (type == 32)
-    InjectDLL32( ppi, dll );
-  else
-    InjectDLL64( ppi, dll );
-#else
-  wcscpy( dll + len, L"ANSI32.dll" );
-  InjectDLL32( ppi, dll );
-#endif
-  return TRUE;
-}
-
-
-static HANDLE hConOut;
-static CONSOLE_SCREEN_BUFFER_INFO csbi;
-
-void get_original_attr( void )
-{
-  hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
-                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                   NULL, OPEN_EXISTING, 0, 0 );
-  GetConsoleScreenBufferInfo( hConOut, &csbi );
-}
-
-
-void set_original_attr( void )
-{
-  SetConsoleTextAttribute( hConOut, csbi.wAttributes );
-  CloseHandle( hConOut );
-}
-
-
-DWORD CtrlHandler( DWORD event )
-{
-  return (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT);
-}
-
-
-int main( void )
-{
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  LPTSTR  argv, arg, cmd;
-  TCHAR   logstr[4];
-  BOOL   installed;
-  BOOL   shell, run, gui;
-  HMODULE ansi;
-  DWORD   len;
-  int    rc = 0;
-
-  argv = GetCommandLine();
-  len = (DWORD)wcslen( argv ) + 1;
-  if (len < MAX_PATH)
-    len = MAX_PATH;
-  arg = malloc( TSIZE(len) );
-  get_arg( arg, &argv, &cmd ); // skip the program name
-  get_arg( arg, &argv, &cmd );
-
-  if (*arg)
-  {
-    if (wcscmp( arg, L"/?" ) == 0 ||
-       wcscmp( arg, L"--help" ) == 0)
-    {
-      help();
-      return rc;
-    }
-    if (wcscmp( arg, L"--version" ) == 0)
-    {
-      _putws( L"ANSICON (" BITS L"-bit) version " PVERS L" (" PDATE L")." );
-      return rc;
-    }
-  }
-
-  prog = get_program_name( NULL );
-  *logstr = '\0';
-  GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
-  log_level = _wtoi( logstr );
-
-#ifdef _WIN64
-  if (*arg == '-' && arg[1] == 'P')
-  {
-    swscanf( arg + 2, L"%u:%u", &pi.dwProcessId, &pi.dwThreadId );
-    pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
-    pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId );
-    Inject( &pi, &gui, arg );
-    CloseHandle( pi.hThread );
-    CloseHandle( pi.hProcess );
-    return 0;
-  }
-#endif
-
-  if (log_level && !(log_level & 8))
-    DEBUGSTR( 1, NULL );       // create a new file
-
-  installed = (GetEnvironmentVariable( L"ANSICON_VER", NULL, 0 ) != 0);
-  // If it's already installed, remove it.  This serves two purposes: preserves
-  // the parent's GRM; and unconditionally injects into GUI, without having to
-  // worry about ANSICON_GUI.
-  if (installed)
-  {
-    fputws( L"\33[m", stdout );
-    FreeLibrary( GetModuleHandle( L"ANSI" BITS L".dll" ) );
-  }
-
-  shell = run = TRUE;
-  get_original_attr();
-
-  while (*arg == '-')
-  {
-    switch (arg[1])
-    {
-      case 'l':
-       SetEnvironmentVariable( L"ANSICON_LOG", arg + 2 );
-       log_level = _wtoi( arg + 2 );
-       if (!(log_level & 8))           // unless told otherwise
-         DEBUGSTR( 1, NULL );          // create a new file
-       break;
-
-      case 'i':
-      case 'I':
-      case 'u':
-      case 'U':
-       shell = FALSE;
-       process_autorun( arg[1] );
-       if (arg[1] == 'u' || arg[1] == 'U')
-         break;
-       // else fall through
-
-      case 'p':
-       shell = FALSE;
-       // If it's already installed, there's no need to do anything.
-       if (installed)
-       {
-         DEBUGSTR( 1, L"Already installed" );
-       }
-       else if (GetParentProcessInfo( &pi, arg ))
-       {
-         pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
-         pi.hThread  = OpenThread( THREAD_ALL_ACCESS,  FALSE, pi.dwThreadId );
-         SuspendThread( pi.hThread );
-         if (!Inject( &pi, &gui, arg ))
-           rc = 1;
-         ResumeThread( pi.hThread );
-         CloseHandle( pi.hThread );
-         CloseHandle( pi.hProcess );
-       }
-       else
-       {
-         fputws( L"ANSICON: could not obtain the parent process.\n", stderr );
-         rc = 1;
-       }
-       break;
-
-      case 'm':
-      {
-       int a = wcstol( arg + 2, NULL, 16 );
-       if (a == 0)
-         a = (arg[2] == '-') ? -7 : 7;
-       if (a < 0)
-       {
-         SetEnvironmentVariable( L"ANSICON_REVERSE", L"1" );
-         a = -a;
-         a = ((a >> 4) & 15) | ((a & 15) << 4);
-       }
-       SetConsoleTextAttribute( hConOut, a );
-       SetEnvironmentVariable( L"ANSICON_DEF", NULL );
-       break;
-      }
-
-      case 'e':
-      case 'E':
-      case 't':
-      case 'T':
-       run = FALSE;
-       ++arg;
-       goto arg_out;
-    }
-    get_arg( arg, &argv, &cmd );
-  }
-arg_out:
-  if (run && *cmd == '\0')
-  {
-    if (!shell)
-      run = FALSE;
-    else if (!_isatty( 0 ))
-    {
-      *arg = 't';
-      run = FALSE;
-    }
-  }
-
-  if (run)
-  {
-    if (*cmd == '\0')
-    {
-      cmd = _wgetenv( L"ComSpec" );
-      if (cmd == NULL)
-      {
-       // CreateProcessW writes to the string, so can't simply point to "cmd".
-       static TCHAR cmdstr[] = L"cmd";
-       cmd = cmdstr;
-      }
-      arg = cmd;
-    }
-
-    ZeroMemory( &si, sizeof(si) );
-    si.cb = sizeof(si);
-    if (CreateProcess( NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
-                      NULL, NULL, &si, &pi ))
-    {
-      Inject( &pi, &gui, arg );
-      ResumeThread( pi.hThread );
-      if (!gui)
-      {
-       SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
-       WaitForSingleObject( pi.hProcess, INFINITE );
-       GetExitCodeProcess( pi.hProcess, (LPDWORD)(LPVOID)&rc );
-      }
-      CloseHandle( pi.hProcess );
-      CloseHandle( pi.hThread );
-    }
-    else
-    {
-      print_error( arg, arg );
-      rc = 1;
-    }
-  }
-  else if (*arg)
-  {
-    ansi = LoadLibrary( L"ANSI" BITS L".dll" );
-    if (ansi == NULL)
-    {
-      print_error( L"ANSI" BITS L".dll" );
-      rc = 1;
-    }
-
-    if (*arg == 'e' || *arg == 'E')
-    {
-      cmd += 2;
-      if (*cmd == ' ' || *cmd == '\t')
-       ++cmd;
-      fputws( cmd, stdout );
-      if (*arg == 'e')
-       putwchar( '\n' );
-    }
-    else // (*arg == 't' || *arg == 'T')
-    {
-      BOOL title = (*arg == 'T');
-      get_arg( arg, &argv, &cmd );
-      if (*arg == '\0')
-       wcscpy( arg, L"-" );
-      do
-      {
-       if (title)
-       {
-         wprintf( L"==> %s <==\n", arg );
-         display( arg, title );
-         putwchar( '\n' );
-       }
-       else
-         display( arg, title );
-       get_arg( arg, &argv, &cmd );
-      } while (*arg);
-    }
-
-    FreeLibrary( ansi );
-  }
-
-  if (run || *arg)
-    set_original_attr();
-  else
-    CloseHandle( hConOut );
-
-  return rc;
-}
-
-
-// Display a file.
-void display( LPCTSTR name, BOOL title )
-{
-  HANDLE in, out;
-  BOOL  pipe;
-  char  buf[8192];
-  DWORD  len;
-
-  if (*name == '-' && name[1] == '\0')
-  {
-    pipe = TRUE;
-    in = GetStdHandle( STD_INPUT_HANDLE );
-  }
-  else
-  {
-    pipe = FALSE;
-    in = CreateFile( name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
-                    NULL, OPEN_EXISTING, 0, NULL );
-    if (in == INVALID_HANDLE_VALUE)
-    {
-      print_error( name );
-      return;
-    }
-  }
-  if (title)
-  {
-    putwchar( '\n' );
-    // Need to flush, otherwise it's written *after* STD_OUTPUT_HANDLE should
-    // it be redirected.
-    fflush( stdout );
-  }
-  out = GetStdHandle( STD_OUTPUT_HANDLE );
-  for (;;)
-  {
-    if (!ReadFile( in, buf, sizeof(buf), &len, NULL ))
-    {
-      if (GetLastError() != ERROR_BROKEN_PIPE)
-       print_error( name );
-      break;
-    }
-    if (len == 0)
-      break;
-    WriteFile( out, buf, len, &len, NULL );
-  }
-  if (!pipe)
-    CloseHandle( in );
-}
-
-
-void print_error( LPCTSTR name, ... )
-{
-  LPTSTR errmsg = NULL;
-  DWORD err = GetLastError();
-  va_list arg;
-
-  if (err == ERROR_BAD_EXE_FORMAT)
-  {
-    // This error requires an argument, which is a duplicate of name.
-    va_start( arg, name );
-    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                  NULL, err, 0, (LPTSTR)(LPVOID)&errmsg, 0, &arg );
-    va_end( arg );
-    fwprintf( stderr, L"ANSICON: %s", errmsg );
-  }
-  else
-  {
-    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                  NULL, err, 0, (LPTSTR)(LPVOID)&errmsg, 0, NULL );
-    // Just in case there are other messages requiring args...
-    if (errmsg == NULL)
-      fwprintf( stderr, L"ANSICON: %s: Error %lu.\n", name, err );
-    else
-      fwprintf( stderr, L"ANSICON: %s: %s", name, errmsg );
-  }
-  LocalFree( errmsg );
-}
-
-
-// Add or remove ANSICON to AutoRun.
-void process_autorun( TCHAR cmd )
-{
-  HKEY  cmdkey;
-  TCHAR  ansicon[MAX_PATH+80];
-  TCHAR  logstr[80];
-  LPTSTR autorun, ansirun;
-  DWORD  len, type, exist;
-  BOOL  inst;
-
-  if (log_level)
-    _snwprintf( logstr, lenof(logstr), L"set ANSICON_LOG=%d&", log_level );
-  else
-    *logstr = '\0';
-  len = TSIZE(_snwprintf( ansicon, lenof(ansicon),
-               L"(if %%ANSICON_VER%%==^%%ANSICON_VER^%% %s\"%s\" -p)",
-               logstr, prog_path ) + 1);
-
-  inst = (towlower( cmd ) == 'i');
-  RegCreateKeyEx( (iswlower( cmd )) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
-                 CMDKEY, 0, NULL,
-                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
-                 &cmdkey, &exist );
-  exist = 0;
-  RegQueryValueEx( cmdkey, AUTORUN, NULL, NULL, NULL, &exist );
-  if (exist == 0)
-  {
-    if (inst)
-      RegSetValueEx( cmdkey, AUTORUN, 0, REG_SZ, (PBYTE)ansicon, len );
-  }
-  else
-  {
-    // Let's assume there's sufficient memory.
-    autorun = malloc( exist + len );
-    RegQueryValueEx( cmdkey, AUTORUN, NULL, &type, (PBYTE)autorun, &exist );
-    // Remove the existing command, if present.
-    ansirun = wcsstr( autorun, L"(if %ANSICON_VER%" );
-    if (ansirun != NULL)
-    {
-      LPTSTR tmp = wcschr( ansirun, '"' );      // opening quote
-      tmp = wcschr( tmp + 1, '"' );             // closing quote
-      tmp = wcschr( tmp + 1, ')' );             // closing bracket
-      if (*++tmp == '&')
-       ++tmp;
-      if (*tmp == '&')
-       ++tmp;
-      if (*tmp == '\0')
-      {
-       if (ansirun > autorun && ansirun[-1] == '&')
-         --ansirun;
-       if (ansirun > autorun && ansirun[-1] == '&')
-         --ansirun;
-      }
-      wcscpy( ansirun, tmp );
-      exist = TSIZE((DWORD)wcslen( autorun ) + 1);
-    }
-    if (inst)
-    {
-      if (exist == sizeof(TCHAR))
-       RegSetValueEx( cmdkey, AUTORUN, 0, REG_SZ, (PBYTE)ansicon, len );
-      else
-      {
-       memmove( (PBYTE)autorun + len, autorun, exist );
-       memcpy( autorun, ansicon, len );
-       ((PBYTE)autorun)[len-sizeof(TCHAR)] = '&';
-       RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun, exist+len );
-      }
-    }
-    else
-    {
-      if (exist == sizeof(TCHAR))
-       RegDeleteValue( cmdkey, AUTORUN );
-      else
-       RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun, exist );
-    }
-    free( autorun );
-  }
-  RegCloseKey( cmdkey );
-}
-
-
-// Search each process in the snapshot for id.
-BOOL find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe )
-{
-  BOOL fOk;
-
-  ppe->dwSize = sizeof(PROCESSENTRY32);
-  for (fOk = Process32First( snap, ppe ); fOk; fOk = Process32Next( snap, ppe ))
-    if (ppe->th32ProcessID == id)
-      break;
-
-  return fOk;
-}
-
-
-// Obtain the process and thread identifiers of the parent process.
-BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR name )
-{
-  HANDLE hSnap;
-  PROCESSENTRY32 pe;
-  THREADENTRY32  te;
-  BOOL  fOk;
-
-  hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD, 0 );
-
-  if (hSnap == INVALID_HANDLE_VALUE)
-    return FALSE;
-
-  find_proc_id( hSnap, GetCurrentProcessId(), &pe );
-  if (!find_proc_id( hSnap, pe.th32ParentProcessID, &pe ))
-  {
-    CloseHandle( hSnap );
-    return FALSE;
-  }
-
-  te.dwSize = sizeof(te);
-  for (fOk = Thread32First( hSnap, &te ); fOk; fOk = Thread32Next( hSnap, &te ))
-    if (te.th32OwnerProcessID == pe.th32ProcessID)
-      break;
-
-  CloseHandle( hSnap );
-
-  ppi->dwProcessId = pe.th32ProcessID;
-  ppi->dwThreadId  = te.th32ThreadID;
-  wcscpy( name, pe.szExeFile );
-
-  return fOk;
-}
-
-
-// Return the first non-space character from arg.
-LPTSTR skip_spaces( LPTSTR arg )
-{
-  while (*arg == ' ' || *arg == '\t')
-    ++arg;
-
-  return arg;
-}
-
-
-// Retrieve an argument from the command line. cmd gets the existing argv; argv
-// is ready for the next argument.
-void get_arg( LPTSTR arg, LPTSTR* argv, LPTSTR* cmd )
-{
-  LPTSTR line;
-
-  line = *cmd = skip_spaces( *argv );
-  while (*line != '\0')
-  {
-    if (*line == ' ' || *line == '\t')
-    {
-      ++line;
-      break;
-    }
-    if (*line == '"')
-    {
-      while (*++line != '\0')
-      {
-       if (*line == '"')
-       {
-         ++line;
-         break;
-       }
-       *arg++ = *line;
-      }
-    }
-    else
-      *arg++ = *line++;
-  }
-  *arg = '\0';
-  *argv = line;
-}
-
-
-void help( void )
-{
-  _putws(
-L"ANSICON by Jason Hood <jadoxa@yahoo.com.au>.\n"
-L"Version " PVERS L" (" PDATE L").  Freeware.\n"
-L"http://ansicon.adoxa.cjb.net/\n"
-L"\n"
-#ifdef _WIN64
-L"Process ANSI escape sequences in Windows console programs.\n"
-#else
-L"Process ANSI escape sequences in Win32 console programs.\n"
-#endif
-L"\n"
-L"ansicon [-l<level>] [-i] [-I] [-u] [-U] [-m[<attr>]] [-p]\n"
-L"        [-e|E string | -t|T [file(s)] | program [args]]\n"
-L"\n"
-L"  -l\t\tset the logging level (1=process, 2=module, 3=function,\n"
-L"    \t\t +4=output, +8=append) for program (-p is unaffected)\n"
-L"  -i\t\tinstall - add ANSICON to the AutoRun entry (also implies -p)\n"
-L"  -u\t\tuninstall - remove ANSICON from the AutoRun entry\n"
-L"  -I -U\t\tuse local machine instead of current user\n"
-L"  -m\t\tuse grey on black (\"monochrome\") or <attr> as default color\n"
-L"  -p\t\thook into the parent process\n"
-L"  -e\t\techo string\n"
-L"  -E\t\techo string, don't append newline\n"
-L"  -t\t\tdisplay files (\"-\" for stdin), combined as a single stream\n"
-L"  -T\t\tdisplay files, name first, blank line before and after\n"
-L"  program\trun the specified program\n"
-L"  nothing\trun a new command processor, or display stdin if redirected\n"
-L"\n"
-L"<attr> is one or two hexadecimal digits; please use \"COLOR /?\" for details.\n"
-L"It may start with '-' to reverse foreground and background (but not for -p)."
-       );
-}
+/*\r
+  ANSICON.c - ANSI escape sequence console driver.\r
+\r
+  Jason Hood, 21 to 23 October, 2005.\r
+\r
+  Original injection code was derived from Console Manager by Sergey Oblomov\r
+  (hoopoepg).  Use of FlushInstructionCache came from www.catch22.net.\r
+  Additional information came from "Process-wide API spying - an ultimate hack",\r
+  Anton Bassov's article in "The Code Project" (use of OpenThread).\r
+\r
+  v1.01, 11 & 12 March, 2006:\r
+    -m option to set "monochrome" (grey on black);\r
+    restore original color on exit.\r
+\r
+  v1.10, 22 February, 2009:\r
+    ignore Ctrl+C/Ctrl+Break.\r
+\r
+  v1.13, 21 & 27 March, 2009:\r
+    alternate injection method, to work with DEP;\r
+    use Unicode.\r
+\r
+  v1.20, 17 to 21 June, 2009:\r
+    use a combination of the two injection methods;\r
+    test if ANSICON is already installed;\r
+    added -e (and -E) option to echo the command line (without newline);\r
+    added -t (and -T) option to type (display) files (with file name).\r
+\r
+  v1.21, 23 September, 2009:\r
+    added -i (and -u) to add (remove) ANSICON to AutoRun.\r
+\r
+  v1.24, 6 & 7 January, 2010:\r
+    no arguments to -t, or using "-" for the name, will read from stdin;\r
+    fix -t and -e when ANSICON was already loaded.\r
+\r
+  v1.25, 22 July, 2010:\r
+    added -IU for HKLM.\r
+\r
+  v1.30, 3 August to 7 September, 2010:\r
+    x64 support.\r
+\r
+  v1.31, 13 & 15 November, 2010:\r
+    use LLW to fix potential Unicode path problems;\r
+    VC compatibility (2008 Express for 32-bit, PSDK 2003 R2 for 64-bit);\r
+    explicitly use wide characters (stick with TCHAR, but not <tchar.h>).\r
+\r
+  v1.32, 4 to 22 December, 2010:\r
+    make -p more robust;\r
+    inject into GUI processes;\r
+    -i implies -p.\r
+\r
+  v1.50, 7 to 14 December, 2011:\r
+    -u does not imply -p;\r
+    add the PID to the debugging output;\r
+    use ANSICON_VER to test if already installed;\r
+    always place first in AutoRun;\r
+    logging is always available, controlled by ANSICON_LOG environment variable;\r
+    only restore the original color after program/echo/type;\r
+    return program's exit code.\r
+\r
+  7 January, 2012:\r
+    fixed installing into a piped CMD.EXE;\r
+    added a log message indicating all imports have been processed.\r
+\r
+  v1.52, 10 April, 2012:\r
+    fixed running "cmd" if "ComSpec" is not defined;\r
+    pass process & thread identifiers on the command line (for x86->x64).\r
+\r
+  v1.60, 22 & 24 November, 2012:\r
+    set the code page to convert strings correctly;\r
+    expand wildcards for -t;\r
+    write the date if appending to the log.\r
+\r
+  v1.62, 18 July, 2013:\r
+    write the bits to the log;\r
+    test if creating the registry key fails (HKLM requires admin privileges).\r
+\r
+  v1.63, 25 July, 2013:\r
+    don't write the reset sequence if output is redirected.\r
+*/\r
+\r
+#define PDATE L"21 September, 2013"\r
+\r
+#include "ansicon.h"\r
+#include "version.h"\r
+#include <tlhelp32.h>\r
+#include <ctype.h>\r
+#include <io.h>\r
+#include <locale.h>\r
+\r
+#ifdef __MINGW32__\r
+int _CRT_glob = 0;\r
+#endif\r
+\r
+\r
+#define CMDKEY L"Software\\Microsoft\\Command Processor"\r
+#define AUTORUN L"AutoRun"\r
+\r
+\r
+void   help( void );\r
+\r
+void   display( LPCTSTR, BOOL );\r
+void   print_error( LPCTSTR, ... );\r
+LPTSTR skip_spaces( LPTSTR );\r
+void   get_arg( LPTSTR, LPTSTR*, LPTSTR* );\r
+void   get_file( LPTSTR, LPTSTR*, LPTSTR* );\r
+\r
+void   process_autorun( TCHAR );\r
+\r
+BOOL   find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe );\r
+BOOL   GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR );\r
+\r
+\r
+// The DLL shares this variable, so injection requires it here.\r
+#ifdef _WIN64\r
+DWORD  LLW32;\r
+extern LPVOID base;\r
+#endif\r
+\r
+\r
+// Find the name of the DLL and inject it.\r
+BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app )\r
+{\r
+  DWORD len;\r
+  WCHAR dll[MAX_PATH];\r
+  int  type;\r
+\r
+  DEBUGSTR( 1, L"%s (%lu)", app, ppi->dwProcessId );\r
+  type = ProcessType( ppi, gui );\r
+  if (type == 0)\r
+  {\r
+    fwprintf( stderr, L"ANSICON: %s: unsupported process.\n", app );\r
+    return FALSE;\r
+  }\r
+\r
+  len = (DWORD)(prog - prog_path);\r
+  memcpy( dll, prog_path, TSIZE(len) );\r
+#ifdef _WIN64\r
+  wsprintf( dll + len, L"ANSI%d.dll", type );\r
+  if (type == 32)\r
+    InjectDLL32( ppi, dll );\r
+  else\r
+    InjectDLL64( ppi, dll );\r
+#else\r
+  wcscpy( dll + len, L"ANSI32.dll" );\r
+  InjectDLL32( ppi, dll );\r
+#endif\r
+  return TRUE;\r
+}\r
+\r
+\r
+static HANDLE hConOut;\r
+static CONSOLE_SCREEN_BUFFER_INFO csbi;\r
+\r
+void get_original_attr( void )\r
+{\r
+  hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,\r
+                                   FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+                                   NULL, OPEN_EXISTING, 0, 0 );\r
+  GetConsoleScreenBufferInfo( hConOut, &csbi );\r
+}\r
+\r
+\r
+void set_original_attr( void )\r
+{\r
+  SetConsoleTextAttribute( hConOut, csbi.wAttributes );\r
+  CloseHandle( hConOut );\r
+}\r
+\r
+\r
+DWORD CtrlHandler( DWORD event )\r
+{\r
+  return (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT);\r
+}\r
+\r
+\r
+int main( void )\r
+{\r
+  STARTUPINFO si;\r
+  PROCESS_INFORMATION pi;\r
+  LPTSTR  argv, arg, cmd;\r
+  TCHAR   logstr[4];\r
+  BOOL   installed;\r
+  BOOL   shell, run, gui;\r
+  HMODULE ansi;\r
+  DWORD   len;\r
+  int    rc = 0;\r
+\r
+  argv = GetCommandLine();\r
+  len = (DWORD)wcslen( argv ) + 1;\r
+  if (len < MAX_PATH)\r
+    len = MAX_PATH;\r
+  arg = malloc( TSIZE(len) );\r
+  get_arg( arg, &argv, &cmd ); // skip the program name\r
+  get_arg( arg, &argv, &cmd );\r
+\r
+  if (*arg)\r
+  {\r
+    if (wcscmp( arg, L"/?" ) == 0 ||\r
+       wcscmp( arg, L"--help" ) == 0)\r
+    {\r
+      help();\r
+      return rc;\r
+    }\r
+    if (wcscmp( arg, L"--version" ) == 0)\r
+    {\r
+      _putws( L"ANSICON (" BITS L"-bit) version " PVERS L" (" PDATE L")." );\r
+      return rc;\r
+    }\r
+  }\r
+\r
+  prog = get_program_name( NULL );\r
+  *logstr = '\0';\r
+  GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );\r
+  log_level = _wtoi( logstr );\r
+\r
+  // Using "" for setlocale uses the system ANSI code page.\r
+  sprintf( (LPSTR)logstr, ".%u", GetConsoleOutputCP() );\r
+  setlocale( LC_CTYPE, (LPSTR)logstr );\r
+\r
+#ifdef _WIN64\r
+  if (*arg == '-' && arg[1] == 'P')\r
+  {\r
+    swscanf( arg + 2, L"%u:%u", &pi.dwProcessId, &pi.dwThreadId );\r
+    pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);\r
+    pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId );\r
+    Inject( &pi, &gui, arg );\r
+    CloseHandle( pi.hThread );\r
+    CloseHandle( pi.hProcess );\r
+    return 0;\r
+  }\r
+#endif\r
+\r
+  if (log_level)\r
+    DEBUGSTR( 1, NULL );       // start a new session\r
+\r
+  installed = (GetEnvironmentVariable( L"ANSICON_VER", NULL, 0 ) != 0);\r
+  // If it's already installed, remove it.  This serves two purposes: preserves\r
+  // the parent's GRM; and unconditionally injects into GUI, without having to\r
+  // worry about ANSICON_GUI.\r
+  if (installed)\r
+  {\r
+    if (_isatty( 1 ))\r
+      fputws( L"\33[m", stdout );\r
+    FreeLibrary( GetModuleHandle( ANSIDLL ) );\r
+  }\r
+\r
+  shell = run = TRUE;\r
+  get_original_attr();\r
+\r
+  while (*arg == '-')\r
+  {\r
+    switch (arg[1])\r
+    {\r
+      case 'l':\r
+       SetEnvironmentVariable( L"ANSICON_LOG", arg + 2 );\r
+       log_level = _wtoi( arg + 2 );\r
+       DEBUGSTR( 1, NULL );            // create a session\r
+       break;\r
+\r
+      case 'i':\r
+      case 'I':\r
+      case 'u':\r
+      case 'U':\r
+       shell = FALSE;\r
+       process_autorun( arg[1] );\r
+       if (arg[1] == 'u' || arg[1] == 'U')\r
+         break;\r
+       // else fall through\r
+\r
+      case 'p':\r
+       shell = FALSE;\r
+       // If it's already installed, there's no need to do anything.\r
+       if (installed)\r
+       {\r
+         DEBUGSTR( 1, L"Already installed" );\r
+       }\r
+       else if (GetParentProcessInfo( &pi, arg ))\r
+       {\r
+         pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);\r
+         pi.hThread  = OpenThread( THREAD_ALL_ACCESS,  FALSE, pi.dwThreadId );\r
+         SuspendThread( pi.hThread );\r
+#ifdef _WIN64\r
+         // Find the base address of kernel32.dll if the 64-bit version is\r
+         // injecting into a 32-bit parent.\r
+         if (IsWow64Process( pi.hProcess, &gui ) && gui)\r
+         {\r
+           HANDLE hSnap;\r
+           MODULEENTRY32 me;\r
+           BOOL fOk;\r
+\r
+           hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE |\r
+                                             TH32CS_SNAPMODULE32,\r
+                                             pi.dwProcessId );\r
+           if (hSnap != INVALID_HANDLE_VALUE)\r
+           {\r
+             me.dwSize = sizeof(MODULEENTRY32);\r
+             for (fOk = Module32First( hSnap, &me ); fOk;\r
+                  fOk = Module32Next( hSnap, &me ))\r
+             {\r
+               if (_wcsicmp( me.szModule, L"kernel32.dll" ) == 0)\r
+               {\r
+                 base = me.modBaseAddr;\r
+                 break;\r
+               }\r
+             }\r
+             CloseHandle( hSnap );\r
+           }\r
+         }\r
+#endif\r
+         if (!Inject( &pi, &gui, arg ))\r
+           rc = 1;\r
+         ResumeThread( pi.hThread );\r
+         CloseHandle( pi.hThread );\r
+         CloseHandle( pi.hProcess );\r
+       }\r
+       else\r
+       {\r
+         fputws( L"ANSICON: could not obtain the parent process.\n", stderr );\r
+         rc = 1;\r
+       }\r
+       break;\r
+\r
+      case 'm':\r
+      {\r
+       int a = wcstol( arg + 2, NULL, 16 );\r
+       if (a == 0)\r
+         a = (arg[2] == '-') ? -7 : 7;\r
+       if (a < 0)\r
+       {\r
+         SetEnvironmentVariable( L"ANSICON_REVERSE", L"1" );\r
+         a = -a;\r
+         a = ((a >> 4) & 15) | ((a & 15) << 4);\r
+       }\r
+       SetConsoleTextAttribute( hConOut, (WORD)a );\r
+       SetEnvironmentVariable( L"ANSICON_DEF", NULL );\r
+       break;\r
+      }\r
+\r
+      case 'e':\r
+      case 'E':\r
+      case 't':\r
+      case 'T':\r
+       run = FALSE;\r
+       ++arg;\r
+       goto arg_out;\r
+    }\r
+    get_arg( arg, &argv, &cmd );\r
+  }\r
+arg_out:\r
+  if (run && *cmd == '\0')\r
+  {\r
+    if (!shell)\r
+      run = FALSE;\r
+    else if (!_isatty( 0 ))\r
+    {\r
+      *arg = 't';\r
+      run = FALSE;\r
+    }\r
+  }\r
+\r
+  if (run)\r
+  {\r
+    if (*cmd == '\0')\r
+    {\r
+      if (GetEnvironmentVariable( L"ComSpec", arg, MAX_PATH ))\r
+       cmd = arg;\r
+      else\r
+      {\r
+       // CreateProcessW writes to the string, so can't simply point to "cmd".\r
+       static TCHAR cmdstr[] = L"cmd";\r
+       cmd = cmdstr;\r
+      }\r
+    }\r
+\r
+    ZeroMemory( &si, sizeof(si) );\r
+    si.cb = sizeof(si);\r
+    if (CreateProcess( NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED,\r
+                      NULL, NULL, &si, &pi ))\r
+    {\r
+      Inject( &pi, &gui, arg );\r
+      ResumeThread( pi.hThread );\r
+      if (!gui)\r
+      {\r
+       SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );\r
+       WaitForSingleObject( pi.hProcess, INFINITE );\r
+       GetExitCodeProcess( pi.hProcess, (LPDWORD)(LPVOID)&rc );\r
+      }\r
+      CloseHandle( pi.hProcess );\r
+      CloseHandle( pi.hThread );\r
+    }\r
+    else\r
+    {\r
+      print_error( arg, arg );\r
+      rc = 1;\r
+    }\r
+  }\r
+  else if (*arg)\r
+  {\r
+    ansi = LoadLibrary( ANSIDLL );\r
+    if (ansi == NULL)\r
+    {\r
+      print_error( ANSIDLL );\r
+      rc = 1;\r
+    }\r
+\r
+    if (*arg == 'e' || *arg == 'E')\r
+    {\r
+      cmd += 2;\r
+      if (*cmd == ' ' || *cmd == '\t')\r
+       ++cmd;\r
+      fputws( cmd, stdout );\r
+      if (*arg == 'e')\r
+       putwchar( '\n' );\r
+    }\r
+    else // (*arg == 't' || *arg == 'T')\r
+    {\r
+      BOOL title = (*arg == 'T');\r
+      get_file( arg, &argv, &cmd );\r
+      if (*arg == '\0')\r
+       wcscpy( arg, L"-" );\r
+      do\r
+      {\r
+       if (title)\r
+       {\r
+         wprintf( L"==> %s <==\n", arg );\r
+         display( arg, title );\r
+         putwchar( '\n' );\r
+       }\r
+       else\r
+         display( arg, title );\r
+       get_file( arg, &argv, &cmd );\r
+      } while (*arg);\r
+    }\r
+\r
+    FreeLibrary( ansi );\r
+  }\r
+\r
+  if (run || *arg)\r
+    set_original_attr();\r
+  else\r
+    CloseHandle( hConOut );\r
+\r
+  return rc;\r
+}\r
+\r
+\r
+// Display a file.\r
+void display( LPCTSTR name, BOOL title )\r
+{\r
+  HANDLE in, out;\r
+  BOOL  pipe;\r
+  char  buf[8192];\r
+  DWORD  len;\r
+\r
+  if (*name == '-' && name[1] == '\0')\r
+  {\r
+    pipe = TRUE;\r
+    in = GetStdHandle( STD_INPUT_HANDLE );\r
+  }\r
+  else\r
+  {\r
+    pipe = FALSE;\r
+    in = CreateFile( name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+                    NULL, OPEN_EXISTING, 0, NULL );\r
+    if (in == INVALID_HANDLE_VALUE)\r
+    {\r
+      print_error( name );\r
+      return;\r
+    }\r
+  }\r
+  if (title)\r
+  {\r
+    putwchar( '\n' );\r
+    // Need to flush, otherwise it's written *after* STD_OUTPUT_HANDLE should\r
+    // it be redirected.\r
+    fflush( stdout );\r
+  }\r
+  out = GetStdHandle( STD_OUTPUT_HANDLE );\r
+  for (;;)\r
+  {\r
+    if (!ReadFile( in, buf, sizeof(buf), &len, NULL ))\r
+    {\r
+      if (GetLastError() != ERROR_BROKEN_PIPE)\r
+       print_error( name );\r
+      break;\r
+    }\r
+    if (len == 0)\r
+      break;\r
+    WriteFile( out, buf, len, &len, NULL );\r
+  }\r
+  if (!pipe)\r
+    CloseHandle( in );\r
+}\r
+\r
+\r
+void print_error( LPCTSTR name, ... )\r
+{\r
+  LPTSTR errmsg = NULL;\r
+  DWORD err = GetLastError();\r
+  va_list arg;\r
+\r
+  if (err == ERROR_BAD_EXE_FORMAT)\r
+  {\r
+    // This error requires an argument, which is a duplicate of name.\r
+    va_start( arg, name );\r
+    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,\r
+                  NULL, err, 0, (LPTSTR)(LPVOID)&errmsg, 0, &arg );\r
+    va_end( arg );\r
+    fwprintf( stderr, L"ANSICON: %s", errmsg );\r
+  }\r
+  else\r
+  {\r
+    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,\r
+                  NULL, err, 0, (LPTSTR)(LPVOID)&errmsg, 0, NULL );\r
+    // Just in case there are other messages requiring args...\r
+    if (errmsg == NULL)\r
+      fwprintf( stderr, L"ANSICON: %s: Error %lu.\n", name, err );\r
+    else\r
+      fwprintf( stderr, L"ANSICON: %s: %s", name, errmsg );\r
+  }\r
+  LocalFree( errmsg );\r
+}\r
+\r
+\r
+// Add or remove ANSICON to AutoRun.\r
+void process_autorun( TCHAR cmd )\r
+{\r
+  HKEY  cmdkey;\r
+  TCHAR  ansicon[MAX_PATH+80];\r
+  TCHAR  logstr[80];\r
+  LPTSTR autorun, ansirun;\r
+  DWORD  len, type, exist;\r
+  BOOL  inst;\r
+\r
+  if (log_level)\r
+    _snwprintf( logstr, lenof(logstr), L"set ANSICON_LOG=%d&", log_level );\r
+  else\r
+    *logstr = '\0';\r
+  len = TSIZE(_snwprintf( ansicon, lenof(ansicon),\r
+               L"(if %%ANSICON_VER%%==^%%ANSICON_VER^%% %s\"%s\" -p)",\r
+               logstr, prog_path ) + 1);\r
+\r
+  inst = (towlower( cmd ) == 'i');\r
+  if (RegCreateKeyEx( (iswlower(cmd)) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,\r
+                     CMDKEY, 0, NULL,\r
+                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,\r
+                     &cmdkey, &exist ) != ERROR_SUCCESS)\r
+  {\r
+    fputws( L"ANSICON: could not update AutoRun", stderr );\r
+    if (iswupper( cmd ))\r
+      fwprintf( stderr, L" (perhaps use -%c, or run as admin)", towlower(cmd) );\r
+    fputws( L".\n", stderr );\r
+  }\r
+  exist = 0;\r
+  RegQueryValueEx( cmdkey, AUTORUN, NULL, NULL, NULL, &exist );\r
+  if (exist == 0)\r
+  {\r
+    if (inst)\r
+      RegSetValueEx( cmdkey, AUTORUN, 0, REG_SZ, (PBYTE)ansicon, len );\r
+  }\r
+  else\r
+  {\r
+    // Let's assume there's sufficient memory.\r
+    autorun = malloc( exist + len );\r
+    RegQueryValueEx( cmdkey, AUTORUN, NULL, &type, (PBYTE)autorun, &exist );\r
+    // Remove the existing command, if present.\r
+    ansirun = wcsstr( autorun, L"(if %ANSICON_VER%" );\r
+    if (ansirun != NULL)\r
+    {\r
+      LPTSTR tmp = wcschr( ansirun, '"' );      // opening quote\r
+      tmp = wcschr( tmp + 1, '"' );             // closing quote\r
+      tmp = wcschr( tmp + 1, ')' );             // closing bracket\r
+      if (*++tmp == '&')\r
+       ++tmp;\r
+      if (*tmp == '&')\r
+       ++tmp;\r
+      if (*tmp == '\0')\r
+      {\r
+       if (ansirun > autorun && ansirun[-1] == '&')\r
+         --ansirun;\r
+       if (ansirun > autorun && ansirun[-1] == '&')\r
+         --ansirun;\r
+      }\r
+      wcscpy( ansirun, tmp );\r
+      exist = TSIZE((DWORD)wcslen( autorun ) + 1);\r
+    }\r
+    if (inst)\r
+    {\r
+      if (exist == sizeof(TCHAR))\r
+       RegSetValueEx( cmdkey, AUTORUN, 0, REG_SZ, (PBYTE)ansicon, len );\r
+      else\r
+      {\r
+       memmove( (PBYTE)autorun + len, autorun, exist );\r
+       memcpy( autorun, ansicon, len );\r
+       ((PBYTE)autorun)[len-sizeof(TCHAR)] = '&';\r
+       RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun, exist+len );\r
+      }\r
+    }\r
+    else\r
+    {\r
+      if (exist == sizeof(TCHAR))\r
+       RegDeleteValue( cmdkey, AUTORUN );\r
+      else\r
+       RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun, exist );\r
+    }\r
+    free( autorun );\r
+  }\r
+  RegCloseKey( cmdkey );\r
+}\r
+\r
+\r
+// Search each process in the snapshot for id.\r
+BOOL find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe )\r
+{\r
+  BOOL fOk;\r
+\r
+  ppe->dwSize = sizeof(PROCESSENTRY32);\r
+  for (fOk = Process32First( snap, ppe ); fOk; fOk = Process32Next( snap, ppe ))\r
+    if (ppe->th32ProcessID == id)\r
+      break;\r
+\r
+  return fOk;\r
+}\r
+\r
+\r
+// Obtain the process and thread identifiers of the parent process.\r
+BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR name )\r
+{\r
+  HANDLE hSnap;\r
+  PROCESSENTRY32 pe;\r
+  THREADENTRY32  te;\r
+  BOOL  fOk;\r
+\r
+  hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD, 0 );\r
+\r
+  if (hSnap == INVALID_HANDLE_VALUE)\r
+    return FALSE;\r
+\r
+  find_proc_id( hSnap, GetCurrentProcessId(), &pe );\r
+  if (!find_proc_id( hSnap, pe.th32ParentProcessID, &pe ))\r
+  {\r
+    CloseHandle( hSnap );\r
+    return FALSE;\r
+  }\r
+\r
+  te.dwSize = sizeof(te);\r
+  for (fOk = Thread32First( hSnap, &te ); fOk; fOk = Thread32Next( hSnap, &te ))\r
+    if (te.th32OwnerProcessID == pe.th32ProcessID)\r
+      break;\r
+\r
+  CloseHandle( hSnap );\r
+\r
+  ppi->dwProcessId = pe.th32ProcessID;\r
+  ppi->dwThreadId  = te.th32ThreadID;\r
+  wcscpy( name, pe.szExeFile );\r
+\r
+  return fOk;\r
+}\r
+\r
+\r
+// Return the first non-space character from arg.\r
+LPTSTR skip_spaces( LPTSTR arg )\r
+{\r
+  while (*arg == ' ' || *arg == '\t')\r
+    ++arg;\r
+\r
+  return arg;\r
+}\r
+\r
+\r
+// Retrieve an argument from the command line. cmd gets the existing argv; argv\r
+// is ready for the next argument.\r
+void get_arg( LPTSTR arg, LPTSTR* argv, LPTSTR* cmd )\r
+{\r
+  LPTSTR line;\r
+\r
+  line = *cmd = skip_spaces( *argv );\r
+  while (*line != '\0')\r
+  {\r
+    if (*line == ' ' || *line == '\t')\r
+    {\r
+      ++line;\r
+      break;\r
+    }\r
+    if (*line == '"')\r
+    {\r
+      while (*++line != '\0')\r
+      {\r
+       if (*line == '"')\r
+       {\r
+         ++line;\r
+         break;\r
+       }\r
+       *arg++ = *line;\r
+      }\r
+    }\r
+    else\r
+      *arg++ = *line++;\r
+  }\r
+  *arg = '\0';\r
+  *argv = line;\r
+}\r
+\r
+\r
+int glob_sort( const void* a, const void* b )\r
+{\r
+  return lstrcmpi( *(LPCTSTR*)a, *(LPCTSTR*)b );\r
+}\r
+\r
+\r
+// As get_arg, but expand wildcards.\r
+void get_file( LPTSTR arg, LPTSTR* argv, LPTSTR* cmd )\r
+{\r
+  HANDLE  fh, in;\r
+  WIN32_FIND_DATA fd;\r
+  LPTSTR  path;\r
+  int    size;\r
+  char   buf[1024];\r
+  static LPTSTR  name;\r
+  static LPTSTR* glob;\r
+  static int    globbed;\r
+\r
+  if (globbed != 0)\r
+  {\r
+    if (glob[globbed] == NULL)\r
+    {\r
+      free( glob );\r
+      globbed = 0;\r
+    }\r
+    else\r
+    {\r
+      wcscpy( name, glob[globbed++] );\r
+      return;\r
+    }\r
+  }\r
+\r
+  get_arg( arg, argv, cmd );\r
+  if (wcspbrk( arg, L"*?" ) != NULL)\r
+  {\r
+    fh = FindFirstFile( arg, &fd );\r
+    if (fh != INVALID_HANDLE_VALUE)\r
+    {\r
+      size = 0;\r
+      do\r
+      {\r
+       if (! (fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |\r
+                                     FILE_ATTRIBUTE_HIDDEN)))\r
+       {\r
+         ++globbed;\r
+         size += (int)wcslen( fd.cFileName ) + 1;\r
+       }\r
+      } while (FindNextFile( fh, &fd ));\r
+      FindClose( fh );\r
+\r
+      if (globbed != 0)\r
+      {\r
+       for (path = name = arg; *path != '\0'; ++path)\r
+         if (*path == '\\' || *path == '/')\r
+           name = path + 1;\r
+       glob = malloc( (globbed + 1) * sizeof(LPTSTR) + TSIZE(size) );\r
+       path = (LPTSTR)(glob + globbed + 1);\r
+       globbed = 0;\r
+       fh = FindFirstFile( arg, &fd );\r
+       do\r
+       {\r
+         if (! (fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |\r
+                                       FILE_ATTRIBUTE_HIDDEN)))\r
+         {\r
+           // Ignore apparent binary files.\r
+           wcscpy( name, fd.cFileName );\r
+           in = CreateFile( arg, GENERIC_READ,\r
+                            FILE_SHARE_READ|FILE_SHARE_WRITE,\r
+                            NULL, OPEN_EXISTING, 0, NULL );\r
+           if (in != INVALID_HANDLE_VALUE)\r
+           {\r
+             ReadFile( in, buf, sizeof(buf), (LPVOID)&size, NULL );\r
+             CloseHandle( in );\r
+             if (memchr( buf, 0, size ) != NULL)\r
+               continue;\r
+           }\r
+           size = (int)wcslen( fd.cFileName ) + 1;\r
+           memcpy( path, fd.cFileName, TSIZE(size) );\r
+           glob[globbed++] = path;\r
+           path += size;\r
+         }\r
+       } while (FindNextFile( fh, &fd ));\r
+       FindClose( fh );\r
+       glob[globbed] = NULL;\r
+\r
+       qsort( glob, globbed, sizeof(LPTSTR), glob_sort );\r
+\r
+       wcscpy( name, glob[0] );\r
+       globbed = 1;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+void help( void )\r
+{\r
+  _putws(\r
+L"ANSICON by Jason Hood <jadoxa@yahoo.com.au>.\n"\r
+L"Version " PVERS L" (" PDATE L").  Freeware.\n"\r
+L"http://ansicon.adoxa.vze.com/\n"\r
+L"\n"\r
+#ifdef _WIN64\r
+L"Process ANSI escape sequences in Windows console programs.\n"\r
+#else\r
+L"Process ANSI escape sequences in Win32 console programs.\n"\r
+#endif\r
+L"\n"\r
+L"ansicon [-l<level>] [-i] [-I] [-u] [-U] [-m[<attr>]] [-p]\n"\r
+L"        [-e|E string | -t|T [file(s)] | program [args]]\n"\r
+L"\n"\r
+L"  -l\t\tset the logging level (1=process, 2=module, 3=function,\n"\r
+L"    \t\t +4=output, +8=append) for program (-p is unaffected)\n"\r
+L"  -i\t\tinstall - add ANSICON to the AutoRun entry (also implies -p)\n"\r
+L"  -u\t\tuninstall - remove ANSICON from the AutoRun entry\n"\r
+L"  -I -U\t\tuse local machine instead of current user\n"\r
+L"  -m\t\tuse grey on black (\"monochrome\") or <attr> as default color\n"\r
+L"  -p\t\thook into the parent process\n"\r
+L"  -e\t\techo string\n"\r
+L"  -E\t\techo string, don't append newline\n"\r
+L"  -t\t\tdisplay files (\"-\" for stdin), combined as a single stream\n"\r
+L"  -T\t\tdisplay files, name first, blank line before and after\n"\r
+L"  program\trun the specified program\n"\r
+L"  nothing\trun a new command processor, or display stdin if redirected\n"\r
+L"\n"\r
+L"<attr> is one or two hexadecimal digits; please use \"COLOR /?\" for details.\n"\r
+L"It may start with '-' to reverse foreground and background (but not for -p)."\r
+       );\r
+}\r
old mode 100755 (executable)
new mode 100644 (file)
index 8819186..f5cc47a
@@ -1,47 +1,51 @@
-/*
-  ansicon.h - Header file for common definitions.
-
-  Jason Hood, 12 December, 2010 (originally injdll.h, 20 June, 2009).
-*/
-
-#ifndef ANSICON_H
-#define ANSICON_H
-
-#ifndef UNICODE
-# define UNICODE
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#define _WIN32_WINNT 0x0500    // MinGW wants this defined for OpenThread
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define lenof(array) (sizeof(array)/sizeof(*(array)))
-#define TSIZE(size)  ((size) * sizeof(TCHAR))
-
-
-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
-} GRM, *PGRM;          // Graphic Rendition Mode
-
-
-int  ProcessType( LPPROCESS_INFORMATION, BOOL* );
-void InjectDLL32( LPPROCESS_INFORMATION, LPCTSTR );
-void InjectDLL64( LPPROCESS_INFORMATION, LPCTSTR );
-
-extern TCHAR  prog_path[MAX_PATH];
-extern LPTSTR prog;
-LPTSTR get_program_name( LPTSTR );
-
-extern int log_level;
-void DEBUGSTR( int level, LPTSTR szFormat, ... );
-
-#endif
+/*\r
+  ansicon.h - Header file for common definitions.\r
+\r
+  Jason Hood, 12 December, 2010 (originally injdll.h, 20 June, 2009).\r
+*/\r
+\r
+#ifndef ANSICON_H\r
+#define ANSICON_H\r
+\r
+#ifndef UNICODE\r
+# define UNICODE\r
+#endif\r
+\r
+#define WIN32_LEAN_AND_MEAN\r
+#ifdef _WIN64\r
+#define _WIN32_WINNT 0x0600    // MinGW-w64 wants this defined for Wow64 stuff\r
+#else\r
+#define _WIN32_WINNT 0x0500    // MinGW wants this defined for OpenThread\r
+#endif\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#define lenof(array) (sizeof(array)/sizeof(*(array)))\r
+#define TSIZE(size)  ((size) * sizeof(TCHAR))\r
+\r
+\r
+typedef struct\r
+{\r
+  BYTE foreground;     // ANSI base color (0 to 7; add 30)\r
+  BYTE background;     // ANSI base color (0 to 7; add 40)\r
+  BYTE bold;           // console FOREGROUND_INTENSITY bit\r
+  BYTE underline;      // console BACKGROUND_INTENSITY bit\r
+  BYTE rvideo;         // swap foreground/bold & background/underline\r
+  BYTE concealed;      // set foreground/bold to background/underline\r
+  BYTE reverse;        // swap console foreground & background attributes\r
+} GRM, *PGRM;          // Graphic Rendition Mode\r
+\r
+\r
+int  ProcessType( LPPROCESS_INFORMATION, BOOL* );\r
+void InjectDLL32( LPPROCESS_INFORMATION, LPCTSTR );\r
+void InjectDLL64( LPPROCESS_INFORMATION, LPCTSTR );\r
+\r
+extern TCHAR  prog_path[MAX_PATH];\r
+extern LPTSTR prog;\r
+LPTSTR get_program_name( LPTSTR );\r
+\r
+extern int log_level;\r
+void DEBUGSTR( int level, LPTSTR szFormat, ... );\r
+\r
+#endif\r
old mode 100755 (executable)
new mode 100644 (file)
index 09b03c1..908044f
@@ -1,36 +1,54 @@
-/*
-  ansicon.rc - Version resource for ansicon.exe.
-
-  Jason Hood, 11 November, 2009.
-*/
-
-#include <winver.h>
-#include "version.h"
-
-1 VERSIONINFO
-FILEVERSION    PVERB
-PRODUCTVERSION PVERB
-FILEOS         VOS_NT
-FILETYPE       VFT_APP
-{
-  BLOCK "StringFileInfo"
-  {
-    BLOCK "040904B0"
-    {
-      VALUE "Comments",         "http://ansicon.adoxa.cjb.net/"
-      VALUE "CompanyName",      "Jason Hood"
-      VALUE "FileDescription",  "ANSI Console"
-      VALUE "FileVersion",      PVERSA
-      VALUE "InternalName",     "ansicon"
-      VALUE "LegalCopyright",   "Freeware"
-      VALUE "OriginalFilename", "ansicon.exe"
-      VALUE "ProductName",      "ANSICON"
-      VALUE "ProductVersion",   PVERSA
-    }
-  }
-
-  BLOCK "VarFileInfo"
-  {
-    VALUE "Translation", 0x0409, 0x04B0
-  }
-}
+/*\r
+  ansicon.rc - Version resource for ansicon.exe.\r
+\r
+  Jason Hood, 11 November, 2009.\r
+*/\r
+\r
+#include <winver.h>\r
+#include "version.h"\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+FILEVERSION    PVERB\r
+PRODUCTVERSION PVERB\r
+FILEOS         VOS_NT\r
+FILETYPE       VFT_APP\r
+{\r
+  BLOCK "StringFileInfo"\r
+  {\r
+    BLOCK "040904B0"\r
+    {\r
+      VALUE "Comments",         "http://ansicon.adoxa.vze.com/"\r
+      VALUE "CompanyName",      "Jason Hood"\r
+      VALUE "FileDescription",  "ANSI Console"\r
+      VALUE "FileVersion",      PVERSA\r
+      VALUE "InternalName",     "ansicon"\r
+      VALUE "LegalCopyright",   "Freeware"\r
+      VALUE "OriginalFilename", "ansicon.exe"\r
+      VALUE "ProductName",      "ANSICON"\r
+      VALUE "ProductVersion",   PVERSA\r
+    }\r
+  }\r
+\r
+  BLOCK "VarFileInfo"\r
+  {\r
+    VALUE "Translation", 0x0409, 0x04B0\r
+  }\r
+}\r
+\r
+// Add a manifest for the 32-bit version, to prevent registry redirection when\r
+// trying to use HKLM.\r
+#ifndef _WIN64\r
+1 24\r
+{\r
+"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>\\r
+<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">\\r
+<trustInfo xmlns=""urn:schemas-microsoft-com:asm.v3"">\\r
+  <security>\\r
+    <requestedPrivileges>\\r
+      <requestedExecutionLevel level=""asInvoker"" uiAccess=""false"" />\\r
+    </requestedPrivileges>\\r
+  </security>\\r
+</trustInfo>\\r
+</assembly>"\r
+}\r
+#endif\r
old mode 100755 (executable)
new mode 100644 (file)
index 25ed7ae..1a299de
-/*
-  Inject code into the target process to load our DLL. The target thread
-  should be suspended on entry; it remains suspended on exit.
-
-  Initially I used the "stack" method of injection.  However, this fails
-  when DEP is active, since that doesn't allow code to execute in the stack.
-  To overcome this I used the "CreateRemoteThread" method.  However, this
-  would fail with Wselect, a program to assist batch files.  Wselect runs,
-  but it has no output.  As it turns out, removing the suspended flag would
-  make Wselect work, but it caused problems with everything else.  So now I
-  allocate a section of memory and change the context to run from there.  At
-  first I had an event to signal when the library was loaded, then the memory
-  was released.  However, that wouldn't work with -p and CMD.EXE (4NT v8
-  worked fine).  Since it's possible the DLL might start a process suspended,
-  I've decided to simply keep the memory.
-*/
-
-#include "ansicon.h"
-
-#ifdef _WIN64
-#if defined(__MINGW64__) || (defined(_MSC_VER) && _MSC_VER <= 1400)
-#include "wow64.h"
-
-TWow64GetThreadContext Wow64GetThreadContext;
-TWow64SetThreadContext Wow64SetThreadContext;
-#endif
-
-#define CONTEXT         WOW64_CONTEXT
-#undef CONTEXT_CONTROL
-#define CONTEXT_CONTROL  WOW64_CONTEXT_CONTROL
-#define GetThreadContext Wow64GetThreadContext
-#define SetThreadContext Wow64SetThreadContext
-#endif
-
-
-DWORD LLW;
-
-
-void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
-{
-  CONTEXT context;
-  DWORD   len;
-  LPVOID  mem;
-  DWORD   mem32;
-  #define CODESIZE 20
-  BYTE   code[CODESIZE+TSIZE(MAX_PATH)];
-  union
-  {
-    PBYTE  pB;
-    PDWORD pL;
-  } ip;
-
-  len = TSIZE(lstrlen( dll ) + 1);
-  if (len > TSIZE(MAX_PATH))
-    return;
-
-  if (LLW == 0)
-  {
-    HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
-#ifdef _WIN64
-#ifdef __MINGW64__
-    #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
-    GETPROC( Wow64GetThreadContext );
-    GETPROC( Wow64SetThreadContext );
-    // Assume if one is defined, so is the other.
-    if (Wow64GetThreadContext == 0)
-    {
-      DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext.\n" );
-      return;
-    }
-#endif
-
-    STARTUPINFO si;
-    PROCESS_INFORMATION pi;
-    ZeroMemory( &si, sizeof(si) );
-    si.cb = sizeof(si);
-    // ...ANSI32.dll\0
-    CopyMemory( code, dll, len - TSIZE(7) );
-    // ...ANSI-LLW.exe\0
-    CopyMemory( code + len - TSIZE(7), L"-LLW.exe", TSIZE(9) );
-    if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
-                       &si, &pi ))
-    {
-      DEBUGSTR( 1, L"Failed to execute \"%s\".\n", (LPCTSTR)code );
-      return;
-    }
-    WaitForSingleObject( pi.hProcess, INFINITE );
-    GetExitCodeProcess( pi.hProcess, &LLW );
-    CloseHandle( pi.hProcess );
-    CloseHandle( pi.hThread );
-#else
-    LLW = (DWORD)GetProcAddress( hKernel, "LoadLibraryW" );
-#endif
-  }
-
-  CopyMemory( code + CODESIZE, dll, len );
-  len += CODESIZE;
-
-  context.ContextFlags = CONTEXT_CONTROL;
-  GetThreadContext( ppi->hThread, &context );
-  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
-                       PAGE_EXECUTE_READWRITE );
-  mem32 = (DWORD)(DWORD_PTR)mem;
-
-  ip.pB = code;
-
-  *ip.pB++ = 0x68;                     // push  eip
-  *ip.pL++ = context.Eip;
-  *ip.pB++ = 0x9c;                     // pushf
-  *ip.pB++ = 0x60;                     // pusha
-  *ip.pB++ = 0x68;                     // push  L"path\to\ANSI32.dll"
-  *ip.pL++ = mem32 + CODESIZE;
-  *ip.pB++ = 0xe8;                     // call  LoadLibraryW
-  *ip.pL++ = LLW - (mem32 + (DWORD)(ip.pB+4 - code));
-  *ip.pB++ = 0x61;                     // popa
-  *ip.pB++ = 0x9d;                     // popf
-  *ip.pB++ = 0xc3;                     // ret
-
-  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
-  FlushInstructionCache( ppi->hProcess, mem, len );
-  context.Eip = mem32;
-  SetThreadContext( ppi->hThread, &context );
-}
+/*\r
+  Inject code into the target process to load our DLL. The target thread\r
+  should be suspended on entry; it remains suspended on exit.\r
+\r
+  Initially I used the "stack" method of injection.  However, this fails\r
+  when DEP is active, since that doesn't allow code to execute in the stack.\r
+  To overcome this I used the "CreateRemoteThread" method.  However, this\r
+  would fail with Wselect, a program to assist batch files.  Wselect runs,\r
+  but it has no output.  As it turns out, removing the suspended flag would\r
+  make Wselect work, but it caused problems with everything else.  So now I\r
+  allocate a section of memory and change the context to run from there.  At\r
+  first I had an event to signal when the library was loaded, then the memory\r
+  was released.  However, that wouldn't work with -p and CMD.EXE (4NT v8\r
+  worked fine).  Since it's possible the DLL might start a process suspended,\r
+  I've decided to simply keep the memory.\r
+*/\r
+\r
+#include "ansicon.h"\r
+\r
+#ifdef _WIN64\r
+#ifndef WOW64_CONTEXT_ALL\r
+#include "wow64.h"\r
+\r
+TWow64GetThreadContext Wow64GetThreadContext;\r
+TWow64SetThreadContext Wow64SetThreadContext;\r
+#define IMPORT_WOW64\r
+#endif\r
+\r
+#define CONTEXT         WOW64_CONTEXT\r
+#undef CONTEXT_CONTROL\r
+#define CONTEXT_CONTROL  WOW64_CONTEXT_CONTROL\r
+#define GetThreadContext Wow64GetThreadContext\r
+#define SetThreadContext Wow64SetThreadContext\r
+\r
+#define MakeVA( cast, offset ) (cast)((DWORD_PTR)pDosHeader + (DWORD)(offset))\r
+\r
+extern DWORD LLW32;\r
+LPVOID base;\r
+static PIMAGE_DOS_HEADER pDosHeader;\r
+\r
+int export_cmp( const void* a, const void* b )\r
+{\r
+  return strcmp( (LPCSTR)a, MakeVA( LPCSTR, *(const PDWORD)b ) );\r
+}\r
+\r
+\r
+/*\r
+  Get the relative address of the 32-bit LoadLibraryW function from 64-bit code.\r
+  This was originally done via executing a helper program (ANSI-LLW.exe), but I\r
+  never liked doing that, so now I do it the "hard" way - load the 32-bit\r
+  kernel32.dll directly and search the exports.\r
+*/\r
+BOOL get_LLW32( void )\r
+{\r
+  HMODULE kernel32;\r
+  TCHAR   buf[MAX_PATH];\r
+  UINT   len;\r
+  PIMAGE_NT_HEADERS32    pNTHeader;\r
+  PIMAGE_EXPORT_DIRECTORY pExportDir;\r
+  PDWORD  fun_table, name_table;\r
+  PWORD   ord_table;\r
+  PDWORD  pLLW;\r
+\r
+  len = GetSystemWow64Directory( buf, MAX_PATH );\r
+  wcscpy( buf + len, L"\\kernel32.dll" );\r
+  // MinGW-w64 had a typo, calling it LINRARY.\r
+  kernel32 = LoadLibraryEx( buf, NULL, 0x20/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/ );\r
+  if (kernel32 == NULL)\r
+  {\r
+    DEBUGSTR( 1, L"Unable to load 32-bit kernel32.dll!" );\r
+    return FALSE;\r
+  }\r
+  // The handle uses low bits as flags, so strip 'em off.\r
+  pDosHeader = (PIMAGE_DOS_HEADER)((DWORD_PTR)kernel32 & ~0xFFFF);\r
+  pNTHeader  = MakeVA( PIMAGE_NT_HEADERS32, pDosHeader->e_lfanew );\r
+  pExportDir = MakeVA( PIMAGE_EXPORT_DIRECTORY,\r
+                      pNTHeader->OptionalHeader.\r
+                       DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].\r
+                        VirtualAddress );\r
+\r
+  fun_table  = MakeVA( PDWORD, pExportDir->AddressOfFunctions );\r
+  name_table = MakeVA( PDWORD, pExportDir->AddressOfNames );\r
+  ord_table  = MakeVA( PWORD,  pExportDir->AddressOfNameOrdinals );\r
+\r
+  pLLW = bsearch( "LoadLibraryW", name_table, pExportDir->NumberOfNames,\r
+                 sizeof(DWORD), export_cmp );\r
+  if (pLLW == NULL)\r
+  {\r
+    DEBUGSTR( 1, L"Could not find LoadLibraryW!" );\r
+    FreeLibrary( kernel32 );\r
+    return FALSE;\r
+  }\r
+  LLW32 = fun_table[ord_table[pLLW - name_table]];\r
+\r
+  FreeLibrary( kernel32 );\r
+  return TRUE;\r
+}\r
+#else\r
+DWORD LLW32;\r
+#endif\r
+\r
+\r
+void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )\r
+{\r
+  CONTEXT context;\r
+  DWORD   ep;\r
+  DWORD   len;\r
+  LPVOID  mem;\r
+  DWORD   mem32;\r
+  DWORD   pr;\r
+  #define CODESIZE 20\r
+  BYTE   code[CODESIZE+TSIZE(MAX_PATH)];\r
+  union\r
+  {\r
+    PBYTE  pB;\r
+    PDWORD pL;\r
+  } ip;\r
+#ifdef _WIN64\r
+  BOOL entry = FALSE;\r
+#endif\r
+\r
+#ifdef IMPORT_WOW64\r
+  if (Wow64GetThreadContext == 0)\r
+  {\r
+    #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )\r
+    HMODULE hKernel = GetModuleHandle( L"kernel32.dll" );\r
+    GETPROC( Wow64GetThreadContext );\r
+    GETPROC( Wow64SetThreadContext );\r
+    // Assume if one is defined, so is the other.\r
+    if (Wow64GetThreadContext == 0)\r
+    {\r
+      DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext." );\r
+      return;\r
+    }\r
+  }\r
+#endif\r
+\r
+  len = TSIZE(lstrlen( dll ) + 1);\r
+  if (len > TSIZE(MAX_PATH))\r
+    return;\r
+\r
+  CopyMemory( code + CODESIZE, dll, len );\r
+  len += CODESIZE;\r
+\r
+  context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;\r
+  GetThreadContext( ppi->hThread, &context );\r
+  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,\r
+                       PAGE_READWRITE );\r
+  mem32 = (DWORD)(DWORD_PTR)mem;\r
+\r
+  ip.pB = code;\r
+\r
+  ep = context.Eip;\r
+  if (LLW32 == 0)\r
+  {\r
+#ifndef _WIN64\r
+    LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),\r
+                                                    "LoadLibraryW" );\r
+#else\r
+    struct unicode_string\r
+    {\r
+      USHORT Length;\r
+      USHORT MaximumLength;\r
+      DWORD  Buffer;\r
+    };\r
+    struct ldr_module          // incomplete definition\r
+    {\r
+      DWORD next, prev;\r
+      DWORD baseAddress;\r
+      DWORD entryPoint;\r
+      DWORD sizeOfImage;\r
+      struct unicode_string fullDllName;\r
+      struct unicode_string baseDllName;\r
+    } ldr;\r
+    WCHAR basename[MAX_PATH];\r
+\r
+    if (!get_LLW32())\r
+      return;\r
+    // Determine the base address of the 32-bit kernel32.dll.  If injecting\r
+    // into the parent process, base has already been determined.  Otherwise,\r
+    // use the PEB to walk the loaded modules.\r
+    if (base == 0)\r
+    {\r
+      // When a process is created suspended, EAX has the entry point and EBX\r
+      // points to the PEB.\r
+      if (!ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),\r
+                             ip.pL, 4, NULL ))\r
+      {\r
+       DEBUGSTR( 1, L"Failed to read Ldr from PEB." );\r
+       return;\r
+      }\r
+      // In case we're a bit slow (which seems to be unlikely), set up an\r
+      // infinite loop as the entry point.\r
+      WriteProcessMemory( ppi->hProcess, mem, "\xEB\xFE", 2, NULL );\r
+      FlushInstructionCache( ppi->hProcess, mem, 2 );\r
+      ep = context.Eax;\r
+      context.Eax = mem32;\r
+      SetThreadContext( ppi->hThread, &context );\r
+      VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );\r
+      // Now resume the thread, as the PEB hasn't even been created yet.\r
+      ResumeThread( ppi->hThread );\r
+      while (*ip.pL == 0)\r
+      {\r
+       Sleep( 0 );\r
+       ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),\r
+                          ip.pL, 4, NULL );\r
+      }\r
+      // Read PEB_LDR_DATA.InInitializationOrderModuleList.Flink.\r
+      ReadProcessMemory( ppi->hProcess, UIntToPtr( *ip.pL + 0x1c ),\r
+                        &ip.pL[1], 4, NULL );\r
+      // Sometimes we're so quick ntdll.dll is the only one present, so keep\r
+      // looping until kernel32.dll shows up.\r
+      for (;;)\r
+      {\r
+       ldr.next = ip.pL[1];\r
+       do\r
+       {\r
+         ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.next ),\r
+                            &ldr, sizeof(ldr), NULL );\r
+         ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.baseDllName.Buffer ),\r
+                            basename, ldr.baseDllName.MaximumLength, NULL );\r
+         if (_wcsicmp( basename, L"kernel32.dll" ) == 0)\r
+         {\r
+           LLW32 += ldr.baseAddress;\r
+           goto gotit;\r
+         }\r
+       } while (ldr.next != *ip.pL + 0x1c);\r
+      }\r
+    gotit:\r
+      SuspendThread( ppi->hThread );\r
+      VirtualProtectEx( ppi->hProcess, mem, len, pr, &pr );\r
+      entry = TRUE;\r
+    }\r
+    else\r
+      LLW32 += PtrToUint( base );\r
+#endif\r
+  }\r
+\r
+  *ip.pB++ = 0x68;                     // push  ep\r
+  *ip.pL++ = ep;\r
+  *ip.pB++ = 0x9c;                     // pushf\r
+  *ip.pB++ = 0x60;                     // pusha\r
+  *ip.pB++ = 0x68;                     // push  L"path\to\ANSI32.dll"\r
+  *ip.pL++ = mem32 + CODESIZE;\r
+  *ip.pB++ = 0xe8;                     // call  LoadLibraryW\r
+  *ip.pL++ = LLW32 - (mem32 + (DWORD)(ip.pB+4 - code));\r
+  *ip.pB++ = 0x61;                     // popa\r
+  *ip.pB++ = 0x9d;                     // popf\r
+  *ip.pB++ = 0xc3;                     // ret\r
+\r
+  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );\r
+  FlushInstructionCache( ppi->hProcess, mem, len );\r
+  VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );\r
+#ifdef _WIN64\r
+  if (entry)\r
+    return;\r
+#endif\r
+  context.Eip = mem32;\r
+  SetThreadContext( ppi->hThread, &context );\r
+}\r
old mode 100755 (executable)
new mode 100644 (file)
index c46bd46..9e1c65c
@@ -1,96 +1,96 @@
-/*
-  Inject code into the target process to load our DLL. The target thread
-  should be suspended on entry; it remains suspended on exit.
-
-  Initially I used the "stack" method of injection.  However, this fails
-  when DEP is active, since that doesn't allow code to execute in the stack.
-  To overcome this I used the "CreateRemoteThread" method.  However, this
-  would fail with Wselect, a program to assist batch files.  Wselect runs,
-  but it has no output.  As it turns out, removing the suspended flag would
-  make Wselect work, but it caused problems with everything else.  So now I
-  allocate a section of memory and change the context to run from there.  At
-  first I had an event to signal when the library was loaded, then the memory
-  was released.  However, that wouldn't work with -p and CMD.EXE (4NT v8
-  worked fine).  Since it's possible the DLL might start a process suspended,
-  I've decided to simply keep the memory.
-*/
-
-#include "ansicon.h"
-
-void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
-{
-  CONTEXT context;
-  DWORD   len;
-  LPVOID  mem;
-  DWORD64 LLW;
-  union
-  {
-    PBYTE    pB;
-    PDWORD64 pL;
-  } ip;
-  #define CODESIZE 92
-  static BYTE code[CODESIZE+TSIZE(MAX_PATH)] = {
-       0,0,0,0,0,0,0,0,           // original rip
-       0,0,0,0,0,0,0,0,           // LoadLibraryW
-       0x9C,                      // pushfq
-       0x50,                      // push  rax
-       0x51,                      // push  rcx
-       0x52,                      // push  rdx
-       0x53,                      // push  rbx
-       0x55,                      // push  rbp
-       0x56,                      // push  rsi
-       0x57,                      // push  rdi
-       0x41,0x50,                 // push  r8
-       0x41,0x51,                 // push  r9
-       0x41,0x52,                 // push  r10
-       0x41,0x53,                 // push  r11
-       0x41,0x54,                 // push  r12
-       0x41,0x55,                 // push  r13
-       0x41,0x56,                 // push  r14
-       0x41,0x57,                 // push  r15
-       0x48,0x83,0xEC,0x28,       // sub   rsp, 40
-       0x48,0x8D,0x0D,41,0,0,0,   // lea   ecx, L"path\to\ANSI64.dll"
-       0xFF,0x15,-49,-1,-1,-1,    // call  LoadLibraryW
-       0x48,0x83,0xC4,0x28,       // add   rsp, 40
-       0x41,0x5F,                 // pop   r15
-       0x41,0x5E,                 // pop   r14
-       0x41,0x5D,                 // pop   r13
-       0x41,0x5C,                 // pop   r12
-       0x41,0x5B,                 // pop   r11
-       0x41,0x5A,                 // pop   r10
-       0x41,0x59,                 // pop   r9
-       0x41,0x58,                 // pop   r8
-       0x5F,                      // pop   rdi
-       0x5E,                      // pop   rsi
-       0x5D,                      // pop   rbp
-       0x5B,                      // pop   rbx
-       0x5A,                      // pop   rdx
-       0x59,                      // pop   rcx
-       0x58,                      // pop   rax
-       0x9D,                      // popfq
-       0xFF,0x25,-91,-1,-1,-1,    // jmp   original Rip
-       0,                         // dword alignment for LLW, fwiw
-  };
-
-  len = TSIZE(lstrlen( dll ) + 1);
-  if (len > TSIZE(MAX_PATH))
-    return;
-  CopyMemory( code + CODESIZE, dll, len );
-  len += CODESIZE;
-
-  context.ContextFlags = CONTEXT_CONTROL;
-  GetThreadContext( ppi->hThread, &context );
-  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
-                       PAGE_EXECUTE_READWRITE );
-  LLW = (DWORD64)LoadLibraryW;
-
-  ip.pB = code;
-
-  *ip.pL++ = context.Rip;
-  *ip.pL++ = LLW;
-
-  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
-  FlushInstructionCache( ppi->hProcess, mem, len );
-  context.Rip = (DWORD64)mem + 16;
-  SetThreadContext( ppi->hThread, &context );
-}
+/*\r
+  Inject code into the target process to load our DLL. The target thread\r
+  should be suspended on entry; it remains suspended on exit.\r
+\r
+  Initially I used the "stack" method of injection.  However, this fails\r
+  when DEP is active, since that doesn't allow code to execute in the stack.\r
+  To overcome this I used the "CreateRemoteThread" method.  However, this\r
+  would fail with Wselect, a program to assist batch files.  Wselect runs,\r
+  but it has no output.  As it turns out, removing the suspended flag would\r
+  make Wselect work, but it caused problems with everything else.  So now I\r
+  allocate a section of memory and change the context to run from there.  At\r
+  first I had an event to signal when the library was loaded, then the memory\r
+  was released.  However, that wouldn't work with -p and CMD.EXE (4NT v8\r
+  worked fine).  Since it's possible the DLL might start a process suspended,\r
+  I've decided to simply keep the memory.\r
+*/\r
+\r
+#include "ansicon.h"\r
+\r
+void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCTSTR dll )\r
+{\r
+  CONTEXT context;\r
+  DWORD   len;\r
+  LPVOID  mem;\r
+  DWORD64 LLW;\r
+  union\r
+  {\r
+    PBYTE    pB;\r
+    PDWORD64 pL;\r
+  } ip;\r
+  #define CODESIZE 92\r
+  static BYTE code[CODESIZE+TSIZE(MAX_PATH)] = {\r
+       0,0,0,0,0,0,0,0,           // original rip\r
+       0,0,0,0,0,0,0,0,           // LoadLibraryW\r
+       0x9C,                      // pushfq\r
+       0x50,                      // push  rax\r
+       0x51,                      // push  rcx\r
+       0x52,                      // push  rdx\r
+       0x53,                      // push  rbx\r
+       0x55,                      // push  rbp\r
+       0x56,                      // push  rsi\r
+       0x57,                      // push  rdi\r
+       0x41,0x50,                 // push  r8\r
+       0x41,0x51,                 // push  r9\r
+       0x41,0x52,                 // push  r10\r
+       0x41,0x53,                 // push  r11\r
+       0x41,0x54,                 // push  r12\r
+       0x41,0x55,                 // push  r13\r
+       0x41,0x56,                 // push  r14\r
+       0x41,0x57,                 // push  r15\r
+       0x48,0x83,0xEC,0x28,       // sub   rsp, 40\r
+       0x48,0x8D,0x0D,41,0,0,0,   // lea   ecx, L"path\to\ANSI64.dll"\r
+       0xFF,0x15,-49,-1,-1,-1,    // call  LoadLibraryW\r
+       0x48,0x83,0xC4,0x28,       // add   rsp, 40\r
+       0x41,0x5F,                 // pop   r15\r
+       0x41,0x5E,                 // pop   r14\r
+       0x41,0x5D,                 // pop   r13\r
+       0x41,0x5C,                 // pop   r12\r
+       0x41,0x5B,                 // pop   r11\r
+       0x41,0x5A,                 // pop   r10\r
+       0x41,0x59,                 // pop   r9\r
+       0x41,0x58,                 // pop   r8\r
+       0x5F,                      // pop   rdi\r
+       0x5E,                      // pop   rsi\r
+       0x5D,                      // pop   rbp\r
+       0x5B,                      // pop   rbx\r
+       0x5A,                      // pop   rdx\r
+       0x59,                      // pop   rcx\r
+       0x58,                      // pop   rax\r
+       0x9D,                      // popfq\r
+       0xFF,0x25,-91,-1,-1,-1,    // jmp   original Rip\r
+       0,                         // dword alignment for LLW, fwiw\r
+  };\r
+\r
+  len = TSIZE(lstrlen( dll ) + 1);\r
+  if (len > TSIZE(MAX_PATH))\r
+    return;\r
+  CopyMemory( code + CODESIZE, dll, len );\r
+  len += CODESIZE;\r
+\r
+  context.ContextFlags = CONTEXT_CONTROL;\r
+  GetThreadContext( ppi->hThread, &context );\r
+  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,\r
+                       PAGE_EXECUTE_READWRITE );\r
+  LLW = (DWORD64)LoadLibraryW;\r
+\r
+  ip.pB = code;\r
+\r
+  *ip.pL++ = context.Rip;\r
+  *ip.pL++ = LLW;\r
+\r
+  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );\r
+  FlushInstructionCache( ppi->hProcess, mem, len );\r
+  context.Rip = (DWORD64)mem + 16;\r
+  SetThreadContext( ppi->hThread, &context );\r
+}\r
diff --git a/ansicon/makefile b/ansicon/makefile
deleted file mode 100755 (executable)
index 0007bee..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-# Makefile for ANSICON.
-# Jason Hood, 11 March, 2006.  Updated 20 June, 2009.
-
-# I've used TDM64 (gcc 4.6.1), building the 32-bit version in the x86 directory
-# and the 64-bit version in the x64 directory. MinGW32 (gcc 3.4.5) will also
-# build the 32-bit version.
-
-# 19 November, 2010:
-#   explicitly use 64-bit flags, in case the compiler isn't.
-#
-# 13 December, 2011:
-#   use CMD for file operations, not programs from fileutils.
-
-CC = gcc
-CFLAGS = -O2 -Wall
-
-X86OBJS = x86/proctype.o x86/injdll32.o x86/util.o
-X64OBJS = x64/proctype.o x64/injdll64.o x64/injdll32.o x64/util.o
-
-x86/%.o: %.c ansicon.h
-       $(CC) -m32 -c $(CFLAGS) $< -o $@
-
-x86/%v.o: %.rc version.h
-       windres -U _WIN64 -F pe-i386 $< $@
-
-x64/%.o: %.c ansicon.h
-       $(CC) -m64 -c $(CFLAGS) $< -o $@
-
-x64/%v.o: %.rc version.h
-       windres -F pe-x86-64 $< $@
-
-all: ansicon32 ansicon64
-
-ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll
-
-ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll x64/ANSI-LLW.exe
-
-x86:
-       cmd /c "mkdir x86"
-
-x86/ansicon.exe: x86/ansicon.o $(X86OBJS) x86/ansiconv.o
-       $(CC) -m32 $+ -s -o $@
-
-x86/ANSI32.dll: x86/ANSI.o $(X86OBJS) x86/ansiv.o
-       $(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared
-
-x64:
-       cmd /c "mkdir x64"
-
-x64/ansicon.exe: x64/ansicon.o $(X64OBJS) x64/ansiconv.o
-       $(CC) -m64 $+ -s -o $@
-
-x64/ANSI64.dll: x64/ANSI.o $(X64OBJS) x64/ansiv.o
-       $(CC) -m64 $+ -s -o $@ -mdll -Wl,-shared
-
-x64/ANSI32.dll: x64/ANSI32.o x64/proctype32.o x86/injdll32.o x86/util.o x86/ansiv.o
-       $(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared
-
-x64/ANSI-LLW.exe: ANSI-LLW.c
-       $(CC) -m32 $(CFLAGS) $< -s -o $@
-
-x86/ansicon.o: version.h
-x86/ANSI.o:    version.h
-x64/ansicon.o: version.h
-x64/ANSI.o:    version.h
-x86/util.o:    version.h
-x64/util.o:    version.h
-x86/ansiconv.o: ansicon.rc
-x86/ansiv.o:   ansi.rc
-x64/ansiconv.o: ansicon.rc
-x64/ansiv.o:   ansi.rc
-
-x64/ANSI32.o: ANSI.c
-       $(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@
-x64/proctype32.o: proctype.c
-       $(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@
-
-# Need two commands, because if the directory doesn't exist, it won't delete
-# anything at all.
-clean:
-       -cmd /c "del x86\*.o 2>nul"
-       -cmd /c "del x64\*.o 2>nul"
diff --git a/ansicon/makefile.gcc b/ansicon/makefile.gcc
new file mode 100644 (file)
index 0000000..75543ca
--- /dev/null
@@ -0,0 +1,112 @@
+# MinGW/MinGW-w64 makefile for ANSICON.\r
+# Jason Hood, 11 March, 2006.  Updated 20 June, 2009.\r
+#\r
+# 19 November, 2010:\r
+#   explicitly use 64-bit flags, in case the compiler isn't.\r
+#\r
+# 13 December, 2011:\r
+#   use CMD for file operations, not programs from fileutils.\r
+#\r
+# 23 November, 2012:\r
+#   set the base address of the DLLs to AC0000[00] (AnsiCon).\r
+#\r
+# 17 & 18 July, 2013:\r
+#   work with 32-bit only, 64-bit only or multilib compilers;\r
+#   hide the commands (use V=1 to show them).\r
+#\r
+# Tested with:\r
+# * MinGW/gcc 4.7.2;\r
+# * tdm-gcc-4.7.1-2;\r
+# * tdm64-gcc-4.7.1-3;\r
+# * MinGW-builds x64-4.8.1-release-posix-seh-rev1.\r
+\r
+CC = gcc\r
+CFLAGS = -O2 -Wall\r
+\r
+#ARCH = 32\r
+#ARCH = 64\r
+#ARCH = multi\r
+\r
+ifndef ARCH\r
+# Use the machine to distinguish between MinGW and MinGW-w64.\r
+ifeq (,$(findstring 64,$(shell gcc -dumpmachine)))\r
+ARCH = 32\r
+else\r
+# It's 64-bit, if it's multi the lib name will be different.\r
+ifeq ($(shell gcc -m32 -print-libgcc-file-name),$(shell gcc -m64 -print-libgcc-file-name))\r
+ARCH = 64\r
+else\r
+ARCH = multi\r
+endif\r
+endif\r
+endif\r
+\r
+X86OBJS = x86/proctype.o x86/injdll32.o x86/util.o\r
+X64OBJS = x64/proctype.o x64/injdll64.o x64/injdll32.o x64/util.o\r
+\r
+V ?= 0\r
+ifeq ($(V),0)\r
+CCmsg = @echo $<;\r
+RCmsg = $(CCmsg)\r
+LDmsg = @echo $@;\r
+endif\r
+\r
+x86/%.o: %.c ansicon.h\r
+       $(CCmsg)$(CC) -m32 -c $(CFLAGS) $< -o $@\r
+\r
+x86/%v.o: %.rc version.h\r
+       $(RCmsg)windres -U _WIN64 -F pe-i386 $< $@\r
+\r
+x64/%.o: %.c ansicon.h\r
+       $(CCmsg) $(CC) -m64 -c $(CFLAGS) $< -o $@\r
+\r
+x64/%v.o: %.rc version.h\r
+       $(RCmsg)windres -F pe-x86-64 $< $@\r
+\r
+x64/%32.o: %.c\r
+       $(CCmsg)$(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@\r
+\r
+\r
+ifeq ($(ARCH),multi)\r
+all: ansicon32 ansicon64\r
+else\r
+all: ansicon$(ARCH)\r
+endif\r
+\r
+ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll x64 x64/ANSI32.dll\r
+\r
+ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll\r
+\r
+x86:\r
+       cmd /c "mkdir x86"\r
+\r
+x86/ansicon.exe: x86/ansicon.o $(X86OBJS) x86/ansiconv.o\r
+       $(LDmsg)$(CC) -m32 $+ -s -o $@\r
+\r
+x86/ANSI32.dll: x86/ANSI.o $(X86OBJS) x86/ansiv.o\r
+       $(LDmsg)$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000\r
+\r
+x64:\r
+       cmd /c "mkdir x64"\r
+\r
+x64/ansicon.exe: x64/ansicon.o $(X64OBJS) x64/ansiconv.o\r
+       $(LDmsg)$(CC) -m64 $+ -s -o $@\r
+\r
+x64/ANSI64.dll: x64/ANSI.o $(X64OBJS) x64/ansiv.o\r
+       $(LDmsg)$(CC) -m64 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC000000\r
+\r
+x64/ANSI32.dll: x64/ANSI32.o x64/proctype32.o x86/injdll32.o x86/util.o x86/ansiv.o\r
+       $(LDmsg)$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000\r
+\r
+x86/ansicon.o: version.h\r
+x86/ANSI.o:    version.h\r
+x86/util.o:    version.h\r
+x64/ansicon.o: version.h\r
+x64/ANSI.o:    version.h\r
+x64/util.o:    version.h\r
+\r
+# Need two commands, because if the directory doesn't exist, it won't delete\r
+# anything at all.\r
+clean:\r
+       -cmd /c "del x86\*.o 2>nul"\r
+       -cmd /c "del x64\*.o 2>nul"\r
old mode 100755 (executable)
new mode 100644 (file)
index da71872..081982d
-# VC makefile for ANSICON.
-# Jason Hood, 15 November, 2010.
-
-# I've used Visual C++ 2008 Express for the 32-bit version and the 2003 R2
-# Platform SDK for the 64-bit version. Since these are entirely separate
-# environments, define BITS to decide which should be built.  Note that the
-# 64-bit version still requires the 32-bit ANSI32.dll, so both environments
-# are required and you should build the 32-bit version before the 64-bit.
-
-#BITS = 32
-#BITS = 64
-
-!IFNDEF BITS
-BITS = 32
-!ENDIF
-
-!IF $(BITS) == 32
-DIR = x86
-!ELSE
-!IF $(BITS) == 64
-DIR = x64
-!ELSE
-!ERROR BITS should be defined to 32 or 64.
-!ENDIF
-!ENDIF
-
-CC = cl
-CFLAGS = /nologo /W3 /Ox /GF /D_CRT_SECURE_NO_WARNINGS
-LIBS = advapi32.lib user32.lib
-
-# This is required for the 2003 Platform SDK, but not for Visual Studio 2010.
-#LIBS64 = bufferoverflowu.lib
-
-X86OBJS = x86\proctype.obj x86\injdll32.obj x86\util.obj
-X64OBJS = x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\util.obj
-
-{}.c{$(DIR)}.obj:
-       $(CC) /c $(CFLAGS) /Fo$@ $<
-
-{}.rc{$(DIR)}.res:
-       rc /fo$@ $<
-
-all: ansicon$(BITS)
-
-ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64\ANSI32.dll
-
-ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll x64\ANSI-LLW.exe
-
-x86:
-       mkdir x86
-
-x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res
-       $(CC) /nologo /Fe$@ $** $(LIBS)
-
-x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res
-       $(CC) /nologo /LD /Fe$@ $** $(LIBS)
-
-x64:
-       mkdir x64
-
-x64\ansicon.exe: x64\ansicon.obj $(X64OBJS) x64\ansicon.res
-       $(CC) /nologo /Fe$@ $** $(LIBS) $(LIBS64)
-
-x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res
-       $(CC) /nologo /LD /Fe$@ $** $(LIBS) $(LIBS64)
-
-x64\ANSI32.dll: x64\ANSI32.obj x64\proctype32.obj x86\injdll32.obj x86\util.obj x86\ansi.res
-       $(CC) /nologo /LD /Fe$@ $** $(LIBS)
-
-x64\ANSI-LLW.exe: ANSI-LLW.c
-       $(CC) $(CFLAGS) /Fe$@ /Fo$*.obj $? $(LIBS64)
-
-ansicon.c:  ansicon.h version.h
-ansicon.rc: version.h
-ANSI.c:     ansicon.h version.h
-ANSI.rc:    version.h
-util.c:     ansicon.h version.h
-injdll32.c: ansicon.h
-injdll64.c: ansicon.h
-proctype.c: ansicon.h
-
-x64\ANSI32.obj: ANSI.c
-       $(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?
-x64\proctype32.obj: proctype.c
-       $(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?
-
-clean:
-       -del $(DIR)\*.obj $(DIR)\*.res $(DIR)\*.lib $(DIR)\*.exp
+# VC makefile for ANSICON.\r
+# Jason Hood, 15 November, 2010.\r
+#\r
+# Tested with:\r
+# * Visual Studio 6.0 (VC6);\r
+# * Visual C++ 2003 Toolkit (VC7);\r
+# * Platform SDK for Windows Server 2003 R2 (VC8 64-bit);\r
+# * Visual Studio 2008 Express SP1 (VC9);\r
+# * Visual Studio 2010 Professional (VC10).\r
+#\r
+# Note that the 64-bit version still requires a 32-bit compiler.\r
+#\r
+# 22 & 23 November, 2012:\r
+#   determine if the PSDK is used automatically;\r
+#   use AC0000[00] (AnsiCon) as the base address;\r
+#   twiddle stuff around to support VC6 (with 2003 PSDK) for the 32-bit version;\r
+#   determine BITS automatically.\r
+#\r
+# 18 July, 2013:\r
+#   hide the commands (use V=1 to show them).\r
+\r
+#BITS = 32\r
+#BITS = 64\r
+\r
+!IFNDEF BITS\r
+!IF "$(CPU)" == "AMD64" || "$(PLATFORM)" == "x64"\r
+BITS = 64\r
+!ELSE\r
+BITS = 32\r
+!ENDIF\r
+!ENDIF\r
+\r
+!IF $(BITS) == 32\r
+DIR = x86\r
+!ELSE\r
+!IF $(BITS) == 64\r
+DIR = x64\r
+RFLAGS = /D_WIN64\r
+!ELSE\r
+!ERROR BITS should be defined to 32 or 64.\r
+!ENDIF\r
+!ENDIF\r
+\r
+# This is required for the 2003 Platform SDK, but not for Visual Studio 2010.\r
+!IF "$(_NMAKE_VER)" == "7.00.8882"\r
+!IF $(BITS) == 64\r
+LIBS64 = bufferoverflowu.lib\r
+# The 2003 Toolkit doesn't have MSVCRT.LIB, but VC98 does.\r
+!ELSEIF !DEFINED(SHARE) && !DEFINED(MSVCDIR)\r
+SHARE =\r
+!ENDIF\r
+!ENDIF\r
+\r
+# Link with MSVCRT.LIB by default.\r
+!IFNDEF SHARE\r
+SHARE = /MD\r
+!ENDIF\r
+\r
+# Manifest tool to embed the manifest required by 2008.\r
+MT = mt.exe\r
+\r
+CFLAGS = /nologo /W3 /O2 $(SHARE) /D_CRT_SECURE_NO_WARNINGS\r
+LIBS = advapi32.lib user32.lib $(LIBS64)\r
+\r
+X86OBJS = x86\proctype.obj x86\injdll32.obj x86\util.obj\r
+X64OBJS = x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\util.obj\r
+\r
+!IF !DEFINED(V)\r
+V = 0\r
+!ENDIF\r
+!IF $(V) == 0\r
+CCmsg = @\r
+RCmsg = @echo $<&\r
+LDmsg = @echo $@&\r
+MTmsg = @echo Embedding manifest&\r
+!ENDIF\r
+\r
+{}.c{$(DIR)}.obj:\r
+       $(CCmsg)$(CC) /c $(CFLAGS) /Fo$@ $<\r
+\r
+{}.rc{$(DIR)}.res:\r
+       $(RCmsg)$(RC) $(RFLAGS) /fo$@ $<\r
+\r
+all: ansicon$(BITS)\r
+\r
+ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64 x64\ANSI32.dll\r
+\r
+ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll\r
+\r
+x86:\r
+       mkdir x86\r
+\r
+x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res\r
+       $(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) /link /filealign:512\r
+!IF "$(_NMAKE_VER)" == "9.00.30729.01"\r
+       $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;1\r
+       @del $@.manifest\r
+!ENDIF\r
+\r
+x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res\r
+       $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512\r
+!IF "$(_NMAKE_VER)" == "9.00.30729.01"\r
+       $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2\r
+       @del $@.manifest\r
+!ENDIF\r
+\r
+x64:\r
+       mkdir x64\r
+\r
+x64\ansicon.exe: x64\ansicon.obj $(X64OBJS) x64\ansicon.res\r
+       $(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS)\r
+\r
+x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res\r
+       $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC000000 /section:.shared,s\r
+\r
+x64\ANSI32.dll: x64\ANSI32.obj x64\proctype32.obj x86\injdll32.obj x86\util.obj x86\ansi.res\r
+       $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512\r
+!IF "$(_NMAKE_VER)" == "9.00.30729.01"\r
+       $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2\r
+       @del $@.manifest\r
+!ENDIF\r
+\r
+ansicon.c:  ansicon.h version.h\r
+ansicon.rc: version.h\r
+ANSI.c:     ansicon.h version.h\r
+ANSI.rc:    version.h\r
+util.c:     ansicon.h version.h\r
+injdll32.c: ansicon.h\r
+injdll64.c: ansicon.h\r
+proctype.c: ansicon.h\r
+\r
+x64\ANSI32.obj: ANSI.c\r
+       $(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?\r
+x64\proctype32.obj: proctype.c\r
+       $(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?\r
+\r
+clean:\r
+       -del $(DIR)\*.obj $(DIR)\*.res $(DIR)\*.lib $(DIR)\*.exp\r
+!IF $(BITS) == 32\r
+       -del x64\ansi32.obj x64\proctype32.obj\r
+!ENDIF\r
old mode 100755 (executable)
new mode 100644 (file)
index 27399cd..d45fdbc
-/*
-  Test for a valid process.  This may sometimes detect GUI, even for a console
-  process.  I think this is due to a DLL being loaded in the address space
-  before the main image.  Ideally I could just use the base address directly,
-  but that doesn't seem easy to do for another process - there doesn't seem to
-  be a GetModuleHandle for another process.  The CreateRemoteThread trick won't
-  work with 64-bit (exit code is DWORD) and setting it up to make it work
-  hardly seems worth it.  There's GetModuleInformation, but passing in NULL just
-  returns a base of NULL, so that's no help.  Since 64/32 is sufficient, let
-  ansicon.exe handle the difference between console/GUI.
-
-  Update: ignore images characterised as DLL.
-*/
-
-#include "ansicon.h"
-
-
-int ProcessType( LPPROCESS_INFORMATION pinfo, BOOL* gui )
-{
-  char* ptr;
-  MEMORY_BASIC_INFORMATION minfo;
-  IMAGE_DOS_HEADER dos_header;
-  IMAGE_NT_HEADERS nt_header;
-  SIZE_T read;
-
-  *gui = FALSE;
-  for (ptr = NULL;
-       VirtualQueryEx( pinfo->hProcess, ptr, &minfo, sizeof(minfo) );
-       ptr += minfo.RegionSize)
-  {
-    if (minfo.BaseAddress == minfo.AllocationBase &&
-       ReadProcessMemory( pinfo->hProcess, minfo.AllocationBase,
-                          &dos_header, sizeof(dos_header), &read ))
-    {
-      if (dos_header.e_magic == IMAGE_DOS_SIGNATURE)
-      {
-       if (ReadProcessMemory( pinfo->hProcess, (char*)minfo.AllocationBase +
-                              dos_header.e_lfanew, &nt_header,
-                              sizeof(nt_header), &read ))
-       {
-         if (nt_header.Signature == IMAGE_NT_SIGNATURE &&
-             (nt_header.FileHeader.Characteristics &
-                        (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
-                        == IMAGE_FILE_EXECUTABLE_IMAGE)
-         {
-           *gui = (nt_header.OptionalHeader.Subsystem
-                             == IMAGE_SUBSYSTEM_WINDOWS_GUI);
-           if (nt_header.OptionalHeader.Subsystem ==
-               IMAGE_SUBSYSTEM_WINDOWS_CUI || *gui)
-           {
-             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
-             {
-               // Microsoft ignores precision on %p.
-               DEBUGSTR( 1, L"  32-bit %s (base = %.8X)",
-                         (*gui) ? L"GUI" : L"console",
-                         (DWORD)(DWORD_PTR)minfo.AllocationBase );
-               return 32;
-             }
-#ifdef _WIN64
-             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
-             {
-               DEBUGSTR( 1, L"  64-bit %s (base = %p)",
-                         (*gui) ? L"GUI" : L"console", minfo.AllocationBase );
-               return 64;
-             }
-#elif defined(W32ON64)
-             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
-             {
-               DEBUGSTR( 1, L"  64-bit %s",
-                         (*gui) ? L"GUI" : L"console" );
-               return 64;
-             }
-#endif
-             DEBUGSTR( 1, L"  Ignoring unsupported machine (0x%X)",
-                       nt_header.FileHeader.Machine );
-           }
-           else
-           {
-             DEBUGSTR( 1, L"  Ignoring unsupported subsystem (%u)",
-                       nt_header.OptionalHeader.Subsystem );
-           }
-           return 0;
-         }
-       }
-      }
-    }
-#ifdef _WIN32
-    // If a 32-bit process manages to load a 64-bit one, we may miss the base
-    // address.  If the pointer overflows, assume 64-bit and abort.
-    if (ptr > ptr + minfo.RegionSize)
-    {
-#ifdef W32ON64
-      DEBUGSTR( 1, L"  Pointer overflow: assuming 64-bit console" );
-      return 64;
-#else
-      DEBUGSTR( 1, L"  Ignoring apparent 64-bit process" );
-      return 0;
-#endif
-    }
-#endif
-  }
-
-  DEBUGSTR( 1, L"  Ignoring non-Windows process" );
-  return 0;
-}
+/*\r
+  Test for a valid process.  This may sometimes detect GUI, even for a console\r
+  process.  I think this is due to a DLL being loaded in the address space\r
+  before the main image.  Ideally I could just use the base address directly,\r
+  but that doesn't seem easy to do for another process - there doesn't seem to\r
+  be a GetModuleHandle for another process.  The CreateRemoteThread trick won't\r
+  work with 64-bit (exit code is DWORD) and setting it up to make it work\r
+  hardly seems worth it.  There's GetModuleInformation, but passing in NULL just\r
+  returns a base of NULL, so that's no help.  Since 64/32 is sufficient, let\r
+  ansicon.exe handle the difference between console/GUI.\r
+\r
+  Update: ignore images characterised as DLL.\r
+*/\r
+\r
+#include "ansicon.h"\r
+\r
+\r
+int ProcessType( LPPROCESS_INFORMATION pinfo, BOOL* gui )\r
+{\r
+  char* ptr;\r
+  MEMORY_BASIC_INFORMATION minfo;\r
+  IMAGE_DOS_HEADER dos_header;\r
+  IMAGE_NT_HEADERS nt_header;\r
+  SIZE_T read;\r
+\r
+  *gui = FALSE;\r
+  for (ptr = NULL;\r
+       VirtualQueryEx( pinfo->hProcess, ptr, &minfo, sizeof(minfo) );\r
+       ptr += minfo.RegionSize)\r
+  {\r
+    if (minfo.BaseAddress == minfo.AllocationBase &&\r
+       ReadProcessMemory( pinfo->hProcess, minfo.AllocationBase,\r
+                          &dos_header, sizeof(dos_header), &read ))\r
+    {\r
+      if (dos_header.e_magic == IMAGE_DOS_SIGNATURE)\r
+      {\r
+       if (ReadProcessMemory( pinfo->hProcess, (char*)minfo.AllocationBase +\r
+                              dos_header.e_lfanew, &nt_header,\r
+                              sizeof(nt_header), &read ))\r
+       {\r
+         if (nt_header.Signature == IMAGE_NT_SIGNATURE &&\r
+             (nt_header.FileHeader.Characteristics &\r
+                        (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))\r
+                        == IMAGE_FILE_EXECUTABLE_IMAGE)\r
+         {\r
+           *gui = (nt_header.OptionalHeader.Subsystem\r
+                             == IMAGE_SUBSYSTEM_WINDOWS_GUI);\r
+           if (nt_header.OptionalHeader.Subsystem ==\r
+               IMAGE_SUBSYSTEM_WINDOWS_CUI || *gui)\r
+           {\r
+             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)\r
+             {\r
+               // Microsoft ignores precision on %p.\r
+               DEBUGSTR( 1, L"  32-bit %s (base = %.8X)",\r
+                         (*gui) ? L"GUI" : L"console",\r
+                         (DWORD)(DWORD_PTR)minfo.AllocationBase );\r
+               return 32;\r
+             }\r
+#ifdef _WIN64\r
+             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)\r
+             {\r
+               DEBUGSTR( 1, L"  64-bit %s (base = %p)",\r
+                         (*gui) ? L"GUI" : L"console", minfo.AllocationBase );\r
+               return 64;\r
+             }\r
+#elif defined(W32ON64)\r
+             if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)\r
+             {\r
+               DEBUGSTR( 1, L"  64-bit %s",\r
+                         (*gui) ? L"GUI" : L"console" );\r
+               return 64;\r
+             }\r
+#endif\r
+             DEBUGSTR( 1, L"  Ignoring unsupported machine (0x%X)",\r
+                       nt_header.FileHeader.Machine );\r
+           }\r
+           else\r
+           {\r
+             DEBUGSTR( 1, L"  Ignoring unsupported subsystem (%u)",\r
+                       nt_header.OptionalHeader.Subsystem );\r
+           }\r
+           return 0;\r
+         }\r
+       }\r
+      }\r
+    }\r
+#ifndef _WIN64\r
+    // If a 32-bit process loads a 64-bit one, we may miss the base\r
+    // address.  If the pointer overflows, assume 64-bit.\r
+    if (((DWORD)ptr >> 12) + ((DWORD)minfo.RegionSize >> 12) > 0x80000)\r
+    {\r
+#ifdef W32ON64\r
+      DEBUGSTR( 1, L"  Pointer overflow: assuming 64-bit console" );\r
+      return 64;\r
+#else\r
+      DEBUGSTR( 1, L"  Ignoring apparent 64-bit process" );\r
+      return 0;\r
+#endif\r
+    }\r
+#endif\r
+  }\r
+\r
+  DEBUGSTR( 1, L"  Ignoring non-Windows process" );\r
+  return 0;\r
+}\r
old mode 100755 (executable)
new mode 100644 (file)
index 78f00eb..b092aa3
-
-                                   ANSICON
-
-                        Copyright 2005-2012 Jason Hood
-
-                           Version 1.53.  Freeware
-
-
-    ===========
-    Description
-    ===========
-
-    ANSICON provides ANSI escape sequences for Windows console programs.  It
-    provides much the same functionality as `ANSI.SYS' does for MS-DOS.
-
-
-    ============
-    Requirements
-    ============
-
-    Windows 2000 Professional and later (it won't work with NT or 9X).
-
-
-    ============
-    Installation
-    ============
-
-    Add x86 (if your OS is 32-bit) or x64 (if 64-bit) to your PATH, or copy
-    the relevant files to a directory already on the PATH.  Alternatively,
-    use option `-i' (or `-I') to install it permanently, by adding an entry
-    to CMD.EXE's AutoRun registry value (current user or local machine,
-    respectively).  Uninstall simply involves closing any programs that are
-    currently using it, running with `-u' (and/or `-U') to remove the Auto-
-    Run entry/ies, then removing the directory from PATH or deleting the
-    files.  No other changes are made.
-
-    ---------
-    Upgrading
-    ---------
-
-    Delete ANSI.dll, it has been replaced with ANSI32.dll.
-    Delete ANSI-LLA.dll, it has been replaced with ANSI-LLW.dll.
-    Uninstall a pre-1.50 version and reinstall with this version.
-
-
-    =====
-    Usage
-    =====
-
-    Options (case sensitive):
-
-       -l      Log to %temp%\ansicon.log.
-
-       -p      Enable the parent process (i.e. the command shell used to
-               run ANSICON) to recognise escapes.
-
-       -m      Set the current (and default) attribute to grey on black
-               ("monochrome"), or the attribute following the `m' (please
-               use `COLOR /?' for attribute values).
-
-       -e      Echo the command line - a space or tab after the `e' is
-               ignored, the remainder is displayed verbatim.
-
-       -E      As above, but no newline is added.
-
-       -t      Display ("type") each file (or standard input if none or the
-               name is "-") as though they are a single file.
-
-       -T      Display "==> FILE NAME <==", a blank line (or an error
-               message), the file and another blank line.
-
-    Running ANSICON with no arguments will start a new instance of the com-
-    mand processor (the program defined by the `ComSpec' environment var-
-    iable, typically `CMD.EXE'), or display standard input if it is redir-
-    ected.  Any argument will be treated as a program and its arguments.
-    
-    Eg: `ansicon -m30 -t file.ans' will display `file.ans' using black on
-    cyan as the default color.
-
-    The attribute may start with "-" to permanently reverse the foreground
-    and background colors (but not when using `-p').  Eg: `ansicon -m-f0 -t
-    file.log' will use reversed black on white as the default (i.e. white on
-    black, with foreground sequences changing the background).
-
-    If you experience trouble with certain programs, the log may help in
-    finding the cause; it  can be found at "%TEMP%\ansicon.log".  A number
-    should follow the `l':
-
-       0       No logging
-       1       Log process start and end
-       2       Above, plus log modules used by the process
-       3       Above, plus log functions that are hooked
-       4       Log console output (add to any of the above)
-       8       Append to the existing file (add to any of the above)
-       16      Log all imported modules (add to any of the above)
-
-    The log option will not work with `-p'; set the environment variable
-    ANSICON_LOG instead.  The variable is only read once when a new process
-    is started; changing it won't affect running processes.  If you identify
-    a module that causes problems (one known is "nvd3d9wrap.dll") add it to
-    the ANSICON_EXC environment variable (see ANSICON_API below, but the
-    extension is required).
-
-    Once installed, the ANSICON environment variable will be created.  This
-    variable is of the form "WxH (wxh)", where W & H are the width and
-    height of the buffer and w & h are the width and height of the window.
-    The variable is updated whenever a program reads it directly (i.e. as
-    an individual request, not as part of the entire environment block).
-    For example, "set an" will not update it, but "echo %ansicon%" will.
-    Also created is ANSICON_VER, which contains the version without the
-    point (1.50 becomes "150").  This variable does not exist as part of the
-    environment block ("set an" will not show it).
-
-    If installed, GUI programs will not be hooked.  Either start the program
-    directly with `ansicon', or add it to the ANSICON_GUI variable (see
-    ANSICON_API below).
-
-    Using `ansicon' after install will always start with the default attrib-
-    utes, restoring the originals on exit; all other programs will use the
-    current attributes.  The shift state is always reset for a new process.
-
-    The Windows API WriteFile and WriteConsoleA functions will set the num-
-    ber of characters written, not the number of bytes.  When using a multi-
-    byte character set, this results in a smaller number (since multiple
-    bytes are used to represent a single character).  Some programs recog-
-    nise this as a reduced write and will inadvertently repeat previous
-    characters.  If you discover such a program, use the ANSICON_API envir-
-    onment variable to record it and override the API, returning the origin-
-    al byte count.  Ruby is an example of such a program (at least, up till
-    1.9.2p0), so use "set ANSICON_API=ruby" to avoid the repitition.  The
-    full syntax of the variable is:
-
-       ANSICON_API=[!]program;program;program...
-
-    PROGRAM is the name of the program, with no path and extension.  The
-    leading exclamation inverts the usage, meaning the API will always be
-    overridden, unless the program is in the list.  The variable can be made
-    permanent by going to System Properties, selecting the Advanced tab and
-    clicking Environment Variables (using XP; Vista/7 may be different).
-
-
-    ====================
-    Sequences Recognised
-    ====================
-
-    The following escape sequences are recognised.
-
-       \e]0;titleBEL           Set (xterm) window's title (and icon)
-       \e[21t                  Report (xterm) window's title
-       \e[s                    Save Cursor
-       \e[u                    Restore Cursor
-       \e[#G           CHA     Cursor Character Absolute
-       \e[#E           CNL     Cursor Next Line
-       \e[#F           CPL     Cursor Preceding Line
-       \e[#D           CUB     Cursor Left
-       \e[#B           CUD     Cursor Down
-       \e[#C           CUF     Cursor Right
-       \e[#;#H         CUP     Cursor Position
-       \e[#A           CUU     Cursor Up
-       \e[#P           DCH     Delete Character
-       \e[?25h         DECTCEM DEC Text Cursor Enable Mode (show cursor)
-       \e[?25l         DECTCEM DEC Text Cursor Enable Mode (hide cursor)
-       \e[#M           DL      Delete Line
-       \e[#n           DSR     Device Status Report
-       \e[#X           ECH     Erase Character
-       \e[#J           ED      Erase In Page
-       \e[#K           EL      Erase In Line
-       \e[#`           HPA     Character Position Absolute
-       \e[#j           HPB     Character Position Backward
-       \e[#a           HPR     Character Position Forward
-       \e[#;#f         HVP     Character And Line Position
-       \e[#@           ICH     Insert Character
-       \e[#L           IL      Insert Line
-       SI              LS0     Locking-shift Zero (see below)
-       SO              LS1     Locking-shift One
-       \e[#;#;#m       SGR     Select Graphic Rendition
-       \e[#d           VPA     Line Position Absolute
-       \e[#k           VPB     Line Position Backward
-       \e[#e           VPR     Line Position Forward
-
-    `\e' represents the escape character (ASCII 27); `#' represents a
-    decimal number (optional, in most cases defaulting to 1); BEL, SO and
-    SI are ASCII 7, 14 and 15. Regarding SGR: bold will set the foreground
-    intensity; underline and blink will set the background intensity;
-    conceal uses background as foreground.
-
-    I make a distinction between "\e[m" and "\e[0;...m".  Both will restore
-    the original foreground/background colors (and so "0" should be the
-    first parameter); the former will also restore the original bold and
-    underline attributes, whilst the latter will explicitly reset them.  The
-    environment variable ANSICON_DEF can be used to change the default col-
-    ors (same value as `-m'; setting the variable does not change the cur-
-    rent colors).
-
-
-    =================
-    Sequences Ignored
-    =================
-
-    The following escape sequences are explicitly ignored.
-
-       \e(?            Designate G0 character set (`?' is anything).
-       \e)?            Designate G1 character set (`?' is anything).
-       \e[?...         Private sequence
-       \e[>...         Private sequence
-
-    The G0 character set is always ASCII; the G1 character set is always
-    the DEC Special Graphics Character Set.
-
-
-    ==================================
-    DEC Special Graphics Character Set
-    ==================================
-
-    This is my interpretation of the set, as shown by
-    http://vt100.net/docs/vt220-rm/table2-4.html.
-
-
-       Char    Unicode Code Point & Name
-       ----    -------------------------
-       _       U+0020  Space (blank)
-       `       U+2666  Black Diamond Suit
-       a       U+2592  Medium Shade
-       b       U+2409  Symbol For Horizontal Tabulation
-       c       U+240C  Symbol For Form Feed
-       d       U+240D  Symbol For Carriage Return
-       e       U+240A  Symbol For Line Feed
-       f       U+00B0  Degree Sign
-       g       U+00B1  Plus-Minus Sign
-       h       U+2424  Symbol For Newline
-       i       U+240B  Symbol For Vertical Tabulation
-       j       U+2518  Box Drawings Light Up And Left
-       k       U+2510  Box Drawings Light Down And Left
-       l       U+250C  Box Drawings Light Down And Right
-       m       U+2514  Box Drawings Light Up And Right
-       n       U+253C  Box Drawings Light Vertical And Horizontal
-       o       U+00AF  Macron (SCAN 1)
-       p       U+25AC  Black Rectangle (SCAN 3)
-       q       U+2500  Box Drawings Light Horizontal (SCAN 5)
-       r       U+005F  Low Line (SCAN 7)
-       s       U+005F  Low Line (SCAN 9)
-       t       U+251C  Box Drawings Light Vertical And Right
-       u       U+2524  Box Drawings Light Vertical And Left
-       v       U+2534  Box Drawings Light Up And Horizontal
-       w       U+252C  Box Drawings Light Down And Horizontal
-       x       U+2502  Box Drawings Light Vertical
-       y       U+2264  Less-Than Or Equal To
-       z       U+2265  Greater-Than Or Equal To
-       {       U+03C0  Greek Small Letter Pi
-       |       U+2260  Not Equal To
-       }       U+00A3  Pound Sign
-       ~       U+00B7  Middle Dot
-
-
-    G1.txt is a Unicode file to view the glyphs "externally".  G1.bat is a
-    batch file (using `x86\ansicon') to show the glyphs in the console.  The
-    characters will appear as they should using Lucida (other than the Sym-
-    bols), but code page will influence them when using a raster font (but
-    of particular interest, 437 and 850 both show the Box Drawings).
-
-
-    ===========
-    Limitations
-    ===========
-
-    The entire console buffer is used, not just the visible window.
-
-    Building rubyinstaller on Win7 crashes (XP is fine).
-
-
-    ===============
-    Version History
-    ===============
-
-    Legend: + added, - bug-fixed, * changed.
-
-    1.53 - 12 June, 2012:
-    - fix for multiple simultaneous process creation (e.g. "cl /MP ...").
-
-    1.52 - 2 June, 2012:
-    + 32-bit processes can inject into 64-bit processes;
-    + implemented \e[39m & \e[49m (set default foreground/background color);
-    + added \e[#X, \e[#`, \e[#a, \e[#d, \e[#e, \[e#j and \e[#k;
-    * changed sequence descriptions to those in ECMA-48, ordered by acronym.
-
-    1.51 - 24 February, 2012:
-    - fixed installing into a piped/redirected CMD.EXE;
-    - fixed 32-bit process trying to identify a 64-bit process;
-    - ignore version within core API DLL names (now Win8 works);
-    + hook _lwrite & _hwrite (now Silverfrost FTN95 v6.20 works).
-
-    1.50 - 14 December, 2011:
-    - -u does not imply -p;
-    - return the program's exit code;
-    - -p by itself will not restore original color;
-    - output error messages to stderr;
-    * logging is always available, with various levels; include the pid;
-    * don't automatically hook GUI programs, use `ansicon' or ANSICON_GUI;
-    * always place first in AutoRun; don't run if already installed;
-    + global reverse video capability;
-    + added ANSICON_VER to provide version/install test;
-    + added ANSICON_EXC to exclude selected modules;
-    + added ANSICON_DEF to explicitly set the default SGM.
-
-    1.40 - 1 March, 2011:
-    - hook GetProcAddress (now PowerShell works);
-    + add SO/SI, using the DEC Special Graphics Character Set for G1;
-    + add DECTCEM to show/hide the cursor.
-
-    1.32 - 22 December, 2010:
-    - fixed crash due to NULL lpNumberOfBytesWritten/lpNumberOfCharsWritten;
-    - -p will test the parent process for validity;
-    * hook into GUI processes;
-    + recognise DSR and xterm window title sequences;
-    - fixed MinGW32 binaries (LLW was wrong).
-
-    1.31 - 19 November, 2010:
-    - fixed multibyte support (no extra junk with UTF-8 files);
-    * provide workaround for API byte/character differences;
-    * fixed potential problem if install path uses Unicode.
-
-    1.30 - 7 September, 2010:
-    + x64 version.
-
-    1.25 - 22 July, 2010:
-    - hook LoadLibraryEx (now CScript works);
-    - fixed -i when AutoRun existed, but was empty;
-    + support for Windows 7;
-    + -I (and -U) use HKEY_LOCAL_MACHINE.
-
-    1.24 - 7 January, 2010:
-    - fix -t and -e when ANSICON was already running;
-    + read standard input if redirected with no arguments, if -t has no
-      files, or if the name is "-" (which also serves as a workaround for
-      programs that don't get hooked, such as CScript).
-
-    1.23 - 11 November, 2009:
-    - restore hooked functions when unloading;
-    - reverse the "bold" and "underline" settings;
-    * conceal characters by making foreground color same as background.
-
-    1.22 - 5 October, 2009:
-    - hook LoadLibrary to inject into applications started via association.
-
-    1.21 - 23 September, 2009:
-    + -i (and -u) option to add (remove) entry to AutoRun value.
-
-    1.20 - 21 June, 2009:
-    * use another injection method;
-    + create ANSICON environment variable;
-    + -e (and -E) option to echo the command line (without newline);
-    + -t (and -T) option to type (display) files (with file name).
-
-    1.15 - 17 May, 2009:
-    - fix output corruption for long (over 8192 characters) ANSI strings.
-
-    1.14 - 3 April, 2009:
-    - fix the test for an empty import section (eg. XCOPY now works).
-
-    1.13 - 21 & 27 March, 2009:
-    * use a new injection method (to work with DEP);
-    * use Unicode.
-
-    1.12 - 9 March, 2009:
-    - fix processing child programs (generate a relocatable DLL).
-
-    1.11 - 28 February, 2009:
-    - fix processing child programs (only use for console executables).
-
-    1.10 - 22 February, 2009:
-    - fix output corruption (buffer overflow in MyConsoleWriteW);
-    - recognise current screen attributes as current ANSI atrributes;
-    - ignore Ctrl+C and Ctrl+Break;
-    + process child programs.
-
-    1.01 - 12 March, 2006:
-    * \e[m will restore original color, not set grey on black;
-    + -m option to set default (and initial) color;
-    - restore original color on exit;
-    - disable escape processing when console has disabled processed output;
-    + \e[5m (blink) is the same as \e[4m (underline);
-    - do not conceal control characters (0 to 31).
-
-    1.00 - 23 October, 2005:
-    + initial release.
-
-
-    ===============
-    Acknowledgments
-    ===============
-
-    Jean-Louis Morel, for his Perl package Win32::Console::ANSI.  It
-    provided the basis of `ANSI.dll'.
-
-    Sergey Oblomov (hoopoepg), for Console Manager.  It provided the basis
-    of `ansicon.exe'.
-
-    Anton Bassov's article "Process-wide API spying - an ultimate hack" in
-    "The Code Project".
-
-    Richard Quadling - his persistence in finding bugs has made ANSICON
-    what it is today.
-
-    Dmitry Menshikov, Marko Bozikovic and Philippe Villiers, for their
-    assistance in making the 64-bit version a reality.
-
-    Luis Lavena and the Ruby people for additional improvements.
-
-    Leigh Hebblethwaite for documentation tweaks.
-
-
-    =======
-    Contact
-    =======
-
-    mailto:jadoxa@yahoo.com.au
-    http://ansicon.adoxa.cjb.net/
-    https://github.com/adoxa/ansicon
-
-    Jason Hood
-    11 Buckle Street
-    North Rockhampton
-    Qld 4701
-    Australia
-
-
-    ============
-    Distribution
-    ============
-
-    The original zipfile can be freely distributed, by any means.  However,
-    I would like to be informed if it is placed on a CD-ROM (other than an
-    archive compilation; permission is granted, I'd just like to know).
-    Modified versions may be distributed, provided it is indicated as such
-    in the version text and a source diff is included.
-
-
-    ==========================
-    Jason Hood, 12 June, 2012.
+\r
+                                   ANSICON\r
+\r
+                        Copyright 2005-2013 Jason Hood\r
+\r
+                           Version 1.66.  Freeware\r
+\r
+\r
+Description\r
+===========\r
+\r
+    ANSICON provides ANSI escape sequences for Windows console programs.  It\r
+    provides much the same functionality as 'ANSI.SYS' does for MS-DOS.\r
+\r
+\r
+Requirements\r
+============\r
+\r
+    32-bit: Windows 2000 Professional and later (it won't work with NT or 9X).\r
+    64-bit: Vista and later (it won't work with XP64).\r
+\r
+\r
+Installation\r
+============\r
+\r
+    Add "x86" (if your OS is 32-bit) or "x64" (if 64-bit) to your PATH, or copy\r
+    the relevant files to a directory already on the PATH.  Alternatively, use\r
+    option '-i' (or '-I', if permitted) to install it permanently, by adding an\r
+    entry to CMD.EXE's AutoRun registry value (current user or local machine,\r
+    respectively).\r
+\r
+    Uninstall simply involves closing any programs that are currently using it;\r
+    running with '-u' (and/or '-U') to remove it from AutoRun; removing the\r
+    directory from PATH; and deleting the files.  No other changes are made\r
+    (although you may have also created environment variables).\r
+\r
+Upgrading\r
+---------\r
+\r
+    Delete ANSI.dll, it has been replaced with ANSI32.dll.\r
+    Delete ANSI-LLA.exe and ANSI-LLW.exe, they are no longer used.\r
+    Uninstall a pre-1.50 version and reinstall with this version.\r
+\r
+\r
+Usage\r
+=====\r
+\r
+    Options (case sensitive):\r
+\r
+       -l      Log to "%TEMP%\ansicon.log".\r
+\r
+       -p      Enable the parent process (i.e. the command shell used to run\r
+               ANSICON) to recognise escapes.\r
+\r
+       -m      Set the current (and default) attribute to grey on black\r
+               ("monochrome"), or the attribute following the 'm' (please\r
+               use 'COLOR /?' for attribute values).\r
+\r
+       -e      Echo the command line - a space or tab after the 'e' is\r
+               ignored, the remainder is displayed verbatim.\r
+\r
+       -E      As above, but no newline is added.\r
+\r
+       -t      Display ("type") each file (or standard input if none or the\r
+               name is "-") as though they are a single file.\r
+\r
+       -T      Display "==> FILE NAME <==", a blank line (or an error\r
+               message), the file and another blank line.\r
+\r
+    Running ANSICON with no arguments will start a new instance of the command\r
+    processor (the program defined by the 'ComSpec' environment variable, typ-\r
+    ically 'CMD.EXE'), or display standard input if it is redirected.  Any arg-\r
+    ument will be treated as a program and its arguments.\r
+    \r
+    E.g.: 'ansicon -m30 -t file.ans' will display "file.ans" using black on\r
+    cyan as the default color.\r
+\r
+    The attribute may start with '-' to permanently reverse the foreground and\r
+    background colors (but not when using '-p').  E.g.: 'ansicon -m-f0 -t\r
+    file.log' will use reversed black on white as the default (i.e. white on\r
+    black, with foreground sequences changing the background).\r
+\r
+    If you experience trouble with certain programs, the log may help in find-\r
+    ing the cause; it can be found at "%TEMP%\ansicon.log".  A number should\r
+    follow the 'l':\r
+\r
+       0       No logging\r
+       1       Log process start and end\r
+       2       Above, plus log modules used by the process\r
+       3       Above, plus log functions that are hooked\r
+       4       Log console output (add to any of the above)\r
+       8       Append to the existing file (add to any of the above)\r
+       16      Log all imported modules (add to any of the above)\r
+\r
+    The log option will not work with '-p'; set the environment variable\r
+    ANSICON_LOG instead.  The variable is only read once when a new process is\r
+    started; changing it won't affect running processes.  If you identify a\r
+    module that causes problems, add it to the ANSICON_EXC environment variable\r
+    (see ANSICON_API below, but the extension is required).\r
+\r
+    E.g.: 'ansicon -l5' will start a new command processor, logging every pro-\r
+    cess it starts along with their output.\r
+\r
+    Once installed, the ANSICON environment variable will be created.  This\r
+    variable is of the form "WxH (wxh)", where 'W' & 'H' are the width and\r
+    height of the buffer and 'w' & 'h' are the width and height of the window.\r
+    The variable is updated whenever a program reads it directly (i.e. as an\r
+    individual request, not as part of the entire environment block).  For\r
+    example, 'set an' will not update it, but 'echo %ansicon%' will.  Also\r
+    created is ANSICON_VER, which contains the version without the point (1.50\r
+    becomes "150").  This variable does not exist as part of the environment\r
+    block ('set an' will not show it).\r
+\r
+    If installed, GUI programs will not be hooked.  Either start the program\r
+    directly with 'ansicon', or add it to the ANSICON_GUI variable (see\r
+    ANSICON_API below).\r
+\r
+    Using 'ansicon' after install will always start with the default attrib-\r
+    utes, restoring the originals on exit; all other programs will use the cur-\r
+    rent attributes.  The shift state is always reset for a new process.\r
+\r
+    The Windows API WriteFile and WriteConsoleA functions will set the number\r
+    of characters written, not the number of bytes.  When using a multibyte\r
+    character set, this results in a smaller number (since multiple bytes are\r
+    used to represent a single character).  Some programs recognise this as a\r
+    reduced write and will inadvertently repeat previous characters.  If you\r
+    discover such a program, use the ANSICON_API environment variable to record\r
+    it and override the API, returning the original byte count.  Ruby (prior to\r
+    1.9.3) is an example of such a program, so use 'set ANSICON_API=ruby' to\r
+    avoid the repitition.  The full syntax is:\r
+\r
+       ANSICON_API=[!]program;program;program...\r
+\r
+    PROGRAM is the name of the program, with no path and extension.  The lead-\r
+    ing exclamation inverts the usage, meaning the API will always be over-\r
+    ridden, unless the program is in the list. The variable can be made perm-\r
+    anent by going to System Properties, selecting the Advanced tab (with Vista\r
+    onwards, this can be done by running "SystemPropertiesAdvanced") and click-\r
+    ing Environment Variables.\r
+\r
+\r
+Sequences Recognised\r
+====================\r
+\r
+    The following escape sequences are recognised.\r
+\r
+       \e]0;titleBEL           Set (xterm) window's title (and icon)\r
+       \e[21t                  Report (xterm) window's title\r
+       \e[s                    Save Cursor\r
+       \e[u                    Restore Cursor\r
+       \e[#G           CHA     Cursor Character Absolute\r
+       \e[#E           CNL     Cursor Next Line\r
+       \e[#F           CPL     Cursor Preceding Line\r
+       \e[#D           CUB     Cursor Left\r
+       \e[#B           CUD     Cursor Down\r
+       \e[#C           CUF     Cursor Right\r
+       \e[#;#H         CUP     Cursor Position\r
+       \e[#A           CUU     Cursor Up\r
+       \e[#P           DCH     Delete Character\r
+       \e[?25h         DECTCEM DEC Text Cursor Enable Mode (show cursor)\r
+       \e[?25l         DECTCEM DEC Text Cursor Enable Mode (hide cursor)\r
+       \e[#M           DL      Delete Line\r
+       \e[#n           DSR     Device Status Report\r
+       \e[#X           ECH     Erase Character\r
+       \e[#J           ED      Erase In Page\r
+       \e[#K           EL      Erase In Line\r
+       \e[#`           HPA     Character Position Absolute\r
+       \e[#j           HPB     Character Position Backward\r
+       \e[#a           HPR     Character Position Forward\r
+       \e[#;#f         HVP     Character And Line Position\r
+       \e[#@           ICH     Insert Character\r
+       \e[#L           IL      Insert Line\r
+       SI              LS0     Locking-shift Zero (see below)\r
+       SO              LS1     Locking-shift One\r
+       \e[#;#;#m       SGR     Select Graphic Rendition\r
+       \e[#d           VPA     Line Position Absolute\r
+       \e[#k           VPB     Line Position Backward\r
+       \e[#e           VPR     Line Position Forward\r
+\r
+    '\e' represents the escape character (ASCII 27); '#' represents a decimal\r
+    number (optional, in most cases defaulting to 1); BEL, SO and SI are ASCII\r
+    7, 14 and 15.  Regarding SGR: bold will set the foreground intensity; blink\r
+    and underline will set the background intensity; conceal uses background as\r
+    foreground.  See "sequences.txt" for a more complete description.\r
+\r
+    I make a distinction between '\e[m' and '\e[0;...m'.  Both will restore the\r
+    original foreground/background colors (and so '0' should be the first para-\r
+    meter); the former will also restore the original bold and underline attri-\r
+    butes, whilst the latter will explicitly reset them.  The environment var-\r
+    iable ANSICON_DEF can be used to change the default colors (same value as\r
+    '-m'; setting the variable does not change the current colors).\r
+\r
+\r
+Sequences Ignored\r
+=================\r
+\r
+    The following escape sequences are explicitly ignored.\r
+\r
+       \e(?            Designate G0 character set ('?' is any character).\r
+       \e)?            Designate G1 character set ('?' is any character).\r
+       \e[?...         Private sequence\r
+       \e[>...         Private sequence\r
+\r
+    The G0 character set is always ASCII; the G1 character set is always the\r
+    DEC Special Graphics Character Set.\r
+\r
+\r
+DEC Special Graphics Character Set\r
+==================================\r
+\r
+    This is my interpretation of the set, as shown by\r
+    http://vt100.net/docs/vt220-rm/table2-4.html.\r
+\r
+\r
+       Char    Unicode Code Point & Name\r
+       ----    -------------------------\r
+       _       U+0020  Space (blank)\r
+       `       U+2666  Black Diamond Suit\r
+       a       U+2592  Medium Shade\r
+       b       U+2409  Symbol For Horizontal Tabulation\r
+       c       U+240C  Symbol For Form Feed\r
+       d       U+240D  Symbol For Carriage Return\r
+       e       U+240A  Symbol For Line Feed\r
+       f       U+00B0  Degree Sign\r
+       g       U+00B1  Plus-Minus Sign\r
+       h       U+2424  Symbol For Newline\r
+       i       U+240B  Symbol For Vertical Tabulation\r
+       j       U+2518  Box Drawings Light Up And Left\r
+       k       U+2510  Box Drawings Light Down And Left\r
+       l       U+250C  Box Drawings Light Down And Right\r
+       m       U+2514  Box Drawings Light Up And Right\r
+       n       U+253C  Box Drawings Light Vertical And Horizontal\r
+       o       U+00AF  Macron (SCAN 1)\r
+       p       U+25AC  Black Rectangle (SCAN 3)\r
+       q       U+2500  Box Drawings Light Horizontal (SCAN 5)\r
+       r       U+005F  Low Line (SCAN 7)\r
+       s       U+005F  Low Line (SCAN 9)\r
+       t       U+251C  Box Drawings Light Vertical And Right\r
+       u       U+2524  Box Drawings Light Vertical And Left\r
+       v       U+2534  Box Drawings Light Up And Horizontal\r
+       w       U+252C  Box Drawings Light Down And Horizontal\r
+       x       U+2502  Box Drawings Light Vertical\r
+       y       U+2264  Less-Than Or Equal To\r
+       z       U+2265  Greater-Than Or Equal To\r
+       {       U+03C0  Greek Small Letter Pi\r
+       |       U+2260  Not Equal To\r
+       }       U+00A3  Pound Sign\r
+       ~       U+00B7  Middle Dot\r
+\r
+    G1.txt is a Unicode file to view the glyphs "externally".  G1.bat is a\r
+    batch file (using 'x86\ansicon') to show the glyphs in the console.  The\r
+    characters will appear as they should using Lucida (other than the Sym-\r
+    bols), but code page will influence them when using a raster font (but of\r
+    particular interest, 437 and 850 both show the Box Drawings).\r
+\r
+\r
+Limitations\r
+===========\r
+\r
+    The entire console buffer is used, not just the visible window.\r
+\r
+    There's a conflict with NVIDIA's drivers, requiring the setting of the\r
+    Environment Variable:\r
+\r
+       ANSICON_EXC=nvd3d9wrap.dll;nvd3d9wrapx.dll\r
+\r
+\r
+Version History\r
+===============\r
+\r
+    Legend: + added, - bug-fixed, * changed.\r
+\r
+    1.66 - 20 September, 2013:\r
+    - fix 32-bit process trying to detect 64-bit process.\r
+\r
+    1.65 - 4 September, 2013:\r
+    - fix finding 32-bit LoadLibraryW address from 64-bit;\r
+    - fix \e[K (was using window, not buffer).\r
+\r
+    1.64 - 2 August, 2013:\r
+    - improved detection of console output.\r
+\r
+    1.63 - 25 July, 2013:\r
+    - don't write the reset sequence (when it's already installed) if output is\r
+      redirected.\r
+\r
+    1.62 - 18 July, 2013:\r
+    - indicate if opening HKLM failed;\r
+    * removed ANSI-LLW.exe again, properly this time;\r
+    * add the architecture (32- or 64-bit) to the log.\r
+\r
+    1.61 - 14 February, 2013:\r
+    * revert back to using ANSI-LLW.exe, as the new method was unreliable.\r
+\r
+    1.60 - 24 November, 2012:\r
+    * new method to get the 32-bit LoadLibraryW address from 64-bit code.\r
+      This removes the need for ANSI-LLW.exe, which caused lots of virus\r
+      warnings, for some reason.\r
+    - set the code page to display some file names properly;\r
+    + expand wildcards for -t (ignoring directories and hidden/binary files).\r
+\r
+    1.53 - 12 June, 2012:\r
+    - fix for multiple simultaneous process creation (e.g. "cl /MP ...").\r
+\r
+    1.52 - 2 June, 2012:\r
+    + 32-bit processes can inject into 64-bit processes;\r
+    + implemented \e[39m & \e[49m (set default foreground/background color);\r
+    + added \e[#X, \e[#`, \e[#a, \e[#d, \e[#e, \[e#j and \e[#k;\r
+    * changed sequence descriptions to those in ECMA-48, ordered by acronym.\r
+\r
+    1.51 - 24 February, 2012:\r
+    - fixed installing into a piped/redirected CMD.EXE;\r
+    - fixed 32-bit process trying to identify a 64-bit process;\r
+    - ignore version within core API DLL names (now Win8 works);\r
+    + hook _lwrite & _hwrite (now Silverfrost FTN95 v6.20 works).\r
+\r
+    1.50 - 14 December, 2011:\r
+    - -u does not imply -p;\r
+    - return the program's exit code;\r
+    - -p by itself will not restore original color;\r
+    - output error messages to stderr;\r
+    * logging is always available, with various levels; include the pid;\r
+    * don't automatically hook GUI programs, use 'ansicon' or ANSICON_GUI;\r
+    * always place first in AutoRun; don't run if already installed;\r
+    + global reverse video capability;\r
+    + added ANSICON_VER to provide version/install test;\r
+    + added ANSICON_EXC to exclude selected modules;\r
+    + added ANSICON_DEF to explicitly set the default SGM.\r
+\r
+    1.40 - 1 March, 2011:\r
+    - hook GetProcAddress (now PowerShell works);\r
+    + add SO/SI, using the DEC Special Graphics Character Set for G1;\r
+    + add DECTCEM to show/hide the cursor.\r
+\r
+    1.32 - 22 December, 2010:\r
+    - fixed crash due to NULL lpNumberOfBytesWritten/lpNumberOfCharsWritten;\r
+    - -p will test the parent process for validity;\r
+    * hook into GUI processes;\r
+    + recognise DSR and xterm window title sequences;\r
+    - fixed MinGW32 binaries (LLW was wrong).\r
+\r
+    1.31 - 19 November, 2010:\r
+    - fixed multibyte support (no extra junk with UTF-8 files);\r
+    * provide workaround for API byte/character differences;\r
+    * fixed potential problem if install path uses Unicode.\r
+\r
+    1.30 - 7 September, 2010:\r
+    + x64 version.\r
+\r
+    1.25 - 22 July, 2010:\r
+    - hook LoadLibraryEx (now CScript works);\r
+    - fixed -i when AutoRun existed, but was empty;\r
+    + support for Windows 7;\r
+    + -I (and -U) use HKEY_LOCAL_MACHINE.\r
+\r
+    1.24 - 7 January, 2010:\r
+    - fix -t and -e when ANSICON was already running;\r
+    + read standard input if redirected with no arguments, if -t has no\r
+      files, or if the name is "-" (which also serves as a workaround for\r
+      programs that don't get hooked, such as CScript).\r
+\r
+    1.23 - 11 November, 2009:\r
+    - restore hooked functions when unloading;\r
+    - reverse the "bold" and "underline" settings;\r
+    * conceal characters by making foreground color same as background.\r
+\r
+    1.22 - 5 October, 2009:\r
+    - hook LoadLibrary to inject into applications started via association.\r
+\r
+    1.21 - 23 September, 2009:\r
+    + -i (and -u) option to add (remove) entry to AutoRun value.\r
+\r
+    1.20 - 21 June, 2009:\r
+    * use another injection method;\r
+    + create ANSICON environment variable;\r
+    + -e (and -E) option to echo the command line (without newline);\r
+    + -t (and -T) option to type (display) files (with file name).\r
+\r
+    1.15 - 17 May, 2009:\r
+    - fix output corruption for long (over 8192 characters) ANSI strings.\r
+\r
+    1.14 - 3 April, 2009:\r
+    - fix the test for an empty import section (eg. XCOPY now works).\r
+\r
+    1.13 - 21 & 27 March, 2009:\r
+    * use a new injection method (to work with DEP);\r
+    * use Unicode.\r
+\r
+    1.12 - 9 March, 2009:\r
+    - fix processing child programs (generate a relocatable DLL).\r
+\r
+    1.11 - 28 February, 2009:\r
+    - fix processing child programs (only use for console executables).\r
+\r
+    1.10 - 22 February, 2009:\r
+    - fix output corruption (buffer overflow in MyConsoleWriteW);\r
+    - recognise current screen attributes as current ANSI atrributes;\r
+    - ignore Ctrl+C and Ctrl+Break;\r
+    + process child programs.\r
+\r
+    1.01 - 12 March, 2006:\r
+    * \e[m will restore original color, not set grey on black;\r
+    + -m option to set default (and initial) color;\r
+    - restore original color on exit;\r
+    - disable escape processing when console has disabled processed output;\r
+    + \e[5m (blink) is the same as \e[4m (underline);\r
+    - do not conceal control characters (0 to 31).\r
+\r
+    1.00 - 23 October, 2005:\r
+    + initial release.\r
+\r
+\r
+Acknowledgments\r
+===============\r
+\r
+    Jean-Louis Morel, for his Perl package Win32::Console::ANSI.  It provided\r
+    the basis of 'ANSI.dll'.\r
+\r
+    Sergey Oblomov (hoopoepg), for Console Manager.  It provided the basis of\r
+    'ansicon.exe'.\r
+\r
+    Anton Bassov's article "Process-wide API spying - an ultimate hack" in "The\r
+    Code Project".\r
+\r
+    Richard Quadling - his persistence in finding bugs has made ANSICON what it\r
+    is today.\r
+\r
+    Dmitry Menshikov, Marko Bozikovic and Philippe Villiers, for their assis-\r
+    tance in making the 64-bit version a reality.\r
+\r
+    Luis Lavena and the Ruby people for additional improvements.\r
+\r
+    Leigh Hebblethwaite for documentation tweaks.\r
+\r
+    Vincent Fatica for pointing out \e[K was not right.\r
+\r
+\r
+Contact\r
+=======\r
+\r
+    mailto:jadoxa@yahoo.com.au\r
+    http://ansicon.adoxa.vze.com/\r
+    https://github.com/adoxa/ansicon\r
+\r
+    Jason Hood\r
+    11 Buckle Street\r
+    North Rockhampton\r
+    Qld 4701\r
+    Australia\r
+\r
+\r
+Distribution\r
+============\r
+\r
+    The original zipfile can be freely distributed, by any means.  However, I\r
+    would like to be informed if it is placed on a CD-ROM (other than an arch-\r
+    ive compilation; permission is granted, I'd just like to know).  Modified\r
+    versions may be distributed, provided it is indicated as such in the ver-\r
+    sion text and a source diff is made available.  In particular, the supplied\r
+    binaries are freely redistributable.  A formal license (zlib) is available\r
+    in LICENSE.txt.\r
+\r
+\r
+===============================\r
+Jason Hood, 20 September, 2013.\r
diff --git a/ansicon/sequences.txt b/ansicon/sequences.txt
new file mode 100644 (file)
index 0000000..c7de7e9
--- /dev/null
@@ -0,0 +1,118 @@
+\r
+                                   ANSICON\r
+                                 Version 1.60\r
+\r
+This is a complete list of the ANSI escape sequences recognised by ANSICON,\r
+roughly ordered by function.  The initial escape character is assumed.\r
+\r
+\r
+[m     restore default color (and intensity)\r
+[0m    as above\r
+[...m  set attributes (any of these numbers, separated by semicolons):\r
+                0      all attributes off\r
+                1      bold (foreground is intense)\r
+                4      underline (background is intense)\r
+                5      blink (background is intense)\r
+                7      reverse video\r
+                8      concealed (foreground becomes background)\r
+               22      bold off (foreground is not intense)\r
+               24      underline off (background is not intense)\r
+               25      blink off (background is not intense)\r
+               27      normal video\r
+               28      concealed off\r
+               30      foreground black\r
+               31      foreground red\r
+               32      foreground green\r
+               33      foreground yellow\r
+               34      foreground blue\r
+               35      foreground magenta\r
+               36      foreground cyan\r
+               37      foreground white\r
+               39      default foreground (using current intensity)\r
+               40      background black\r
+               41      background red\r
+               42      background green\r
+               43      background yellow\r
+               44      background blue\r
+               45      background magenta\r
+               46      background cyan\r
+               47      background white\r
+               49      default background (using current intensity)\r
+\r
+[J     erase from cursor to the end of display\r
+[0J    as above\r
+[1J    erase from the start of diplay to cursor (inclusive)\r
+[2J    erase display and move cursor to the top-left\r
+\r
+[K     erase from cursor to the end of line\r
+[0K    as above\r
+[1K    erase from the start of line to cursor (inclusive)\r
+[2K    erase line\r
+\r
+[X     erase one character\r
+[#X    erase # characters\r
+\r
+[L     insert one blank line\r
+[#L    insert # blank lines\r
+\r
+[M     delete one line\r
+[#M    delete # lines\r
+\r
+[P     delete one character\r
+[#P    delete # characters\r
+\r
+[@     insert one blank character\r
+[#@    insert # blank characters\r
+\r
+[A     move cursor up one line\r
+[#A    move cursor up # lines\r
+[B     move cursor down one line\r
+[#B    move cursor down # lines\r
+[C     move cursor right one character\r
+[#C    move cursor right # characters\r
+[D     move cursor left one character\r
+[#D    move cursor left # characters\r
+\r
+[k     move cursor up one line\r
+[#k    move cursor up # lines\r
+[e     move cursor down one line\r
+[#e    move cursor down # lines\r
+[a     move cursor right one character\r
+[#a    move cursor right # characters\r
+[j     move cursor left one character\r
+[#j    move cursor left # characters\r
+\r
+[E     move cursor down one line and to first column\r
+[#E    move cursor down # lines and to first column\r
+[F     move cursor up one line and to first column\r
+[#F    move cursor up # lines and to first column\r
+\r
+[G     move cursor to first column\r
+[#G    move cursor to column #\r
+\r
+[`     move cursor to first column\r
+[#`    move cursor to column #\r
+\r
+[d     move cursor to first line\r
+[#d    move cursor to line #\r
+\r
+[H     move cursor to top-left\r
+[#H    move cursor to line # and first column\r
+[#;#H  move cursor to line #, column #\r
+\r
+[f     move cursor to top-left\r
+[#f    move cursor to line # and first column\r
+[#;#f  move cursor to line #, column #\r
+\r
+[s     save cursor position\r
+[u     move cursor to saved position\r
+\r
+[?25h  show cursor\r
+[?25l  hide cursor\r
+\r
+[5n    sends "\e[0n" to console input (where \e is escape)\r
+[6n    sends "\e[#;#R" (line & column) to console input\r
+[21t   sends "\e]lTitle\e\" (the console's window title) to console input\r
+]0;TitleST\r
+       sets the console title to "Title"; ST (string terminator) is either\r
+        character 7 (BEL) or escape and backslash\r
old mode 100755 (executable)
new mode 100644 (file)
index 461b7b6..f1cf691
-/*
-  util.c - Utility functions.
-*/
-
-#include "ansicon.h"
-#include "version.h"
-
-
-TCHAR  prog_path[MAX_PATH];
-LPTSTR prog;
-int    log_level;
-char   tempfile[MAX_PATH];
-DWORD  pid;
-
-
-// Get just the name of the program: "C:\path\program.exe" -> "program".
-// Returns a pointer within program; it is modified to remove the extension.
-LPTSTR get_program_name( LPTSTR program )
-{
-  LPTSTR name, ext;
-
-  if (program == NULL)
-  {
-    GetModuleFileName( NULL, prog_path, lenof(prog_path) );
-    program = prog_path;
-  }
-  name = wcsrchr( program, '\\' );
-  if (name != NULL)
-    ++name;
-  else
-    name = program;
-  ext = wcsrchr( name, '.' );
-  if (ext != NULL && ext != name)
-    *ext = '\0';
-
-  return name;
-}
-
-
-void DEBUGSTR( int level, LPTSTR szFormat, ... )
-{
-  TCHAR szBuffer[1024], szEscape[1024];
-  va_list pArgList;
-  HANDLE mutex;
-  DWORD wait;
-  FILE* file;
-
-  if ((log_level & 3) < level && !(level & 4 & log_level))
-    return;
-
-  if (*tempfile == '\0')
-  {
-    _snprintf( tempfile, MAX_PATH, "%s\\ansicon.log", getenv( "TEMP" ) );
-    pid = GetCurrentProcessId();
-  }
-  if (szFormat == NULL)
-  {
-    file = fopen( tempfile, "wt" );
-    if (file != NULL)
-    {
-      SYSTEMTIME now;
-      GetLocalTime( &now );
-      fprintf( file, "ANSICON v" PVERSA " log (%d) started "
-                     "%d-%.2d-%.2d %d:%.2d:%.2d\n",
-                    log_level,
-                    now.wYear, now.wMonth, now.wDay,
-                    now.wHour, now.wMinute, now.wSecond );
-      fclose( file );
-    }
-    return;
-  }
-
-  va_start( pArgList, szFormat );
-  _vsnwprintf( szBuffer, lenof(szBuffer), szFormat, pArgList );
-  va_end( pArgList );
-
-  szFormat = szBuffer;
-  if (*szFormat == '\33')
-  {
-    BOOL first = TRUE;
-    LPTSTR pos = szEscape;
-    while (*++szFormat != '\0' && pos < szEscape + lenof(szEscape) - 4)
-    {
-      if (*szFormat < 32)
-      {
-       *pos++ = '\\';
-       switch (*szFormat)
-       {
-         case '\a': *pos++ = 'a'; break;
-         case '\b': *pos++ = 'b'; break;
-         case '\t': *pos++ = 't'; break;
-         case '\r': *pos++ = 'r'; break;
-         case '\n': *pos++ = 'n'; break;
-         case  27 : *pos++ = 'e'; break;
-         default:
-           pos += _snwprintf( pos, 32, L"%.*o",
-                            (szFormat[1] >= '0' && szFormat[1] <= '7') ? 3 : 1,
-                            *szFormat );
-       }
-      }
-      else
-      {
-       if (*szFormat == '"')
-       {
-         if (first)
-           first = FALSE;
-         else if (szFormat[1] != '\0')
-           *pos++ = '\\';
-       }
-       *pos++ = *szFormat;
-      }
-    }
-    *pos = '\0';
-    szFormat = szEscape;
-  }
-
-  mutex = CreateMutex( NULL, FALSE, L"ANSICON_debug_file" );
-  wait = WaitForSingleObject( mutex, 500 );
-  file = fopen( tempfile, "at" ); // _fmode might be binary
-  if (file != NULL)
-  {
-    fwprintf( file, L"%s (%lu): %s\n", prog, pid, szFormat );
-    fclose( file );
-  }
-  if (wait == WAIT_OBJECT_0)
-    ReleaseMutex( mutex );
-  CloseHandle( mutex );
-}
+/*\r
+  util.c - Utility functions.\r
+*/\r
+\r
+#include "ansicon.h"\r
+#include "version.h"\r
+\r
+\r
+TCHAR  prog_path[MAX_PATH];\r
+LPTSTR prog;\r
+int    log_level;\r
+char   tempfile[MAX_PATH];\r
+DWORD  pid;\r
+\r
+\r
+// Get just the name of the program: "C:\path\program.exe" -> "program".\r
+// Returns a pointer within program; it is modified to remove the extension.\r
+LPTSTR get_program_name( LPTSTR program )\r
+{\r
+  LPTSTR name, ext;\r
+\r
+  if (program == NULL)\r
+  {\r
+    GetModuleFileName( NULL, prog_path, lenof(prog_path) );\r
+    program = prog_path;\r
+  }\r
+  name = wcsrchr( program, '\\' );\r
+  if (name != NULL)\r
+    ++name;\r
+  else\r
+    name = program;\r
+  ext = wcsrchr( name, '.' );\r
+  if (ext != NULL && ext != name)\r
+    *ext = '\0';\r
+\r
+  return name;\r
+}\r
+\r
+\r
+void DEBUGSTR( int level, LPTSTR szFormat, ... )\r
+{\r
+  TCHAR szBuffer[1024], szEscape[1024];\r
+  va_list pArgList;\r
+  HANDLE mutex;\r
+  DWORD wait;\r
+  FILE* file;\r
+\r
+  if ((log_level & 3) < level && !(level & 4 & log_level))\r
+    return;\r
+\r
+  if (*tempfile == '\0')\r
+  {\r
+    _snprintf( tempfile, MAX_PATH, "%s\\ansicon.log", getenv( "TEMP" ) );\r
+    pid = GetCurrentProcessId();\r
+  }\r
+  if (szFormat == NULL)\r
+  {\r
+    file = fopen( tempfile, (log_level & 8) ? "at" : "wt" );\r
+    if (file != NULL)\r
+    {\r
+      SYSTEMTIME now;\r
+      GetLocalTime( &now );\r
+      fprintf( file, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d) started "\r
+                     "%d-%.2d-%.2d %d:%.2d:%.2d\n",\r
+                    log_level,\r
+                    now.wYear, now.wMonth, now.wDay,\r
+                    now.wHour, now.wMinute, now.wSecond );\r
+      fclose( file );\r
+    }\r
+    return;\r
+  }\r
+\r
+  va_start( pArgList, szFormat );\r
+  _vsnwprintf( szBuffer, lenof(szBuffer), szFormat, pArgList );\r
+  va_end( pArgList );\r
+\r
+  szFormat = szBuffer;\r
+  if (*szFormat == '\33')\r
+  {\r
+    BOOL first = TRUE;\r
+    LPTSTR pos = szEscape;\r
+    while (*++szFormat != '\0' && pos < szEscape + lenof(szEscape) - 4)\r
+    {\r
+      if (*szFormat < 32)\r
+      {\r
+       *pos++ = '\\';\r
+       switch (*szFormat)\r
+       {\r
+         case '\a': *pos++ = 'a'; break;\r
+         case '\b': *pos++ = 'b'; break;\r
+         case '\t': *pos++ = 't'; break;\r
+         case '\r': *pos++ = 'r'; break;\r
+         case '\n': *pos++ = 'n'; break;\r
+         case  27 : *pos++ = 'e'; break;\r
+         default:\r
+           pos += _snwprintf( pos, 32, L"%.*o",\r
+                            (szFormat[1] >= '0' && szFormat[1] <= '7') ? 3 : 1,\r
+                            *szFormat );\r
+       }\r
+      }\r
+      else\r
+      {\r
+       if (*szFormat == '"')\r
+       {\r
+         if (first)\r
+           first = FALSE;\r
+         else if (szFormat[1] != '\0')\r
+           *pos++ = '\\';\r
+       }\r
+       *pos++ = *szFormat;\r
+      }\r
+    }\r
+    *pos = '\0';\r
+    szFormat = szEscape;\r
+  }\r
+\r
+  mutex = CreateMutex( NULL, FALSE, L"ANSICON_debug_file" );\r
+  wait = WaitForSingleObject( mutex, 500 );\r
+  file = fopen( tempfile, "at" ); // _fmode might be binary\r
+  if (file != NULL)\r
+  {\r
+    fwprintf( file, L"%s (%lu): %s\n", prog, pid, szFormat );\r
+    fclose( file );\r
+  }\r
+  if (wait == WAIT_OBJECT_0)\r
+    ReleaseMutex( mutex );\r
+  CloseHandle( mutex );\r
+}\r
old mode 100755 (executable)
new mode 100644 (file)
index ff76004..ec1ae85
@@ -1,9 +1,19 @@
-/*
-  version.h - Version defines.
-*/
-
-#define PVERS  L"1.53"         // wide string
-#define PVERSA  "1.53"         // ANSI string (windres 2.16.91 didn't like L)
-#define PVERE  L"153"          // wide environment string
-#define PVEREA  "153"          // ANSI environment string
-#define PVERB  1,5,3,0         // binary (resource)
+/*\r
+  version.h - Version defines.\r
+*/\r
+\r
+#define PVERS  L"1.66"         // wide string\r
+#define PVERSA  "1.66"         // ANSI string (windres 2.16.91 didn't like L)\r
+#define PVERE  L"166"          // wide environment string\r
+#define PVEREA  "166"          // ANSI environment string\r
+#define PVERB  1,6,6,0         // binary (resource)\r
+\r
+#ifdef _WIN64\r
+# define BITS L"64"\r
+# define BITSA "64"\r
+#else\r
+# define BITS L"32"\r
+# define BITSA "32"\r
+#endif\r
+\r
+#define ANSIDLL L"ANSI" BITS L".dll"\r
old mode 100755 (executable)
new mode 100644 (file)
index 33e0444..9ab8f40
@@ -1,88 +1,88 @@
-/*
-  wow64.h - Definitions for Wow64.
-
-  Mingw64/TDM does not include these Wow64 definitions.
-*/
-
-#ifndef WOW64_H
-#define WOW64_H
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#define WOW64_CONTEXT_i386     0x00010000
-
-#define WOW64_CONTEXT_CONTROL              (WOW64_CONTEXT_i386 | 0x00000001L)
-#define WOW64_CONTEXT_INTEGER              (WOW64_CONTEXT_i386 | 0x00000002L)
-#define WOW64_CONTEXT_SEGMENTS             (WOW64_CONTEXT_i386 | 0x00000004L)
-#define WOW64_CONTEXT_FLOATING_POINT       (WOW64_CONTEXT_i386 | 0x00000008L)
-#define WOW64_CONTEXT_DEBUG_REGISTERS      (WOW64_CONTEXT_i386 | 0x00000010L)
-#define WOW64_CONTEXT_EXTENDED_REGISTERS    (WOW64_CONTEXT_i386 | 0x00000020L)
-
-#define WOW64_CONTEXT_FULL      (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)
-
-#define WOW64_CONTEXT_ALL       (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | \
-                                 WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | \
-                                 WOW64_CONTEXT_EXTENDED_REGISTERS)
-
-#define WOW64_SIZE_OF_80387_REGISTERS      80
-
-#define WOW64_MAXIMUM_SUPPORTED_EXTENSION     512
-
-typedef struct _WOW64_FLOATING_SAVE_AREA {
-    DWORD   ControlWord;
-    DWORD   StatusWord;
-    DWORD   TagWord;
-    DWORD   ErrorOffset;
-    DWORD   ErrorSelector;
-    DWORD   DataOffset;
-    DWORD   DataSelector;
-    BYTE    RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];
-    DWORD   Cr0NpxState;
-} WOW64_FLOATING_SAVE_AREA;
-
-typedef WOW64_FLOATING_SAVE_AREA *PWOW64_FLOATING_SAVE_AREA;
-
-typedef struct _WOW64_CONTEXT {
-
-    DWORD ContextFlags;
-
-    DWORD   Dr0;
-    DWORD   Dr1;
-    DWORD   Dr2;
-    DWORD   Dr3;
-    DWORD   Dr6;
-    DWORD   Dr7;
-
-    WOW64_FLOATING_SAVE_AREA FloatSave;
-
-    DWORD   SegGs;
-    DWORD   SegFs;
-    DWORD   SegEs;
-    DWORD   SegDs;
-
-    DWORD   Edi;
-    DWORD   Esi;
-    DWORD   Ebx;
-    DWORD   Edx;
-    DWORD   Ecx;
-    DWORD   Eax;
-
-    DWORD   Ebp;
-    DWORD   Eip;
-    DWORD   SegCs;
-    DWORD   EFlags;
-    DWORD   Esp;
-    DWORD   SegSs;
-
-    BYTE    ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
-
-} WOW64_CONTEXT;
-
-typedef WOW64_CONTEXT *PWOW64_CONTEXT;
-
-
-typedef BOOL (WINAPI *TWow64GetThreadContext)( HANDLE hThread, PWOW64_CONTEXT lpContext );
-typedef BOOL (WINAPI *TWow64SetThreadContext)( HANDLE hThread, CONST WOW64_CONTEXT *lpContext );
-
-#endif
+/*\r
+  wow64.h - Definitions for Wow64.\r
+\r
+  The 2003 Platform SDK does not include these Wow64 definitions.\r
+*/\r
+\r
+#ifndef WOW64_H\r
+#define WOW64_H\r
+\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+\r
+#define WOW64_CONTEXT_i386     0x00010000\r
+\r
+#define WOW64_CONTEXT_CONTROL              (WOW64_CONTEXT_i386 | 0x00000001L)\r
+#define WOW64_CONTEXT_INTEGER              (WOW64_CONTEXT_i386 | 0x00000002L)\r
+#define WOW64_CONTEXT_SEGMENTS             (WOW64_CONTEXT_i386 | 0x00000004L)\r
+#define WOW64_CONTEXT_FLOATING_POINT       (WOW64_CONTEXT_i386 | 0x00000008L)\r
+#define WOW64_CONTEXT_DEBUG_REGISTERS      (WOW64_CONTEXT_i386 | 0x00000010L)\r
+#define WOW64_CONTEXT_EXTENDED_REGISTERS    (WOW64_CONTEXT_i386 | 0x00000020L)\r
+\r
+#define WOW64_CONTEXT_FULL      (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)\r
+\r
+#define WOW64_CONTEXT_ALL       (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | \\r
+                                 WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | \\r
+                                 WOW64_CONTEXT_EXTENDED_REGISTERS)\r
+\r
+#define WOW64_SIZE_OF_80387_REGISTERS      80\r
+\r
+#define WOW64_MAXIMUM_SUPPORTED_EXTENSION     512\r
+\r
+typedef struct _WOW64_FLOATING_SAVE_AREA {\r
+    DWORD   ControlWord;\r
+    DWORD   StatusWord;\r
+    DWORD   TagWord;\r
+    DWORD   ErrorOffset;\r
+    DWORD   ErrorSelector;\r
+    DWORD   DataOffset;\r
+    DWORD   DataSelector;\r
+    BYTE    RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];\r
+    DWORD   Cr0NpxState;\r
+} WOW64_FLOATING_SAVE_AREA;\r
+\r
+typedef WOW64_FLOATING_SAVE_AREA *PWOW64_FLOATING_SAVE_AREA;\r
+\r
+typedef struct _WOW64_CONTEXT {\r
+\r
+    DWORD ContextFlags;\r
+\r
+    DWORD   Dr0;\r
+    DWORD   Dr1;\r
+    DWORD   Dr2;\r
+    DWORD   Dr3;\r
+    DWORD   Dr6;\r
+    DWORD   Dr7;\r
+\r
+    WOW64_FLOATING_SAVE_AREA FloatSave;\r
+\r
+    DWORD   SegGs;\r
+    DWORD   SegFs;\r
+    DWORD   SegEs;\r
+    DWORD   SegDs;\r
+\r
+    DWORD   Edi;\r
+    DWORD   Esi;\r
+    DWORD   Ebx;\r
+    DWORD   Edx;\r
+    DWORD   Ecx;\r
+    DWORD   Eax;\r
+\r
+    DWORD   Ebp;\r
+    DWORD   Eip;\r
+    DWORD   SegCs;\r
+    DWORD   EFlags;\r
+    DWORD   Esp;\r
+    DWORD   SegSs;\r
+\r
+    BYTE    ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];\r
+\r
+} WOW64_CONTEXT;\r
+\r
+typedef WOW64_CONTEXT *PWOW64_CONTEXT;\r
+\r
+\r
+typedef BOOL (WINAPI *TWow64GetThreadContext)( HANDLE hThread, PWOW64_CONTEXT lpContext );\r
+typedef BOOL (WINAPI *TWow64SetThreadContext)( HANDLE hThread, CONST WOW64_CONTEXT *lpContext );\r
+\r
+#endif\r
diff --git a/ansicon/x86/ANSI32.dll b/ansicon/x86/ANSI32.dll
new file mode 100644 (file)
index 0000000..1441cb1
Binary files /dev/null and b/ansicon/x86/ANSI32.dll differ
diff --git a/ansicon/x86/ansicon.exe b/ansicon/x86/ansicon.exe
new file mode 100644 (file)
index 0000000..2ac34e4
Binary files /dev/null and b/ansicon/x86/ansicon.exe differ
index 9416f203c4453c7cdd456fcba5524eea391d1177..ade5b9dd04ef2e46d57d49ff4741062a67a2d2ce 100644 (file)
@@ -17,15 +17,15 @@ build()
         echo "Make sdb..."
         make
 
-        echo "Make ancicon..."
-        cd "ansicon"
-        if [ "${TARGET_OS}" = "windows-32" ]
-        then
-                make ansicon32
-        else
-                make ansicon32
-        fi
-        cd ..
+#       echo "Make ancicon..."
+#       cd "ansicon"
+#       if [ "${TARGET_OS}" = "windows-32" ]
+#       then
+#                make ansicon32
+#       else
+#                make ansicon32
+#       fi
+#       cd ..
 }
 
 # install
@@ -49,4 +49,4 @@ install()
 [ "$1" = "clean" ] && clean
 [ "$1" = "build" ] && build
 [ "$1" = "install" ] && install
-exit 0
\ No newline at end of file
+exit 0