ansicon/util.c
Jason Hood dc7569dc26 Inject by adding to the Import Directory Table.
-p uses CreateRemoteThread, determining kernel32.dll & LLW dynamically.
Loading via LoadLibrary will remember the current attributes, restoring them on
unload.
Tweaked log output (remove quotes around CreateProcess command line; add an
underscore to 64-bit addresses).
ansicon.exe will really output (to the console) strings as Unicode.
Fixed ansicon.exe, if installed, restoring the default attributes, not current.
ansicon.exe will start with ANSICON_DEF (if defined and -m not used).
2014-02-05 00:21:42 +10:00

173 lines
3.8 KiB
C

/*
util.c - Utility functions.
*/
#include "ansicon.h"
#include "version.h"
TCHAR prog_path[MAX_PATH];
LPTSTR prog;
int log_level;
char ansi_dll[MAX_PATH];
DWORD ansi_len;
#ifdef _WIN64
char* ansi_bits;
#endif
// 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;
}
// Get the ANSI path of the DLL for the import. If it can't be converted,
// just use the name and hope it's on the PATH. Returns the length of the
// path/name, including padding to make it dword-aligned. The 64-bit version
// expects ansi_bits to point to the size within dll on entry.
void set_ansi_dll( LPTSTR dll )
{
BOOL bad;
ansi_len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, dll, -1,
NULL, 0, NULL, &bad );
if (bad || ansi_len > MAX_PATH)
{
ansi_len = 12;
memcpy( ansi_dll, "ANSI32.dll\0", 12 );
#ifdef _WIN64
if (*ansi_bits == '6')
{
ansi_dll[4] = '6';
ansi_dll[5] = '4';
}
ansi_bits = ansi_dll + 4;
#endif
}
else
{
WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, dll, -1,
ansi_dll, MAX_PATH, NULL, NULL );
#ifdef _WIN64
ansi_bits = ansi_dll + ansi_len - 7;
#endif
ansi_len = (ansi_len + 3) & ~3;
}
}
void DEBUGSTR( int level, LPTSTR szFormat, ... )
{
static char tempfile[MAX_PATH];
static DWORD pid;
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)
{
// Explicitly use 't', as _fmode might be binary.
file = fopen( tempfile, (log_level & 8) ? "at" : "wt" );
if (file != NULL)
{
SYSTEMTIME now;
GetLocalTime( &now );
fprintf( file, "ANSICON (" BITSA "-bit) 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" );
if (file != NULL)
{
fwprintf( file, L"%s (%lu): %s\n", prog, pid, szFormat );
fclose( file );
}
if (wait == WAIT_OBJECT_0)
ReleaseMutex( mutex );
CloseHandle( mutex );
}