Merged VC changes

This commit is contained in:
Jason Hood 2010-11-15 22:14:17 +10:00
commit de677f3408
8 changed files with 263 additions and 166 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.zip
/x86
/x64

126
ANSI.c
View File

@ -58,18 +58,20 @@
fix multibyte conversion problems.
*/
#define UNICODE
#define _UNICODE
#include <tchar.h>
#ifndef UNICODE
# define UNICODE
#endif
#define lenof(str) (sizeof(str)/sizeof(TCHAR))
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ImageHlp.h>
#include <tlhelp32.h>
#include "injdll.h"
#define lenof(array) (sizeof(array)/sizeof(*(array)))
#define isdigit(c) ('0' <= (c) && (c) <= '9')
// ========== Auxiliary debug function
@ -87,7 +89,7 @@ void DEBUGSTR( LPTSTR szFormat, ... ) // sort of OutputDebugStringf
TCHAR szBuffer[1024], szEscape[1024];
va_list pArgList;
va_start( pArgList, szFormat );
_vsntprintf( szBuffer, lenof(szBuffer), szFormat, pArgList );
_vsnwprintf( szBuffer, lenof(szBuffer), szFormat, pArgList );
va_end( pArgList );
szFormat = szBuffer;
@ -106,10 +108,11 @@ void DEBUGSTR( LPTSTR szFormat, ... ) // sort of OutputDebugStringf
case '\t': *pos++ = 't'; break;
case '\r': *pos++ = 'r'; break;
case '\n': *pos++ = 'n'; break;
case '\e': *pos++ = 'e'; break;
default: pos += _tprintf( pos, TEXT("%.*o"),
case 27 : *pos++ = 'e'; break;
default:
pos += wprintf( pos, L"%.*o",
(szFormat[1] >= '0' && szFormat[1] <= '7') ? 3 : 1,
*szFormat );
*szFormat );
}
}
else if (*szFormat == '"')
@ -131,19 +134,25 @@ void DEBUGSTR( LPTSTR szFormat, ... ) // sort of OutputDebugStringf
szFormat = szEscape;
}
#if (MYDEBUG > 1)
{
FILE* file = fopen( tempfile, "a" );
if (file != NULL)
{
_ftprintf( file, TEXT("%s\n"), szFormat );
fwprintf( file, L"%s\n", szFormat );
fclose( file );
}
}
#else
OutputDebugString( szFormat );
#endif
}
#else
#if defined(_MSC_VER) && _MSC_VER <= 1400
void DEBUGSTR() { }
#else
#define DEBUGSTR(...)
#endif
#endif
// ========== Global variables and constants
@ -223,11 +232,11 @@ WORD foreground;
WORD background;
WORD bold;
WORD underline;
WORD rvideo = 0;
WORD concealed = 0;
WORD rvideo;
WORD concealed;
// saved cursor position
COORD SavePos = { 0, 0 };
COORD SavePos;
// ========== Hooking API functions
@ -270,7 +279,7 @@ BOOL HookAPIOneMod(
pDosHeader = (PIMAGE_DOS_HEADER)hFromModule;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
DEBUGSTR( TEXT("error: %s(%d)"), TEXT(__FILE__), __LINE__ );
DEBUGSTR( L"error: %S(%d)", __FILE__, __LINE__ );
return FALSE;
}
@ -280,7 +289,7 @@ BOOL HookAPIOneMod(
// One more test to make sure we're looking at a "PE" image
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
DEBUGSTR( TEXT("error: %s(%d)"), TEXT(__FILE__), __LINE__ );
DEBUGSTR( L"error: %S(%d)", __FILE__, __LINE__ );
return FALSE;
}
@ -305,7 +314,7 @@ BOOL HookAPIOneMod(
PCSTR* lib;
PSTR pszModName = MakePtr( PSTR, pDosHeader, pImportDesc->Name );
for (lib = APIs; *lib; ++lib)
if (stricmp( pszModName, *lib ) == 0)
if (_stricmp( pszModName, *lib ) == 0)
break;
if (*lib == NULL)
continue;
@ -335,7 +344,7 @@ BOOL HookAPIOneMod(
DWORD flOldProtect, flNewProtect, flDummy;
MEMORY_BASIC_INFORMATION mbi;
DEBUGSTR( TEXT(" %hs"), hook->name );
DEBUGSTR( L" %S", hook->name );
// Get the current protection attributes.
VirtualQuery( &pThunk->u1.Function, &mbi, sizeof(mbi) );
// Take the access protection flags.
@ -354,7 +363,7 @@ BOOL HookAPIOneMod(
&pThunk->u1.Function,
&patch, sizeof(patch), NULL ))
{
DEBUGSTR( TEXT("error: %s(%d)"), TEXT(__FILE__), __LINE__ );
DEBUGSTR( L"error: %S(%d)", __FILE__, __LINE__ );
return FALSE;
}
@ -389,7 +398,7 @@ BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore )
if (hModuleSnap == INVALID_HANDLE_VALUE)
{
DEBUGSTR( TEXT("error: %s(%d)"), TEXT(__FILE__), __LINE__ );
DEBUGSTR( L"error: %S(%d)", __FILE__, __LINE__ );
return FALSE;
}
@ -403,7 +412,7 @@ BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore )
// We don't hook functions in our own module.
if (me.hModule != hDllInstance && me.hModule != hKernel)
{
DEBUGSTR( (restore) ? TEXT("Unhooking from %s") : TEXT("Hooking in %s"),
DEBUGSTR( (restore) ? L"Unhooking from %s" : L"Hooking in %s",
me.szModule );
// Hook this function in this module.
if (!HookAPIOneMod( me.hModule, Hooks, restore ))
@ -448,7 +457,7 @@ void PushBuffer( TCHAR c )
if (nCharInBuffer >= BUFFER_SIZE)
{
FlushBuffer();
DEBUGSTR( TEXT("flush") );
DEBUGSTR( L"flush" );
}
}
@ -918,13 +927,13 @@ void Inject( LPPROCESS_INFORMATION pinfo, LPPROCESS_INFORMATION lpi,
}
else
{
DEBUGSTR( TEXT(" Ignoring unsupported machine (%x)"),
DEBUGSTR( L" Ignoring unsupported machine (%x)",
nt_header.FileHeader.Machine );
}
}
else
{
DEBUGSTR( TEXT(" Ignoring non-console subsystem (%u)"),
DEBUGSTR( L" Ignoring non-console subsystem (%u)",
nt_header.OptionalHeader.Subsystem );
}
break;
@ -990,7 +999,7 @@ BOOL WINAPI MyCreateProcessA( LPCSTR lpApplicationName,
&pi ))
return FALSE;
DEBUGSTR( TEXT("CreateProcessA: \"%hs\", \"%hs\""),
DEBUGSTR( L"CreateProcessA: \"%S\", \"%S\"",
(lpApplicationName == NULL) ? "" : lpApplicationName,
(lpCommandLine == NULL) ? "" : lpCommandLine );
Inject( &pi, lpProcessInformation, dwCreationFlags );
@ -1024,7 +1033,7 @@ BOOL WINAPI MyCreateProcessW( LPCWSTR lpApplicationName,
&pi ))
return FALSE;
DEBUGSTR( TEXT("CreateProcessW: \"%ls\", \"%ls\""),
DEBUGSTR( L"CreateProcessW: \"%s\", \"%s\"",
(lpApplicationName == NULL) ? L"" : lpApplicationName,
(lpCommandLine == NULL) ? L"" : lpCommandLine );
Inject( &pi, lpProcessInformation, dwCreationFlags );
@ -1038,7 +1047,7 @@ HMODULE WINAPI MyLoadLibraryA( LPCSTR lpFileName )
HMODULE hMod = LoadLibraryA( lpFileName );
if (hMod && hMod != hKernel)
{
DEBUGSTR( TEXT("Hooking in %hs (LoadLibraryA)"), lpFileName );
DEBUGSTR( L"Hooking in %S (LoadLibraryA)", lpFileName );
HookAPIOneMod( hMod, Hooks, FALSE );
}
return hMod;
@ -1050,7 +1059,7 @@ HMODULE WINAPI MyLoadLibraryW( LPCWSTR lpFileName )
HMODULE hMod = LoadLibraryW( lpFileName );
if (hMod && hMod != hKernel)
{
DEBUGSTR( TEXT("Hooking in %ls (LoadLibraryW)"), lpFileName );
DEBUGSTR( L"Hooking in %s (LoadLibraryW)", lpFileName );
HookAPIOneMod( hMod, Hooks, FALSE );
}
return hMod;
@ -1063,7 +1072,7 @@ HMODULE WINAPI MyLoadLibraryExA( LPCSTR lpFileName, HANDLE hFile,
HMODULE hMod = LoadLibraryExA( lpFileName, hFile, dwFlags );
if (hMod && hMod != hKernel && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE))
{
DEBUGSTR( TEXT("Hooking in %hs (LoadLibraryExA)"), lpFileName );
DEBUGSTR( L"Hooking in %S (LoadLibraryExA)", lpFileName );
HookAPIOneMod( hMod, Hooks, FALSE );
}
return hMod;
@ -1076,7 +1085,7 @@ HMODULE WINAPI MyLoadLibraryExW( LPCWSTR lpFileName, HANDLE hFile,
HMODULE hMod = LoadLibraryExW( lpFileName, hFile, dwFlags );
if (hMod && hMod != hKernel && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE))
{
DEBUGSTR( TEXT("Hooking in %ls (LoadLibraryExW)"), lpFileName );
DEBUGSTR( L"Hooking in %s (LoadLibraryExW)", lpFileName );
HookAPIOneMod( hMod, Hooks, FALSE );
}
return hMod;
@ -1103,7 +1112,7 @@ WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
if (GetConsoleMode( hCon, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
{
UINT cp = GetConsoleOutputCP();
DEBUGSTR( TEXT("\\WriteConsoleA: %lu \"%.*hs\""), nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
DEBUGSTR( L"\\WriteConsoleA: %lu \"%.*S\"", nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
len = MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, NULL, 0 );
buf = malloc( len * sizeof(WCHAR) );
if (buf == NULL)
@ -1114,6 +1123,18 @@ WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, buf, len );
rc = ParseAndPrintString( hCon, buf, len, lpNumberOfCharsWritten );
free( buf );
if (rc && *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.
TCHAR name[MAX_PATH];
DWORD len;
len = GetModuleFileName( NULL, name, lenof(name) );
if (len >= 8 && _wcsicmp( name + len - 8, L"ruby.exe" ) == 0)
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
}
return rc;
}
else
@ -1133,7 +1154,7 @@ WINAPI MyWriteConsoleW( HANDLE hCon, LPCVOID lpBuffer,
DWORD Mode;
if (GetConsoleMode( hCon, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
{
DEBUGSTR( TEXT("\\WriteConsoleW: %lu \"%.*ls\""), nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
DEBUGSTR( L"\\WriteConsoleW: %lu \"%.*s\"", nNumberOfCharsToWrite, nNumberOfCharsToWrite, lpBuffer );
return ParseAndPrintString( hCon, lpBuffer,
nNumberOfCharsToWrite,
lpNumberOfCharsWritten );
@ -1154,18 +1175,11 @@ WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
DWORD Mode;
if (GetConsoleMode( hFile, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
{
TCHAR name[MAX_PATH];
DWORD len;
BOOL rc;
DEBUGSTR( TEXT("\\WriteFile: %lu \"%.*hs\""), nNumberOfBytesToWrite, nNumberOfBytesToWrite, lpBuffer );
rc = MyWriteConsoleA( hFile, lpBuffer,
nNumberOfBytesToWrite,
lpNumberOfBytesWritten,
lpOverlapped );
len = GetModuleFileName( NULL, name, lenof(name) );
if (len >= 8 && lstrcmpi( name + len - 8, TEXT("ruby.exe") ) == 0)
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return rc;
DEBUGSTR( L"\\WriteFile: %lu \"%.*S\"", nNumberOfBytesToWrite, nNumberOfBytesToWrite, lpBuffer );
return MyWriteConsoleA( hFile, lpBuffer,
nNumberOfBytesToWrite,
lpNumberOfBytesWritten,
lpOverlapped );
}
else // here, WriteFile is the old function (this module is not hooked)
{
@ -1182,24 +1196,24 @@ WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
TCHAR buf[64];
if (pcsbi == NULL)
{
HANDLE hConOut;
hConOut = CreateFile( TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
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;
}
TCHAR buf[64];
wsprintf( buf, TEXT("%dx%d (%dx%d)"),
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( TEXT("ANSICON"), buf );
SetEnvironmentVariable( L"ANSICON", buf );
}
DWORD
@ -1213,7 +1227,7 @@ WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
DWORD
WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
{
if (lstrcmpiW( lpName, L"ANSICON" ) == 0)
if (lstrcmpi( lpName, L"ANSICON" ) == 0)
set_ansicon( NULL );
return GetEnvironmentVariableW( lpName, lpBuffer, nSize );
}
@ -1249,9 +1263,9 @@ void OriginalAttr( void )
HANDLE hConOut;
CONSOLE_SCREEN_BUFFER_INFO csbi;
hConOut = CreateFile( TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
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 );
@ -1288,7 +1302,7 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
#endif
hDllInstance = hInstance; // save Dll instance handle
DEBUGSTR( TEXT("hDllInstance = %p"), hDllInstance );
DEBUGSTR( L"hDllInstance = %p", hDllInstance );
// Get the entry points to the original functions.
hKernel = GetModuleHandleA( APIKernel );
@ -1306,7 +1320,7 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
}
else if (dwReason == DLL_PROCESS_DETACH && lpReserved == NULL)
{
DEBUGSTR( TEXT("Unloading") );
DEBUGSTR( L"Unloading" );
HookAPIAllMod( Hooks, TRUE );
}

157
ansicon.c
View File

@ -38,20 +38,22 @@
v1.30, 3 August to 7 September, 2010:
x64 support.
v1.31, 13 November, 2010:
use LLW to fix potential Unicode path problems.
v1.31, 13 to 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>).
*/
#define PVERS "1.31"
#define PDATE "13 November, 2010"
#define PVERS L"1.31"
#define PDATE L"15 November, 2010"
#define UNICODE
#define _UNICODE
#ifndef UNICODE
# define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500 // MinGW wants this defined for OpenThread
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <shellapi.h>
@ -60,7 +62,7 @@
#include <io.h>
#include "injdll.h"
#define lenof(str) (sizeof(str)/sizeof(TCHAR))
#define lenof(array) (sizeof(array)/sizeof(*(array)))
#ifdef __MINGW32__
int _CRT_glob = 0;
@ -76,8 +78,8 @@ int _CRT_glob = 0;
#endif
#define CMDKEY TEXT("Software\\Microsoft\\Command Processor")
#define AUTORUN TEXT("AutoRun")
#define CMDKEY L"Software\\Microsoft\\Command Processor"
#define AUTORUN L"AutoRun"
void help( void );
@ -96,7 +98,7 @@ BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi );
void Inject( LPPROCESS_INFORMATION ppi )
{
DWORD len;
WCHAR dll[MAX_PATH];
TCHAR dll[MAX_PATH];
len = GetModuleFileName( NULL, dll, lenof(dll) );
while (dll[len-1] != '\\')
@ -112,9 +114,9 @@ static CONSOLE_SCREEN_BUFFER_INFO csbi;
void get_original_attr( void )
{
hConOut = CreateFile( TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
GetConsoleScreenBufferInfo( hConOut, &csbi );
}
@ -145,27 +147,27 @@ int main( void )
int rc = 0;
int argc;
LPWSTR* argv = CommandLineToArgvW( GetCommandLineW(), &argc );
LPWSTR* argv = CommandLineToArgvW( GetCommandLine(), &argc );
if (argc > 1)
{
if (lstrcmp( argv[1], TEXT("--help") ) == 0 ||
if (lstrcmp( argv[1], L"--help" ) == 0 ||
(argv[1][0] == '-' && (argv[1][1] == '?' || argv[1][1] == 'h')) ||
(argv[1][0] == '/' && argv[1][1] == '?'))
{
help();
return rc;
}
if (lstrcmp( argv[1], TEXT("--version") ) == 0)
if (lstrcmp( argv[1], L"--version" ) == 0)
{
_putts( TEXT("ANSICON (" BITS "-bit) version " PVERS " (" PDATE ").") );
_putws( L"ANSICON (" BITS L"-bit) version " PVERS L" (" PDATE L")." );
return rc;
}
}
option = (argc > 1 && argv[1][0] == '-');
if (option && (_totlower( argv[1][1] ) == 'i' ||
_totlower( argv[1][1] ) == 'u'))
if (option && (towlower( argv[1][1] ) == 'i' ||
towlower( argv[1][1] ) == 'u'))
{
process_autorun( argv[1][1] );
return rc;
@ -177,15 +179,15 @@ int main( void )
if (option && argv[1][1] == 'm')
{
WORD attr = 7;
if (_istxdigit( argv[1][2] ))
if (iswxdigit( argv[1][2] ))
{
attr = _istdigit( argv[1][2] ) ? argv[1][2] - '0'
: (argv[1][2] | 0x20) - 'a' + 10;
if (_istxdigit( argv[1][3]))
attr = iswdigit( argv[1][2] ) ? argv[1][2] - '0'
: (argv[1][2] | 0x20) - 'a' + 10;
if (iswxdigit( argv[1][3]))
{
attr <<= 4;
attr |= _istdigit( argv[1][3] ) ? argv[1][3] - '0'
: (argv[1][3] | 0x20) - 'a' + 10;
attr |= iswdigit( argv[1][3] ) ? argv[1][3] - '0'
: (argv[1][3] | 0x20) - 'a' + 10;
}
}
SetConsoleTextAttribute( hConOut, attr );
@ -196,7 +198,7 @@ int main( void )
option = (argc > 1 && argv[1][0] == '-');
}
installed = (GetEnvironmentVariable( TEXT("ANSICON"), NULL, 0 ) != 0);
installed = (GetEnvironmentVariable( L"ANSICON", NULL, 0 ) != 0);
if (option && argv[1][1] == 'p')
{
@ -215,7 +217,7 @@ int main( void )
}
else
{
_putts( TEXT("ANSICON: could not obtain the parent process.") );
_putws( L"ANSICON: could not obtain the parent process." );
rc = 1;
}
}
@ -223,7 +225,7 @@ int main( void )
{
ansi = 0;
if (!installed)
ansi = LoadLibrary( TEXT("ANSI" BITS ".dll") );
ansi = LoadLibrary( L"ANSI" BITS L".dll" );
if (option && (argv[1][1] == 't' || argv[1][1] == 'T'))
{
@ -236,10 +238,10 @@ int main( void )
for (; argc > 2; ++argv, --argc)
{
if (title)
_tprintf( TEXT("==> %s <==\n"), argv[2] );
wprintf( L"==> %s <==\n", argv[2] );
display( argv[2], title );
if (title)
_puttchar( '\n' );
putwchar( '\n' );
}
}
else
@ -251,21 +253,21 @@ int main( void )
if (cmd[0] == '-' && (cmd[1] == 'e' || cmd[1] == 'E'))
{
_fputts( cmd + 3, stdout );
fputws( cmd + 3, stdout );
if (cmd[1] == 'e')
_puttchar( '\n' );
putwchar( '\n' );
}
else if (!isatty( 0 ) && *cmd == '\0')
else if (!_isatty( 0 ) && *cmd == '\0')
{
display( TEXT("-"), FALSE );
display( L"-", FALSE );
}
else
{
if (*cmd == '\0')
{
cmd = _tgetenv( TEXT("ComSpec") );
cmd = _wgetenv( L"ComSpec" );
if (cmd == NULL)
cmd = TEXT("cmd");
cmd = L"cmd";
}
ZeroMemory( &si, sizeof(si) );
@ -278,7 +280,7 @@ int main( void )
else
{
*skip_arg( cmd ) = '\0';
_tprintf( TEXT("ANSICON: '%s' could not be executed.\n"), cmd );
wprintf( L"ANSICON: '%s' could not be executed.\n", cmd );
rc = 1;
}
}
@ -300,8 +302,8 @@ void print_error( LPCTSTR name, BOOL title )
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, GetLastError(), 0, (LPTSTR)(LPVOID)&errmsg, 0, NULL );
if (!title)
_tprintf( TEXT("ANSICON: %s: "), name );
_fputts( errmsg, stdout );
wprintf( L"ANSICON: %s: ", name );
fputws( errmsg, stdout );
LocalFree( errmsg );
}
@ -309,26 +311,28 @@ void print_error( LPCTSTR name, BOOL title )
// Display a file.
void display( LPCTSTR name, BOOL title )
{
HANDLE file;
int c;
LARGE_INTEGER size, offset;
// Handle the pipe differently.
if (*name == '-' && name[1] == '\0')
{
if (title)
_puttchar( '\n' );
int c;
putwchar( '\n' );
while ((c = getchar()) != EOF)
putchar( c );
return;
}
HANDLE file = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL );
file = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL );
if (file == INVALID_HANDLE_VALUE)
{
print_error( name, title );
return;
}
LARGE_INTEGER size;
GetFileSizeEx( file, &size );
if (size.QuadPart != 0)
{
@ -336,8 +340,7 @@ void display( LPCTSTR name, BOOL title )
if (map)
{
if (title)
_puttchar( '\n' );
LARGE_INTEGER offset;
putwchar( '\n' );
offset.QuadPart = 0;
do
{
@ -378,11 +381,11 @@ void process_autorun( TCHAR cmd )
len = GetModuleFileName( NULL, ansicon+2, MAX_PATH );
ansicon[0] = '&';
ansicon[1] = ansicon[2+len] = '"';
_tcscpy( ansicon + 3+len, L" -p" );
wcscpy( ansicon + 3+len, L" -p" );
len += 6;
inst = (_totlower( cmd ) == 'i');
RegCreateKeyEx( (_istlower( cmd )) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
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 );
@ -394,12 +397,12 @@ void process_autorun( TCHAR cmd )
{
exist += sizeof(TCHAR);
RegQueryValueEx( cmdkey, AUTORUN, NULL, &type, (PBYTE)autorun, &exist );
ansirun = _tcsstr( autorun, ansicon+1 );
ansirun = wcsstr( autorun, ansicon+1 );
if (inst)
{
if (!ansirun)
{
_tcscpy( (LPTSTR)((PBYTE)autorun + exist - sizeof(TCHAR)), ansicon );
wcscpy( (LPTSTR)((PBYTE)autorun + exist - sizeof(TCHAR)), ansicon );
RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun,
exist + len*sizeof(TCHAR) );
}
@ -515,32 +518,32 @@ LPTSTR skip_arg( LPTSTR cmd )
void help( void )
{
_putts( TEXT(
"ANSICON by Jason Hood <jadoxa@yahoo.com.au>.\n"
"Version " PVERS " (" PDATE "). Freeware.\n"
"http://ansicon.adoxa.cjb.net/\n"
"\n"
_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
"Process ANSI escape sequences in Windows console programs.\n"
L"Process ANSI escape sequences in Windows console programs.\n"
#else
"Process ANSI escape sequences in Win32 console programs.\n"
L"Process ANSI escape sequences in Win32 console programs.\n"
#endif
"\n"
"ansicon -i|I | -u|U\n"
"ansicon [-m[<attr>]] [-p | -e|E string | -t|T [file(s)] | program [args]]\n"
"\n"
" -i\t\tinstall - add ANSICON to the AutoRun entry\n"
" -u\t\tuninstall - remove ANSICON from the AutoRun entry\n"
" -I -U\t\tuse local machine instead of current user\n"
" -m\t\tuse grey on black (\"monochrome\") or <attr> as default color\n"
" -p\t\thook into the parent process\n"
" -e\t\techo string\n"
" -E\t\techo string, don't append newline\n"
" -t\t\tdisplay files (\"-\" for stdin), combined as a single stream\n"
" -T\t\tdisplay files, name first, blank line before and after\n"
" program\trun the specified program\n"
" nothing\trun a new command processor, or display stdin if redirected\n"
"\n"
"<attr> is one or two hexadecimal digits; please use \"COLOR /?\" for details."
) );
L"\n"
L"ansicon -i|I | -u|U\n"
L"ansicon [-m[<attr>]] [-p | -e|E string | -t|T [file(s)] | program [args]]\n"
L"\n"
L" -i\t\tinstall - add ANSICON to the AutoRun entry\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."
);
}

View File

@ -7,10 +7,14 @@
#ifndef INJDLL_H
#define INJDLL_H
#ifndef UNICODE
# define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void InjectDLL32( LPPROCESS_INFORMATION, LPCWSTR );
void InjectDLL64( LPPROCESS_INFORMATION, LPCWSTR );
void InjectDLL32( LPPROCESS_INFORMATION, LPCTSTR );
void InjectDLL64( LPPROCESS_INFORMATION, LPCTSTR );
#endif

View File

@ -18,10 +18,12 @@
#include "injdll.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
@ -34,23 +36,29 @@ TWow64SetThreadContext Wow64SetThreadContext;
DWORD LLW;
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
{
CONTEXT context;
DWORD len;
LPVOID mem;
DWORD mem32;
#define CODESIZE 20
BYTE code[CODESIZE+MAX_PATH*sizeof(WCHAR)];
BYTE code[CODESIZE+MAX_PATH*sizeof(TCHAR)];
union
{
PBYTE pB;
PDWORD pL;
} ip;
len = lstrlenW( dll ) + 1;
len = lstrlen( dll ) + 1;
if (len > MAX_PATH)
return;
len *= sizeof(WCHAR);
len *= sizeof(TCHAR);
if (LLW == 0)
{
#ifdef _WIN64
#ifdef __MINGW64__
extern HMODULE hKernel;
#define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
GETPROC( Wow64GetThreadContext );
@ -58,24 +66,25 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
// Assume if one is defined, so is the other.
if (Wow64GetThreadContext == 0)
return;
#endif
STARTUPINFOW si;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
// ...ANSI32.dll\0
CopyMemory( code, dll, len - 7*sizeof(WCHAR) );
// ...ANSI-LLA.exe\0
CopyMemory( code + len - 7*sizeof(WCHAR), L"-LLA.exe", 9*sizeof(WCHAR) );
if (!CreateProcessW( (LPCWSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi ))
CopyMemory( code, dll, len - 7*sizeof(TCHAR) );
// ...ANSI-LLW.exe\0
CopyMemory( code + len - 7*sizeof(TCHAR), L"-LLW.exe", 9*sizeof(TCHAR) );
if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi ))
return;
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess( pi.hProcess, &LLW );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
#else
LLW = (DWORD)LoadLibraryW;
LLW = (DWORD)LoadLibrary;
#endif
}
@ -88,11 +97,6 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
PAGE_EXECUTE_READWRITE );
mem32 = (DWORD)(DWORD_PTR)mem;
union
{
PBYTE pB;
PDWORD pL;
} ip;
ip.pB = code;
*ip.pB++ = 0x68; // push eip
@ -102,7 +106,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
*ip.pB++ = 0x68; // push L"path\to\ANSI32.dll"
*ip.pL++ = mem32 + CODESIZE;
*ip.pB++ = 0xe8; // call LoadLibraryW
*ip.pL++ = LLW - (mem32 + (ip.pB+4 - code));
*ip.pL++ = LLW - (mem32 + (DWORD)(ip.pB+4 - code));
*ip.pB++ = 0x61; // popa
*ip.pB++ = 0x9d; // popf
*ip.pB++ = 0xc3; // ret

View File

@ -15,17 +15,21 @@
I've decided to simply keep the memory.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "injdll.h"
void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
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+MAX_PATH] = {
static BYTE code[CODESIZE+MAX_PATH*sizeof(TCHAR)] = {
0,0,0,0,0,0,0,0, // original rip
0,0,0,0,0,0,0,0, // LoadLibraryW
0x9C, // pushfq
@ -45,7 +49,7 @@ void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
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\ANSI.dll"
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
@ -68,10 +72,10 @@ void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
0, // dword alignment for LLW, fwiw
};
len = lstrlenW( dll ) + 1;
len = lstrlen( dll ) + 1;
if (len > MAX_PATH)
return;
len *= sizeof(WCHAR);
len *= sizeof(TCHAR);
CopyMemory( code + CODESIZE, dll, len );
len += CODESIZE;
@ -81,11 +85,6 @@ void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCWSTR dll )
PAGE_EXECUTE_READWRITE );
LLW = (DWORD64)LoadLibraryW;
union
{
PBYTE pB;
PDWORD64 pL;
} ip;
ip.pB = code;
*ip.pL++ = context.Rip;

70
makefile.vc Normal file
View File

@ -0,0 +1,70 @@
# 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 shell32.lib user32.lib
{}.c{$(DIR)}.obj:
$(CC) /c $(CFLAGS) /Fo$@ $<
{}.rc{$(DIR)}.res:
rc /fo$@ $<
all: ansicon$(BITS)
ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll
ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll x64\ANSI32.dll x64\ANSI-LLW.exe
x86:
mkdir x86
x86\ansicon.exe: x86\ansicon.obj x86\injdll32.obj x86\ansicon.res
$(CC) /nologo /Fe$@ $** $(LIBS)
x86\ANSI32.dll: x86\ANSI.obj x86\injdll32.obj x86\ansi.res
!IF $(BITS) == 32
$(CC) /nologo /LD /Fe$@ $** $(LIBS)
!ENDIF
x64:
mkdir x64
x64\ansicon.exe: x64\ansicon.obj x64\injdll64.obj x64\ansicon.res
$(CC) /nologo /Fe$@ $** $(LIBS) bufferoverflowu.lib
x64\ANSI64.dll: x64\ANSI.obj x64\injdll64.obj x64\injdll32.obj x64\ansi.res
$(CC) /nologo /LD /Fe$@ $** $(LIBS) bufferoverflowu.lib
x64\ANSI32.dll: x86\ANSI32.dll
copy x86\ANSI32.dll x64\ANSI32.dll
x64\ANSI-LLW.exe: ANSI-LLW.c
$(CC) $(CFLAGS) /Fe$@ /Fo$*.obj $? bufferoverflowu.lib
clean:
-del $(DIR)\*.obj $(DIR)\*.res

View File

@ -82,7 +82,7 @@ typedef struct _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 );
typedef BOOL (WINAPI *TWow64GetThreadContext)( HANDLE hThread, PWOW64_CONTEXT lpContext );
typedef BOOL (WINAPI *TWow64SetThreadContext)( HANDLE hThread, CONST WOW64_CONTEXT *lpContext );
#endif