Remove dependence on the CRT; import DLL; fixes
Windows 10's MSVCRT will only work if the Win32 version in the header is 0 or 10. Some PE's use it for something else, so when the DLL is injected the process fails. Provide custom routines for the C functions used, so the DLL only depends on KERNEL32. With the DLL independent of the CRT that would mean the exe would either also need to be independent, or the source files would need to be built twice (or just remove a linker warning). Another option is to export the functions from the DLL and have the exe import them, which turned out to simplify things quite nicely. A process that has a really long command line would not log properly, so double the heap to accommodate it. If ANSICON_DEF could not be parsed the default attribute would be zero (black on black). Use 7 or -7 instead.
This commit is contained in:
parent
f8509c916c
commit
33ba31ad3c
226
ANSI.c
226
ANSI.c
@ -197,14 +197,17 @@
|
|||||||
v1.83, 16 February, 2018:
|
v1.83, 16 February, 2018:
|
||||||
create the flush thread on first use.
|
create the flush thread on first use.
|
||||||
|
|
||||||
v1.84-wip, 17 February, 26 April to 4 May, 2018:
|
v1.84-wip, 17 February, 26 April to 7 May, 2018:
|
||||||
close the flush handles on detach;
|
close the flush handles on detach;
|
||||||
dynamically load WINMM.DLL;
|
dynamically load WINMM.DLL;
|
||||||
use sprintf/_snprintf/_snwprintf instead of wsprintf, avoiding USER32.DLL;
|
use sprintf/_snprintf/_snwprintf instead of wsprintf, avoiding USER32.DLL;
|
||||||
replace bsearch (in procrva.c) with specific code;
|
replace bsearch (in procrva.c) with specific code;
|
||||||
if the primary thread is detached exit the process;
|
if the primary thread is detached exit the process;
|
||||||
get real WriteFile handle before testing for console;
|
get real WriteFile handle before testing for console;
|
||||||
use remote load on Win8+ when the process has no IAT.
|
use remote load on Win8+ when the process has no IAT;
|
||||||
|
remove dependency on the CRT;
|
||||||
|
increase heap to 256KiB to fix logging of really long command lines;
|
||||||
|
default to 7 or -7 if ANSICON_DEF could not be parsed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
@ -445,6 +448,8 @@ typedef struct
|
|||||||
BYTE reverse; // swap console foreground & background attributes
|
BYTE reverse; // swap console foreground & background attributes
|
||||||
} SGR;
|
} SGR;
|
||||||
|
|
||||||
|
SGR orgsgr; // original SGR
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SGR sgr, SaveSgr;
|
SGR sgr, SaveSgr;
|
||||||
@ -493,7 +498,7 @@ void get_state( void )
|
|||||||
|
|
||||||
valid_state = TRUE;
|
valid_state = TRUE;
|
||||||
|
|
||||||
_snwprintf( buf, lenof(buf), L"ANSICON_State_%X", PtrToUint( hwnd ) );
|
ac_wprintf( buf, "ANSICON_State_%X", PtrToUint( hwnd ) );
|
||||||
hMap = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
hMap = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||||
0, sizeof(STATE), buf );
|
0, sizeof(STATE), buf );
|
||||||
init = (GetLastError() != ERROR_ALREADY_EXISTS);
|
init = (GetLastError() != ERROR_ALREADY_EXISTS);
|
||||||
@ -518,11 +523,11 @@ void get_state( void )
|
|||||||
Info.dwSize = csbix.dwSize;
|
Info.dwSize = csbix.dwSize;
|
||||||
ATTR = csbix.wAttributes;
|
ATTR = csbix.wAttributes;
|
||||||
WIN = csbix.srWindow;
|
WIN = csbix.srWindow;
|
||||||
memcpy( pState->o_palette, csbix.ColorTable, sizeof(csbix.ColorTable) );
|
arrcpy( pState->o_palette, csbix.ColorTable );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy( pState->o_palette, legacy_palette, sizeof(legacy_palette) );
|
arrcpy( pState->o_palette, legacy_palette );
|
||||||
if (!GetConsoleScreenBufferInfo( hConOut, &Info ))
|
if (!GetConsoleScreenBufferInfo( hConOut, &Info ))
|
||||||
{
|
{
|
||||||
DEBUGSTR( 1, "Failed to get screen buffer info (%u) - assuming defaults",
|
DEBUGSTR( 1, "Failed to get screen buffer info (%u) - assuming defaults",
|
||||||
@ -536,35 +541,32 @@ void get_state( void )
|
|||||||
BOTTOM = 24;
|
BOTTOM = 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy( pState->x_palette, xterm_palette, sizeof(xterm_palette) );
|
arrcpy( pState->x_palette, xterm_palette );
|
||||||
if (GetEnvironmentVariable( L"ANSICON_REVERSE", NULL, 0 ))
|
|
||||||
{
|
|
||||||
SetEnvironmentVariable( L"ANSICON_REVERSE", NULL );
|
|
||||||
pState->sgr.reverse = TRUE;
|
|
||||||
pState->sgr.foreground = attr2ansi[(ATTR >> 4) & 7];
|
|
||||||
pState->sgr.background = attr2ansi[ATTR & 7];
|
|
||||||
pState->sgr.bold = (ATTR & BACKGROUND_INTENSITY) >> 4;
|
|
||||||
pState->sgr.underline = (ATTR & FOREGROUND_INTENSITY) << 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pState->sgr.foreground = attr2ansi[ATTR & 7];
|
pState->sgr.foreground = attr2ansi[ATTR & 7];
|
||||||
pState->sgr.background = attr2ansi[(ATTR >> 4) & 7];
|
pState->sgr.background = attr2ansi[(ATTR >> 4) & 7];
|
||||||
pState->sgr.bold = ATTR & FOREGROUND_INTENSITY;
|
pState->sgr.bold = ATTR & FOREGROUND_INTENSITY;
|
||||||
pState->sgr.underline = ATTR & BACKGROUND_INTENSITY;
|
pState->sgr.underline = ATTR & BACKGROUND_INTENSITY;
|
||||||
|
|
||||||
|
CloseHandle( hConOut );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetEnvironmentVariable( L"ANSICON_DEF", NULL, 0 ))
|
if (!GetEnvironmentVariable( L"ANSICON_DEF", NULL, 0 ))
|
||||||
{
|
{
|
||||||
TCHAR def[4];
|
TCHAR def[4];
|
||||||
LPTSTR a = def;
|
LPTSTR a = def;
|
||||||
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, 0, NULL );
|
||||||
|
if (!GetConsoleScreenBufferInfo( hConOut, &Info ))
|
||||||
|
ATTR = 7;
|
||||||
if (pState->sgr.reverse)
|
if (pState->sgr.reverse)
|
||||||
{
|
{
|
||||||
*a++ = '-';
|
*a++ = '-';
|
||||||
ATTR = ((ATTR >> 4) & 15) | ((ATTR & 15) << 4);
|
ATTR = ((ATTR >> 4) & 15) | ((ATTR & 15) << 4);
|
||||||
}
|
}
|
||||||
_snwprintf( a, 3, L"%X", ATTR & 255 );
|
ac_wprintf( a, "%X", ATTR & 255 );
|
||||||
SetEnvironmentVariable( L"ANSICON_DEF", def );
|
SetEnvironmentVariable( L"ANSICON_DEF", def );
|
||||||
}
|
|
||||||
set_ansicon( &Info );
|
set_ansicon( &Info );
|
||||||
CloseHandle( hConOut );
|
CloseHandle( hConOut );
|
||||||
}
|
}
|
||||||
@ -611,7 +613,7 @@ BOOL search_env( LPCTSTR var, LPCTSTR val )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (*end != '\0');
|
} while (*end != '\0');
|
||||||
if (_wcsicmp( val, var ) == 0)
|
if (lstrcmpi( val, var ) == 0)
|
||||||
return !not;
|
return !not;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,7 +1004,7 @@ void SendSequence( LPTSTR seq )
|
|||||||
DWORD len;
|
DWORD len;
|
||||||
HANDLE hStdIn = GetStdHandle( STD_INPUT_HANDLE );
|
HANDLE hStdIn = GetStdHandle( STD_INPUT_HANDLE );
|
||||||
|
|
||||||
in = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 2 * wcslen( seq ) * sizeof(*in) );
|
in = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 2 * lstrlen( seq ) * sizeof(*in) );
|
||||||
if (in == NULL)
|
if (in == NULL)
|
||||||
return;
|
return;
|
||||||
for (len = 0; *seq; len += 2, ++seq)
|
for (len = 0; *seq; len += 2, ++seq)
|
||||||
@ -1028,9 +1030,9 @@ void send_palette_sequence( COLORREF c )
|
|||||||
g = GetGValue( c );
|
g = GetGValue( c );
|
||||||
b = GetBValue( c );
|
b = GetBValue( c );
|
||||||
if ((c & 0x0F0F0F) == ((c >> 4) & 0x0F0F0F))
|
if ((c & 0x0F0F0F) == ((c >> 4) & 0x0F0F0F))
|
||||||
_snwprintf( buf, lenof(buf), L"#%X%X%X", r & 0xF, g & 0xF, b & 0xF );
|
ac_wprintf( buf, "#%X%X%X", r & 0xF, g & 0xF, b & 0xF );
|
||||||
else
|
else
|
||||||
_snwprintf( buf, lenof(buf), L"#%02X%02X%02X", r, g, b );
|
ac_wprintf( buf, "#%2X%2X%2X", r, g, b );
|
||||||
SendSequence( buf );
|
SendSequence( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,7 +1042,7 @@ void init_tabs( int size )
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset( pState->tab_stop, FALSE, MAX_TABS );
|
RtlZeroMemory( pState->tab_stop, MAX_TABS );
|
||||||
for (i = 0; i < MAX_TABS; i += size)
|
for (i = 0; i < MAX_TABS; i += size)
|
||||||
pState->tab_stop[i] = TRUE;
|
pState->tab_stop[i] = TRUE;
|
||||||
pState->tabs = TRUE;
|
pState->tabs = TRUE;
|
||||||
@ -1130,12 +1132,12 @@ void Reset( BOOL hard )
|
|||||||
csbix.cbSize = sizeof(csbix);
|
csbix.cbSize = sizeof(csbix);
|
||||||
if (GetConsoleScreenBufferInfoX( hConOut, &csbix ))
|
if (GetConsoleScreenBufferInfoX( hConOut, &csbix ))
|
||||||
{
|
{
|
||||||
memcpy( csbix.ColorTable, pState->o_palette, sizeof(csbix.ColorTable) );
|
arrcpy( csbix.ColorTable, pState->o_palette );
|
||||||
++csbix.srWindow.Right;
|
++csbix.srWindow.Right;
|
||||||
++csbix.srWindow.Bottom;
|
++csbix.srWindow.Bottom;
|
||||||
SetConsoleScreenBufferInfoX( hConOut, &csbix );
|
SetConsoleScreenBufferInfoX( hConOut, &csbix );
|
||||||
}
|
}
|
||||||
memcpy( pState->x_palette, xterm_palette, sizeof(xterm_palette) );
|
arrcpy( pState->x_palette, xterm_palette );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1370,7 +1372,9 @@ void InterpretEscSeq( void )
|
|||||||
int a;
|
int a;
|
||||||
*def = '7'; def[1] = '\0';
|
*def = '7'; def[1] = '\0';
|
||||||
GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) );
|
GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) );
|
||||||
a = wcstol( def, NULL, 16 );
|
a = ac_wcstol( def, NULL, 16 );
|
||||||
|
if (a == 0)
|
||||||
|
a = (*def == '-') ? -7 : 7;
|
||||||
pState->sgr.reverse = FALSE;
|
pState->sgr.reverse = FALSE;
|
||||||
if (a < 0)
|
if (a < 0)
|
||||||
{
|
{
|
||||||
@ -1696,7 +1700,7 @@ void InterpretEscSeq( void )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 3: // ESC[3g Clear all tabs
|
case 3: // ESC[3g Clear all tabs
|
||||||
memset( pState->tab_stop, FALSE, MAX_TABS );
|
RtlZeroMemory( pState->tab_stop, MAX_TABS );
|
||||||
pState->tabs = TRUE;
|
pState->tabs = TRUE;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1775,9 +1779,9 @@ void InterpretEscSeq( void )
|
|||||||
case 6: // ESC[6n Report cursor position
|
case 6: // ESC[6n Report cursor position
|
||||||
{
|
{
|
||||||
TCHAR buf[32];
|
TCHAR buf[32];
|
||||||
_snwprintf( buf, lenof(buf), L"\33[%d;%d%sR",
|
ac_wprintf( buf, "\33[%d;%d%cR",
|
||||||
CUR.Y - top + 1, CUR.X + 1,
|
CUR.Y - top + 1, CUR.X + 1,
|
||||||
(suffix2 == '+') ? L"+" : L"" );
|
(suffix2 == '+') ? '+' : '\0' );
|
||||||
SendSequence( buf );
|
SendSequence( buf );
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1904,7 +1908,7 @@ void InterpretEscSeq( void )
|
|||||||
BOOL started = FALSE;
|
BOOL started = FALSE;
|
||||||
for (beg = Pt_arg;; beg = end + 1)
|
for (beg = Pt_arg;; beg = end + 1)
|
||||||
{
|
{
|
||||||
i = (int)wcstoul( beg, &end, 10 );
|
i = (int)ac_wcstoul( beg, &end, 10 );
|
||||||
if (end == beg || (*end != ';' && *end != '\0') || i >= 256)
|
if (end == beg || (*end != ';' && *end != '\0') || i >= 256)
|
||||||
break;
|
break;
|
||||||
if (end[2] == ';' || end[2] == '\0')
|
if (end[2] == ';' || end[2] == '\0')
|
||||||
@ -1957,7 +1961,7 @@ void InterpretEscSeq( void )
|
|||||||
if (*beg == '#')
|
if (*beg == '#')
|
||||||
{
|
{
|
||||||
valid = TRUE;
|
valid = TRUE;
|
||||||
c = (DWORD)wcstoul( ++beg, &end, 16 );
|
c = (DWORD)ac_wcstoul( ++beg, &end, 16 );
|
||||||
if (end - beg == 3)
|
if (end - beg == 3)
|
||||||
{
|
{
|
||||||
r = (BYTE)(c >> 8);
|
r = (BYTE)(c >> 8);
|
||||||
@ -1976,18 +1980,18 @@ void InterpretEscSeq( void )
|
|||||||
else
|
else
|
||||||
valid = FALSE;
|
valid = FALSE;
|
||||||
}
|
}
|
||||||
else if (wcsncmp( beg, L"rgb:", 4 ) == 0)
|
else if (memcmp( beg, L"rgb:", 8 ) == 0)
|
||||||
{
|
{
|
||||||
valid = FALSE;
|
valid = FALSE;
|
||||||
c = (DWORD)wcstoul( beg += 4, &end, 16 );
|
c = (DWORD)ac_wcstoul( beg += 4, &end, 16 );
|
||||||
if (*end == '/' && (end - beg == 2 || end - beg == 4))
|
if (*end == '/' && (end - beg == 2 || end - beg == 4))
|
||||||
{
|
{
|
||||||
r = (BYTE)(end - beg == 2 ? c : c >> 8);
|
r = (BYTE)(end - beg == 2 ? c : c >> 8);
|
||||||
c = (DWORD)wcstoul( beg = end + 1, &end, 16 );
|
c = (DWORD)ac_wcstoul( beg = end + 1, &end, 16 );
|
||||||
if (*end == '/' && (end - beg == 2 || end - beg == 4))
|
if (*end == '/' && (end - beg == 2 || end - beg == 4))
|
||||||
{
|
{
|
||||||
g = (BYTE)(end - beg == 2 ? c : c >> 8);
|
g = (BYTE)(end - beg == 2 ? c : c >> 8);
|
||||||
c = (DWORD)wcstoul( beg = end + 1, &end, 16 );
|
c = (DWORD)ac_wcstoul( beg = end + 1, &end, 16 );
|
||||||
if ((*end == ',' || *end == ';' || *end == '\0') &&
|
if ((*end == ',' || *end == ';' || *end == '\0') &&
|
||||||
(end - beg == 2 || end - beg == 4))
|
(end - beg == 2 || end - beg == 4))
|
||||||
{
|
{
|
||||||
@ -2000,15 +2004,15 @@ void InterpretEscSeq( void )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
valid = FALSE;
|
valid = FALSE;
|
||||||
c = (DWORD)wcstoul( beg, &end, 10 );
|
c = (DWORD)ac_wcstoul( beg, &end, 10 );
|
||||||
if (*end == ',' && c < 256)
|
if (*end == ',' && c < 256)
|
||||||
{
|
{
|
||||||
r = (BYTE)c;
|
r = (BYTE)c;
|
||||||
c = (DWORD)wcstoul( end + 1, &end, 10 );
|
c = (DWORD)ac_wcstoul( end + 1, &end, 10 );
|
||||||
if (*end == ',' && c < 256)
|
if (*end == ',' && c < 256)
|
||||||
{
|
{
|
||||||
g = (BYTE)c;
|
g = (BYTE)c;
|
||||||
c = (DWORD)wcstoul( end + 1, &end, 10 );
|
c = (DWORD)ac_wcstoul( end + 1, &end, 10 );
|
||||||
if ((*end == ',' || *end == ';' || *end == '\0') && c < 256)
|
if ((*end == ',' || *end == ';' || *end == '\0') && c < 256)
|
||||||
{
|
{
|
||||||
b = (BYTE)c;
|
b = (BYTE)c;
|
||||||
@ -2043,15 +2047,15 @@ void InterpretEscSeq( void )
|
|||||||
// Reset each index, or the entire palette.
|
// Reset each index, or the entire palette.
|
||||||
if (Pt_len == 0)
|
if (Pt_len == 0)
|
||||||
{
|
{
|
||||||
memcpy(csbix.ColorTable, pState->o_palette, sizeof(csbix.ColorTable));
|
arrcpy( csbix.ColorTable, pState->o_palette );
|
||||||
memcpy( pState->x_palette, xterm_palette, sizeof(xterm_palette) );
|
arrcpy( pState->x_palette, xterm_palette );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPTSTR beg, end;
|
LPTSTR beg, end;
|
||||||
for (beg = Pt_arg;; beg = end + 1)
|
for (beg = Pt_arg;; beg = end + 1)
|
||||||
{
|
{
|
||||||
i = (int)wcstoul( beg, &end, 10 );
|
i = (int)ac_wcstoul( beg, &end, 10 );
|
||||||
if (end == beg || (*end != ';' && *end != '\0') || i >= 256)
|
if (end == beg || (*end != ';' && *end != '\0') || i >= 256)
|
||||||
break;
|
break;
|
||||||
if (i < 16)
|
if (i < 16)
|
||||||
@ -2575,12 +2579,13 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
// - Jeffrey Richter ~ Programming Applications for Microsoft Windows 4th ed.
|
// - Jeffrey Richter ~ Programming Applications for Microsoft Windows 4th ed.
|
||||||
|
|
||||||
const char APIKernel[] = "kernel32.dll";
|
const char APIKernel[] = "kernel32.dll";
|
||||||
const char APIConsole[] = "API-MS-Win-Core-Console-";
|
const char APIcore[] = "api-ms-win-core-";
|
||||||
const char APIProcessThreads[] = "API-MS-Win-Core-ProcessThreads-";
|
const char APIConsole[] = "console-";
|
||||||
const char APIProcessEnvironment[] = "API-MS-Win-Core-ProcessEnvironment-";
|
const char APIProcessThreads[] = "processthreads-";
|
||||||
const char APILibraryLoader[] = "API-MS-Win-Core-LibraryLoader-";
|
const char APIProcessEnvironment[] = "processenvironment-";
|
||||||
const char APIFile[] = "API-MS-Win-Core-File-";
|
const char APILibraryLoader[] = "libraryloader-";
|
||||||
const char APIHandle[] = "API-MS-Win-Core-Handle-";
|
const char APIFile[] = "file-";
|
||||||
|
const char APIHandle[] = "handle-";
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -2686,15 +2691,20 @@ BOOL HookAPIOneMod(
|
|||||||
// for the module whose name matches the pszFunctionModule parameter.
|
// for the module whose name matches the pszFunctionModule parameter.
|
||||||
for (; pImportDesc->Name; pImportDesc++)
|
for (; pImportDesc->Name; pImportDesc++)
|
||||||
{
|
{
|
||||||
BOOL kernel = TRUE;
|
BOOL kernel = EOF;
|
||||||
PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );
|
PSTR pszModName = MakeVA( PSTR, pImportDesc->Name );
|
||||||
if (_strnicmp( pszModName, APIKernel, 8 ) != 0 ||
|
if (ac_strnicmp( pszModName, APIKernel, 8 ) == 0 &&
|
||||||
(_stricmp( pszModName+8, APIKernel+8 ) != 0 && pszModName[8] != '\0'))
|
(pszModName[8] == '\0' ||
|
||||||
|
ac_strnicmp( pszModName+8, APIKernel+8, 5 ) == 0))
|
||||||
|
{
|
||||||
|
kernel = TRUE;
|
||||||
|
}
|
||||||
|
else if (ac_strnicmp( pszModName, APIcore, 16 ) == 0)
|
||||||
{
|
{
|
||||||
PAPI_DATA lib;
|
PAPI_DATA lib;
|
||||||
for (lib = APIs; lib->name; ++lib)
|
for (lib = APIs; lib->name; ++lib)
|
||||||
{
|
{
|
||||||
if (_strnicmp( pszModName, lib->name, lib->len ) == 0)
|
if (ac_strnicmp( pszModName+16, lib->name, lib->len ) == 0)
|
||||||
{
|
{
|
||||||
if (lib->base == NULL)
|
if (lib->base == NULL)
|
||||||
{
|
{
|
||||||
@ -2703,17 +2713,17 @@ BOOL HookAPIOneMod(
|
|||||||
if (hook->lib == lib->name)
|
if (hook->lib == lib->name)
|
||||||
hook->apifunc = GetProcAddress( lib->base, hook->name );
|
hook->apifunc = GetProcAddress( lib->base, hook->name );
|
||||||
}
|
}
|
||||||
|
kernel = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lib->name == NULL)
|
}
|
||||||
|
if (kernel == EOF)
|
||||||
{
|
{
|
||||||
if (log_level & 16)
|
if (log_level & 16)
|
||||||
DEBUGSTR( 2, " %s%s %s", sp, zIgnoring, pszModName );
|
DEBUGSTR( 2, " %s%s %s", sp, zIgnoring, pszModName );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
kernel = FALSE;
|
|
||||||
}
|
|
||||||
if (log_level & 16)
|
if (log_level & 16)
|
||||||
DEBUGSTR( 2, " %s%s %s", sp, zScanning, pszModName );
|
DEBUGSTR( 2, " %s%s %s", sp, zScanning, pszModName );
|
||||||
|
|
||||||
@ -2871,8 +2881,6 @@ BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore, BOOL indent )
|
|||||||
static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
||||||
BOOL wide, LPCVOID lpApp, LPCVOID lpCmd )
|
BOOL wide, LPCVOID lpApp, LPCVOID lpCmd )
|
||||||
{
|
{
|
||||||
app[MAX_DEV_PATH-1] = '\0';
|
|
||||||
|
|
||||||
if (lpApp == NULL)
|
if (lpApp == NULL)
|
||||||
{
|
{
|
||||||
typedef DWORD (WINAPI *PGPIFNW)( HANDLE, LPTSTR, DWORD );
|
typedef DWORD (WINAPI *PGPIFNW)( HANDLE, LPTSTR, DWORD );
|
||||||
@ -2905,7 +2913,7 @@ static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
|||||||
term = L"\"";
|
term = L"\"";
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
wcsncpy( app, pos, MAX_DEV_PATH-1 );
|
lstrcpyn( app, pos, MAX_DEV_PATH );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2916,13 +2924,13 @@ static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
|||||||
term = L"\"";
|
term = L"\"";
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
MultiByteToWideChar( CP_ACP, 0, pos, -1, app, MAX_DEV_PATH-1 );
|
MultiByteToWideChar( CP_ACP, 0, pos, -1, app, MAX_DEV_PATH );
|
||||||
}
|
}
|
||||||
// CreateProcess only works with surrounding quotes ('"a name"' works,
|
// CreateProcess only works with surrounding quotes ('"a name"' works,
|
||||||
// but 'a" "name' fails), so that's all I'll test, too. However, it also
|
// 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
|
// tests for a file at each separator ('a name' tries "a.exe" before
|
||||||
// "a name.exe") which I won't do.
|
// "a name.exe") which I won't do.
|
||||||
name = wcspbrk( app, term );
|
name = ac_wcspbrk( app, term );
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
*name = '\0';
|
*name = '\0';
|
||||||
}
|
}
|
||||||
@ -2930,9 +2938,9 @@ static LPTSTR get_program( LPTSTR app, HANDLE hProcess,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wide)
|
if (wide)
|
||||||
wcsncpy( app, lpApp, MAX_DEV_PATH-1 );
|
lstrcpyn( app, lpApp, MAX_DEV_PATH );
|
||||||
else
|
else
|
||||||
MultiByteToWideChar( CP_ACP, 0, lpApp, -1, app, MAX_DEV_PATH-1 );
|
MultiByteToWideChar( CP_ACP, 0, lpApp, -1, app, MAX_DEV_PATH );
|
||||||
}
|
}
|
||||||
return get_program_name( app );
|
return get_program_name( app );
|
||||||
}
|
}
|
||||||
@ -2994,8 +3002,8 @@ void Inject( DWORD dwCreationFlags, LPPROCESS_INFORMATION lpi,
|
|||||||
TCHAR args[64];
|
TCHAR args[64];
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
wcscpy( DllNameType, L"CON.exe" );
|
memcpy( DllNameType, L"CON.exe", 16 );
|
||||||
_snwprintf( args, lenof(args), L"ansicon -P%lu", child_pi->dwProcessId );
|
ac_wprintf( args, "ansicon -P%u", child_pi->dwProcessId );
|
||||||
ZeroMemory( &si, sizeof(si) );
|
ZeroMemory( &si, sizeof(si) );
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
if (CreateProcess( DllName, args, NULL, NULL, FALSE, 0, NULL, NULL,
|
if (CreateProcess( DllName, args, NULL, NULL, FALSE, 0, NULL, NULL,
|
||||||
@ -3007,7 +3015,7 @@ void Inject( DWORD dwCreationFlags, LPPROCESS_INFORMATION lpi,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
DEBUGSTR( 1, "Could not execute %\"S (%u)", DllName, GetLastError() );
|
DEBUGSTR( 1, "Could not execute %\"S (%u)", DllName, GetLastError() );
|
||||||
wcscpy( DllNameType, L"32.dll" );
|
memcpy( DllNameType, L"32.dll", 14 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -3413,7 +3421,7 @@ WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
|
|||||||
if (mb_size <= 4 && mb_size > len - pos)
|
if (mb_size <= 4 && mb_size > len - pos)
|
||||||
{
|
{
|
||||||
mb_len = len - pos;
|
mb_len = len - pos;
|
||||||
memcpy( mb, aBuf + pos, mb_len );
|
RtlMoveMemory( mb, aBuf + pos, mb_len );
|
||||||
len = pos;
|
len = pos;
|
||||||
if (log_level & 4)
|
if (log_level & 4)
|
||||||
{
|
{
|
||||||
@ -3569,11 +3577,14 @@ WINAPI MyCreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess,
|
|||||||
{
|
{
|
||||||
if (dwDesiredAccess == GENERIC_WRITE)
|
if (dwDesiredAccess == GENERIC_WRITE)
|
||||||
{
|
{
|
||||||
if (_stricmp( lpFileName, "con" ) == 0)
|
PDWORD con = (PDWORD)lpFileName;
|
||||||
|
if ((con[0] | 0x202020) == 'noc' ||
|
||||||
|
((con[0] | 0x20202020) == 'onoc' && (con[1] | 0x2020) == '$tu'))
|
||||||
|
{
|
||||||
lpFileName = "CONOUT$";
|
lpFileName = "CONOUT$";
|
||||||
if (_stricmp( lpFileName, "CONOUT$" ) == 0)
|
|
||||||
dwDesiredAccess |= GENERIC_READ;
|
dwDesiredAccess |= GENERIC_READ;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CreateFileA( lpFileName, dwDesiredAccess, dwShareMode,
|
return CreateFileA( lpFileName, dwDesiredAccess, dwShareMode,
|
||||||
lpSecurityAttributes, dwCreationDisposition,
|
lpSecurityAttributes, dwCreationDisposition,
|
||||||
dwFlagsAndAttributes, hTemplateFile );
|
dwFlagsAndAttributes, hTemplateFile );
|
||||||
@ -3588,11 +3599,23 @@ WINAPI MyCreateFileW( LPCWSTR lpFileName, DWORD dwDesiredAccess,
|
|||||||
{
|
{
|
||||||
if (dwDesiredAccess == GENERIC_WRITE)
|
if (dwDesiredAccess == GENERIC_WRITE)
|
||||||
{
|
{
|
||||||
if (_wcsicmp( lpFileName, L"con" ) == 0)
|
#ifdef _WIN64
|
||||||
|
__int64* con = (__int64*)lpFileName;
|
||||||
|
if ((con[0] | 0x2000200020) == 0x6E006F0063/*L'noc'*/ ||
|
||||||
|
((con[0] | 0x20002000200020) == 0x6F006E006F0063/*L'onoc'*/ &&
|
||||||
|
(con[1] | 0x200020) == 0x2400740075/*L'$tu'*/))
|
||||||
|
#else
|
||||||
|
PDWORD con = (PDWORD)lpFileName;
|
||||||
|
if ((con[0] | 0x200020) == 0x6F0063/*L'oc'*/ && ((con[1] | 0x20) == 'n' ||
|
||||||
|
((con[1] | 0x200020) == 0x6F006E/*L'on'*/ &&
|
||||||
|
(con[2] | 0x200020) == 0x740075/*L'tu'*/ &&
|
||||||
|
(con[3] == '$'))))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
lpFileName = L"CONOUT$";
|
lpFileName = L"CONOUT$";
|
||||||
if (_wcsicmp( lpFileName, L"CONOUT$" ) == 0)
|
|
||||||
dwDesiredAccess |= GENERIC_READ;
|
dwDesiredAccess |= GENERIC_READ;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CreateFileW( lpFileName, dwDesiredAccess, dwShareMode,
|
return CreateFileW( lpFileName, dwDesiredAccess, dwShareMode,
|
||||||
lpSecurityAttributes, dwCreationDisposition,
|
lpSecurityAttributes, dwCreationDisposition,
|
||||||
dwFlagsAndAttributes, hTemplateFile );
|
dwFlagsAndAttributes, hTemplateFile );
|
||||||
@ -3708,7 +3731,7 @@ void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )
|
|||||||
pcsbi = &csbi;
|
pcsbi = &csbi;
|
||||||
}
|
}
|
||||||
|
|
||||||
_snwprintf( buf, lenof(buf), L"%dx%d (%dx%d)",
|
ac_wprintf( buf, "%dx%d (%dx%d)",
|
||||||
pcsbi->dwSize.X, pcsbi->dwSize.Y,
|
pcsbi->dwSize.X, pcsbi->dwSize.Y,
|
||||||
pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1,
|
pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1,
|
||||||
pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 );
|
pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 );
|
||||||
@ -3718,7 +3741,7 @@ void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi )
|
|||||||
DWORD
|
DWORD
|
||||||
WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
||||||
{
|
{
|
||||||
if (_stricmp( lpName, "ANSICON_VER" ) == 0)
|
if (lstrcmpiA( lpName, "ANSICON_VER" ) == 0)
|
||||||
{
|
{
|
||||||
if (nSize < sizeof(PVEREA))
|
if (nSize < sizeof(PVEREA))
|
||||||
return sizeof(PVEREA);
|
return sizeof(PVEREA);
|
||||||
@ -3726,7 +3749,7 @@ WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
|||||||
return sizeof(PVEREA) - 1;
|
return sizeof(PVEREA) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stricmp( lpName, "CLICOLOR" ) == 0)
|
if (lstrcmpiA( lpName, "CLICOLOR" ) == 0)
|
||||||
{
|
{
|
||||||
if (nSize < 2)
|
if (nSize < 2)
|
||||||
return 2;
|
return 2;
|
||||||
@ -3735,7 +3758,7 @@ WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stricmp( lpName, "ANSICON" ) == 0)
|
if (lstrcmpiA( lpName, "ANSICON" ) == 0)
|
||||||
set_ansicon( NULL );
|
set_ansicon( NULL );
|
||||||
|
|
||||||
return GetEnvironmentVariableA( lpName, lpBuffer, nSize );
|
return GetEnvironmentVariableA( lpName, lpBuffer, nSize );
|
||||||
@ -3744,7 +3767,7 @@ WINAPI MyGetEnvironmentVariableA( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize )
|
|||||||
DWORD
|
DWORD
|
||||||
WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
|
WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
|
||||||
{
|
{
|
||||||
if (_wcsicmp( lpName, L"ANSICON_VER" ) == 0)
|
if (lstrcmpi( lpName, L"ANSICON_VER" ) == 0)
|
||||||
{
|
{
|
||||||
if (nSize < lenof(PVERE))
|
if (nSize < lenof(PVERE))
|
||||||
return lenof(PVERE);
|
return lenof(PVERE);
|
||||||
@ -3752,7 +3775,7 @@ WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
|
|||||||
return lenof(PVERE) - 1;
|
return lenof(PVERE) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_wcsicmp( lpName, L"CLICOLOR" ) == 0)
|
if (lstrcmpi( lpName, L"CLICOLOR" ) == 0)
|
||||||
{
|
{
|
||||||
if (nSize < 2)
|
if (nSize < 2)
|
||||||
return 2;
|
return 2;
|
||||||
@ -3761,7 +3784,7 @@ WINAPI MyGetEnvironmentVariableW( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_wcsicmp( lpName, L"ANSICON" ) == 0)
|
if (lstrcmpi( lpName, L"ANSICON" ) == 0)
|
||||||
set_ansicon( NULL );
|
set_ansicon( NULL );
|
||||||
|
|
||||||
return GetEnvironmentVariableW( lpName, lpBuffer, nSize );
|
return GetEnvironmentVariableW( lpName, lpBuffer, nSize );
|
||||||
@ -3832,12 +3855,14 @@ void OriginalAttr( PVOID lpReserved )
|
|||||||
{
|
{
|
||||||
HANDLE hConOut;
|
HANDLE hConOut;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO Info;
|
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||||
|
PIMAGE_DOS_HEADER pDosHeader;
|
||||||
|
PIMAGE_NT_HEADERS pNTHeader;
|
||||||
|
BOOL org;
|
||||||
|
|
||||||
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
get_state();
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
NULL, OPEN_EXISTING, 0, NULL );
|
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle( NULL );
|
||||||
if (!GetConsoleScreenBufferInfo( hConOut, &Info ))
|
pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );
|
||||||
ATTR = 7;
|
|
||||||
|
|
||||||
// If we were loaded dynamically, remember the current attributes to restore
|
// If we were loaded dynamically, remember the current attributes to restore
|
||||||
// upon unloading. However, if we're the 64-bit DLL, but the image is 32-
|
// upon unloading. However, if we're the 64-bit DLL, but the image is 32-
|
||||||
@ -3845,27 +3870,35 @@ void OriginalAttr( PVOID lpReserved )
|
|||||||
// be dynamic due to lack of the IAT.
|
// be dynamic due to lack of the IAT.
|
||||||
if (lpReserved == NULL)
|
if (lpReserved == NULL)
|
||||||
{
|
{
|
||||||
BOOL dynamic = TRUE;
|
org = TRUE;
|
||||||
PIMAGE_DOS_HEADER pDosHeader;
|
|
||||||
PIMAGE_NT_HEADERS pNTHeader;
|
|
||||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle( NULL );
|
|
||||||
pNTHeader = MakeVA( PIMAGE_NT_HEADERS, pDosHeader->e_lfanew );
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if (pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
if (pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
||||||
dynamic = FALSE;
|
org = FALSE;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (pNTHeader->DATADIRS <= IMAGE_DIRECTORY_ENTRY_IAT &&
|
if (pNTHeader->DATADIRS <= IMAGE_DIRECTORY_ENTRY_IAT &&
|
||||||
get_os_version() >= 0x602)
|
get_os_version() >= 0x602)
|
||||||
dynamic = FALSE;
|
org = FALSE;
|
||||||
if (dynamic)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We also want to restore the original attributes for ansicon.exe.
|
||||||
|
org = (pNTHeader->OptionalHeader.MajorImageVersion == 20033 && // 'AN'
|
||||||
|
pNTHeader->OptionalHeader.MinorImageVersion == 18771); // 'SI'
|
||||||
|
}
|
||||||
|
if (org)
|
||||||
|
{
|
||||||
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, 0, NULL );
|
||||||
|
if (!GetConsoleScreenBufferInfo( hConOut, &Info ))
|
||||||
|
ATTR = 7;
|
||||||
orgattr = ATTR;
|
orgattr = ATTR;
|
||||||
|
orgsgr = pState->sgr;
|
||||||
GetConsoleMode( hConOut, &orgmode );
|
GetConsoleMode( hConOut, &orgmode );
|
||||||
GetConsoleCursorInfo( hConOut, &orgcci );
|
GetConsoleCursorInfo( hConOut, &orgcci );
|
||||||
}
|
|
||||||
CloseHandle( hConOut );
|
CloseHandle( hConOut );
|
||||||
|
}
|
||||||
get_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3888,8 +3921,6 @@ DWORD WINAPI exit_thread( LPVOID lpParameter )
|
|||||||
// and terminated.
|
// and terminated.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Need to export something for static loading to work, this is as good as any.
|
|
||||||
__declspec(dllexport)
|
|
||||||
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
||||||
{
|
{
|
||||||
BOOL bResult = TRUE;
|
BOOL bResult = TRUE;
|
||||||
@ -3901,7 +3932,7 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
|||||||
|
|
||||||
if (dwReason == DLL_PROCESS_ATTACH)
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
hHeap = HeapCreate( 0, 0, 128 * 1024 );
|
hHeap = HeapCreate( 0, 0, 256 * 1024 );
|
||||||
hKernel = GetModuleHandleA( APIKernel );
|
hKernel = GetModuleHandleA( APIKernel );
|
||||||
GetConsoleScreenBufferInfoX = (PHCSBIX)GetProcAddress(
|
GetConsoleScreenBufferInfoX = (PHCSBIX)GetProcAddress(
|
||||||
hKernel, "GetConsoleScreenBufferInfoEx" );
|
hKernel, "GetConsoleScreenBufferInfoEx" );
|
||||||
@ -3914,7 +3945,7 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
|||||||
|
|
||||||
*logstr = '\0';
|
*logstr = '\0';
|
||||||
GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
|
GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
|
||||||
log_level = _wtoi( logstr );
|
log_level = ac_wtoi( logstr );
|
||||||
prog = get_program_name( NULL );
|
prog = get_program_name( NULL );
|
||||||
#if defined(_WIN64) || defined(W32ON64)
|
#if defined(_WIN64) || defined(W32ON64)
|
||||||
DllNameType = DllName - 6 +
|
DllNameType = DllName - 6 +
|
||||||
@ -3982,6 +4013,7 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
|||||||
SetConsoleMode( hConOut, orgmode );
|
SetConsoleMode( hConOut, orgmode );
|
||||||
SetConsoleCursorInfo( hConOut, &orgcci );
|
SetConsoleCursorInfo( hConOut, &orgcci );
|
||||||
CloseHandle( hConOut );
|
CloseHandle( hConOut );
|
||||||
|
pState->sgr = orgsgr;
|
||||||
}
|
}
|
||||||
if (hMap != NULL)
|
if (hMap != NULL)
|
||||||
{
|
{
|
||||||
|
150
ansicon.c
150
ansicon.c
@ -89,9 +89,12 @@
|
|||||||
v1.80, 28 October & 30 November, 2017:
|
v1.80, 28 October & 30 November, 2017:
|
||||||
write newline with _putws, not putwchar (fixes redirecting to CON);
|
write newline with _putws, not putwchar (fixes redirecting to CON);
|
||||||
use -pu to unload from the parent.
|
use -pu to unload from the parent.
|
||||||
|
|
||||||
|
v1.84, 7 May, 2018:
|
||||||
|
import the DLL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PDATE L"4 May, 2018"
|
#define PDATE L"7 May, 2018"
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -128,25 +131,6 @@ BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR );
|
|||||||
|
|
||||||
|
|
||||||
static HANDLE hConOut;
|
static HANDLE hConOut;
|
||||||
static WORD wAttr;
|
|
||||||
|
|
||||||
void get_original_attr( void )
|
|
||||||
{
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
||||||
|
|
||||||
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
NULL, OPEN_EXISTING, 0, 0 );
|
|
||||||
GetConsoleScreenBufferInfo( hConOut, &csbi );
|
|
||||||
wAttr = csbi.wAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void set_original_attr( void )
|
|
||||||
{
|
|
||||||
SetConsoleTextAttribute( hConOut, wAttr );
|
|
||||||
CloseHandle( hConOut );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The fputws function in MSVCRT.DLL (Windows 7 x64) is broken for Unicode
|
// The fputws function in MSVCRT.DLL (Windows 7 x64) is broken for Unicode
|
||||||
@ -172,53 +156,6 @@ int my_fputws( const wchar_t* s, FILE* f )
|
|||||||
#define _putws( s ) my_fputws( s L"\n", stdout )
|
#define _putws( s ) my_fputws( s L"\n", stdout )
|
||||||
|
|
||||||
|
|
||||||
HANDLE hHeap;
|
|
||||||
#if defined(_WIN64)
|
|
||||||
LPTSTR DllNameType;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Find the name of the DLL and inject it.
|
|
||||||
BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app )
|
|
||||||
{
|
|
||||||
DWORD len;
|
|
||||||
int type;
|
|
||||||
PBYTE base;
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
if (app != NULL)
|
|
||||||
#endif
|
|
||||||
DEBUGSTR( 1, "%S (%u)", app, ppi->dwProcessId );
|
|
||||||
type = ProcessType( ppi, &base, gui );
|
|
||||||
if (type <= 0)
|
|
||||||
{
|
|
||||||
if (type == 0)
|
|
||||||
fwprintf( stderr, L"ANSICON: %s: unsupported process.\n", app );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (DWORD)(prog - prog_path);
|
|
||||||
memcpy( DllName, prog_path, TSIZE(len) );
|
|
||||||
#ifdef _WIN64
|
|
||||||
_snwprintf( DllName + len, MAX_PATH-1 - len,
|
|
||||||
L"ANSI%d.dll", (type == 48) ? 64 : type );
|
|
||||||
DllNameType = DllName + len + 4;
|
|
||||||
set_ansi_dll();
|
|
||||||
if (type == 64)
|
|
||||||
InjectDLL( ppi, base );
|
|
||||||
else if (type == 32)
|
|
||||||
InjectDLL32( ppi, base );
|
|
||||||
else // (type == 48)
|
|
||||||
RemoteLoad64( ppi );
|
|
||||||
#else
|
|
||||||
wcscpy( DllName + len, L"ANSI32.dll" );
|
|
||||||
set_ansi_dll();
|
|
||||||
InjectDLL( ppi, base );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Use CreateRemoteThread to (un)load our DLL in the target process.
|
// Use CreateRemoteThread to (un)load our DLL in the target process.
|
||||||
void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
||||||
{
|
{
|
||||||
@ -227,7 +164,6 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
PBYTE proc;
|
PBYTE proc;
|
||||||
DWORD rva;
|
DWORD rva;
|
||||||
BOOL fOk;
|
BOOL fOk;
|
||||||
DWORD len;
|
|
||||||
LPVOID param;
|
LPVOID param;
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
DWORD ticks;
|
DWORD ticks;
|
||||||
@ -236,7 +172,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
int type;
|
int type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGSTR( 1, "%S (%u)", app, ppi->dwProcessId );
|
DEBUGSTR( 1, "Parent = %S (%u)", app, ppi->dwProcessId );
|
||||||
|
|
||||||
// Find the base address of kernel32.dll.
|
// Find the base address of kernel32.dll.
|
||||||
ticks = GetTickCount();
|
ticks = GetTickCount();
|
||||||
@ -266,11 +202,13 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
proc = param = NULL;
|
proc = param = NULL;
|
||||||
len = (DWORD)(prog - prog_path);
|
|
||||||
memcpy( DllName, prog_path, TSIZE(len) );
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
type = (IsWow64Process( ppi->hProcess, &WOW64 ) && WOW64) ? 32 : 64;
|
type = 64;
|
||||||
_snwprintf( DllName + len, MAX_PATH-1 - len, L"ANSI%d.dll", type );
|
if (IsWow64Process( ppi->hProcess, &WOW64 ) && WOW64)
|
||||||
|
{
|
||||||
|
type = 32;
|
||||||
|
*(PDWORD)DllNameType = 0x320033/*L'23'*/;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
me.dwSize = sizeof(MODULEENTRY32);
|
me.dwSize = sizeof(MODULEENTRY32);
|
||||||
for (fOk = Module32First( hSnap, &me ); fOk; fOk = Module32Next( hSnap, &me ))
|
for (fOk = Module32First( hSnap, &me ); fOk; fOk = Module32Next( hSnap, &me ))
|
||||||
@ -278,17 +216,21 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
if (_wcsicmp( me.szModule, L"kernel32.dll" ) == 0)
|
if (_wcsicmp( me.szModule, L"kernel32.dll" ) == 0)
|
||||||
{
|
{
|
||||||
proc = me.modBaseAddr;
|
proc = me.modBaseAddr;
|
||||||
if (!unload)
|
if (!unload || param)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (unload)
|
else if (unload)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if (_wcsicmp( me.szModule, DllName + len ) == 0)
|
if (_wcsicmp( me.szModule, DllNameType - 4 ) == 0)
|
||||||
#else
|
#else
|
||||||
if (_wcsicmp( me.szModule, L"ANSI32.dll" ) == 0)
|
if (_wcsicmp( me.szModule, L"ANSI32.dll" ) == 0)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
param = me.modBaseAddr;
|
param = me.modBaseAddr;
|
||||||
|
if (proc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CloseHandle( hSnap );
|
CloseHandle( hSnap );
|
||||||
@ -307,7 +249,6 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
rva = GetProcRVA( L"kernel32.dll", (unload) ? "FreeLibrary"
|
rva = GetProcRVA( L"kernel32.dll", (unload) ? "FreeLibrary"
|
||||||
: "LoadLibraryW", type );
|
: "LoadLibraryW", type );
|
||||||
#else
|
#else
|
||||||
wcscpy( DllName + len, L"ANSI32.dll" );
|
|
||||||
rva = GetProcRVA( L"kernel32.dll", unload ? "FreeLibrary" : "LoadLibraryW" );
|
rva = GetProcRVA( L"kernel32.dll", unload ? "FreeLibrary" : "LoadLibraryW" );
|
||||||
#endif
|
#endif
|
||||||
if (rva == 0)
|
if (rva == 0)
|
||||||
@ -316,13 +257,14 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload )
|
|||||||
|
|
||||||
if (!unload)
|
if (!unload)
|
||||||
{
|
{
|
||||||
|
DWORD len = TSIZE((DWORD)wcslen( DllName ) + 1);
|
||||||
param = VirtualAllocEx(ppi->hProcess, NULL, len, MEM_COMMIT,PAGE_READWRITE);
|
param = VirtualAllocEx(ppi->hProcess, NULL, len, MEM_COMMIT,PAGE_READWRITE);
|
||||||
if (param == NULL)
|
if (param == NULL)
|
||||||
{
|
{
|
||||||
DEBUGSTR(1, " Failed to allocate virtual memory (%u)", GetLastError());
|
DEBUGSTR(1, " Failed to allocate virtual memory (%u)", GetLastError());
|
||||||
goto no_go;
|
goto no_go;
|
||||||
}
|
}
|
||||||
WriteProcMem( param, DllName, TSIZE(len + 11) );
|
WriteProcMem( param, DllName, len );
|
||||||
}
|
}
|
||||||
thread = CreateRemoteThread( ppi->hProcess, NULL, 4096,
|
thread = CreateRemoteThread( ppi->hProcess, NULL, 4096,
|
||||||
(LPTHREAD_START_ROUTINE)proc, param, 0, NULL );
|
(LPTHREAD_START_ROUTINE)proc, param, 0, NULL );
|
||||||
@ -346,7 +288,6 @@ int main( void )
|
|||||||
LPTSTR argv, arg, cmd;
|
LPTSTR argv, arg, cmd;
|
||||||
TCHAR buf[4];
|
TCHAR buf[4];
|
||||||
BOOL shell, run, gui;
|
BOOL shell, run, gui;
|
||||||
HMODULE ansi;
|
|
||||||
DWORD len;
|
DWORD len;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
@ -361,7 +302,9 @@ int main( void )
|
|||||||
_setmode( 2, _O_U16TEXT);
|
_setmode( 2, _O_U16TEXT);
|
||||||
|
|
||||||
// Create a console handle and store the current attributes.
|
// Create a console handle and store the current attributes.
|
||||||
get_original_attr();
|
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, 0, 0 );
|
||||||
|
|
||||||
argv = GetCommandLine();
|
argv = GetCommandLine();
|
||||||
len = (DWORD)wcslen( argv ) + 1;
|
len = (DWORD)wcslen( argv ) + 1;
|
||||||
@ -386,9 +329,6 @@ int main( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hHeap = HeapCreate( 0, 0, 65 * 1024 );
|
|
||||||
|
|
||||||
prog = get_program_name( NULL );
|
|
||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
GetEnvironmentVariable( L"ANSICON_LOG", buf, lenof(buf) );
|
GetEnvironmentVariable( L"ANSICON_LOG", buf, lenof(buf) );
|
||||||
log_level = _wtoi( buf );
|
log_level = _wtoi( buf );
|
||||||
@ -405,7 +345,12 @@ int main( void )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Inject( &pi, &gui, NULL );
|
PBYTE base;
|
||||||
|
DEBUGSTR( 1, "64-bit process (%u) started by 32-bit", pi.dwProcessId );
|
||||||
|
if (ProcessType( &pi, &base, NULL ) == 48)
|
||||||
|
RemoteLoad64( &pi );
|
||||||
|
else
|
||||||
|
InjectDLL( &pi, base );
|
||||||
CloseHandle( pi.hProcess );
|
CloseHandle( pi.hProcess );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -456,20 +401,8 @@ int main( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
{
|
SetEnvironmentVariable( L"ANSICON_DEF", arg[2] ? arg + 2 : L"7" );
|
||||||
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, (WORD)a );
|
|
||||||
SetEnvironmentVariable( L"ANSICON_DEF", NULL );
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
@ -494,13 +427,7 @@ arg_out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the default attributes are the current attributes.
|
// Ensure the default attributes are the current attributes.
|
||||||
if (GetEnvironmentVariable( L"ANSICON_DEF", buf, lenof(buf) ) != 0)
|
WriteConsole( hConOut, L"\33[m", 3, &len, NULL );
|
||||||
{
|
|
||||||
int a = wcstol( buf, NULL, 16 );
|
|
||||||
if (a < 0)
|
|
||||||
a = ((-a >> 4) & 15) | ((-a & 15) << 4);
|
|
||||||
SetConsoleTextAttribute( hConOut, (WORD)a );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run)
|
if (run)
|
||||||
{
|
{
|
||||||
@ -518,11 +445,9 @@ arg_out:
|
|||||||
|
|
||||||
ZeroMemory( &si, sizeof(si) );
|
ZeroMemory( &si, sizeof(si) );
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
if (CreateProcess( NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
|
if (CreateProcess( NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ))
|
||||||
NULL, NULL, &si, &pi ))
|
|
||||||
{
|
{
|
||||||
Inject( &pi, &gui, arg );
|
ProcessType( &pi, NULL, &gui );
|
||||||
ResumeThread( pi.hThread );
|
|
||||||
if (!gui)
|
if (!gui)
|
||||||
{
|
{
|
||||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
|
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
|
||||||
@ -540,13 +465,7 @@ arg_out:
|
|||||||
}
|
}
|
||||||
else if (*arg)
|
else if (*arg)
|
||||||
{
|
{
|
||||||
ansi = LoadLibrary( ANSIDLL );
|
if (*arg == 'e' || *arg == 'E')
|
||||||
if (ansi == NULL)
|
|
||||||
{
|
|
||||||
print_error( ANSIDLL );
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
else if (*arg == 'e' || *arg == 'E')
|
|
||||||
{
|
{
|
||||||
cmd += 2;
|
cmd += 2;
|
||||||
if (*cmd == ' ' || *cmd == '\t')
|
if (*cmd == ' ' || *cmd == '\t')
|
||||||
@ -574,11 +493,8 @@ arg_out:
|
|||||||
get_file( arg, &argv, &cmd );
|
get_file( arg, &argv, &cmd );
|
||||||
} while (*arg);
|
} while (*arg);
|
||||||
}
|
}
|
||||||
FreeLibrary( ansi );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_original_attr();
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
ansicon.h
46
ansicon.h
@ -83,34 +83,62 @@ typedef struct IMAGE_COR20_HEADER
|
|||||||
#define VirtProtVar(a, b) VirtualProtectEx( ppi->hProcess, a, sizeof(*(a)), b, &pr )
|
#define VirtProtVar(a, b) VirtualProtectEx( ppi->hProcess, a, sizeof(*(a)), b, &pr )
|
||||||
|
|
||||||
|
|
||||||
int ProcessType( LPPROCESS_INFORMATION, PBYTE*, BOOL* );
|
#ifdef PDATE // i.e. from ansicon.c
|
||||||
|
#define EXTERN __declspec(dllimport) extern
|
||||||
|
#else
|
||||||
|
#define EXTERN __declspec(dllexport) extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN int ProcessType( LPPROCESS_INFORMATION, PBYTE*, BOOL* );
|
||||||
BOOL Wow64Process( HANDLE );
|
BOOL Wow64Process( HANDLE );
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
EXTERN
|
||||||
|
#endif
|
||||||
void InjectDLL( LPPROCESS_INFORMATION, PBYTE );
|
void InjectDLL( LPPROCESS_INFORMATION, PBYTE );
|
||||||
void RemoteLoad32( LPPROCESS_INFORMATION );
|
void RemoteLoad32( LPPROCESS_INFORMATION );
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
void InjectDLL32( LPPROCESS_INFORMATION, PBYTE );
|
void InjectDLL32( LPPROCESS_INFORMATION, PBYTE );
|
||||||
void RemoteLoad64( LPPROCESS_INFORMATION );
|
EXTERN void RemoteLoad64( LPPROCESS_INFORMATION );
|
||||||
DWORD GetProcRVA( LPCTSTR, LPCSTR, int );
|
EXTERN DWORD GetProcRVA( LPCTSTR, LPCSTR, int );
|
||||||
#else
|
#else
|
||||||
DWORD GetProcRVA( LPCTSTR, LPCSTR );
|
EXTERN DWORD GetProcRVA( LPCTSTR, LPCSTR );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern HANDLE hHeap;
|
extern HANDLE hHeap;
|
||||||
|
|
||||||
extern TCHAR prog_path[MAX_PATH];
|
EXTERN TCHAR prog_path[MAX_PATH];
|
||||||
extern LPTSTR prog;
|
extern LPTSTR prog;
|
||||||
LPTSTR get_program_name( LPTSTR );
|
LPTSTR get_program_name( LPTSTR );
|
||||||
|
|
||||||
extern TCHAR DllName[MAX_PATH];
|
EXTERN TCHAR DllName[MAX_PATH];
|
||||||
extern LPTSTR DllNameType;
|
EXTERN LPTSTR DllNameType;
|
||||||
extern char ansi_dll[MAX_PATH];
|
extern char ansi_dll[MAX_PATH];
|
||||||
extern DWORD ansi_len;
|
extern DWORD ansi_len;
|
||||||
extern char* ansi_bits;
|
extern char* ansi_bits;
|
||||||
void set_ansi_dll( void );
|
void set_ansi_dll( void );
|
||||||
DWORD get_os_version( void );
|
DWORD get_os_version( void );
|
||||||
|
|
||||||
extern int log_level;
|
EXTERN int log_level;
|
||||||
void DEBUGSTR( int level, LPCSTR szFormat, ... );
|
EXTERN void DEBUGSTR( int level, LPCSTR szFormat, ... );
|
||||||
|
|
||||||
|
// Replacements for C runtime functions.
|
||||||
|
#undef RtlFillMemory
|
||||||
|
#undef RtlMoveMemory
|
||||||
|
#undef RtlZeroMemory
|
||||||
|
void WINAPI RtlFillMemory( PVOID, SIZE_T, BYTE );
|
||||||
|
void WINAPI RtlMoveMemory( PVOID, const VOID*, SIZE_T );
|
||||||
|
void WINAPI RtlZeroMemory( PVOID, SIZE_T );
|
||||||
|
|
||||||
|
#define arrcpy( dst, src ) RtlMoveMemory( dst, src, sizeof(dst) )
|
||||||
|
|
||||||
|
unsigned long ac_wcstoul( const wchar_t*, wchar_t**, int );
|
||||||
|
int ac_wtoi( const wchar_t* );
|
||||||
|
long ac_wcstol( const wchar_t*, wchar_t**, int );
|
||||||
|
wchar_t* ac_wcspbrk( const wchar_t*, const wchar_t* );
|
||||||
|
wchar_t* ac_wcsrchr( const wchar_t*, wchar_t );
|
||||||
|
int ac_strnicmp( const char*, const char*, size_t );
|
||||||
|
int ac_sprintf( char*, const char*, ... );
|
||||||
|
int ac_wprintf( wchar_t*, const char*, ... );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
8
injdll.c
8
injdll.c
@ -117,7 +117,7 @@ void InjectDLL( LPPROCESS_INFORMATION ppi, PBYTE pBase )
|
|||||||
ip.pL = (PLONG_PTR)pImports;
|
ip.pL = (PLONG_PTR)pImports;
|
||||||
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
|
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
|
||||||
*ip.pL++ = 0;
|
*ip.pL++ = 0;
|
||||||
memcpy( ip.pB, ansi_dll, ansi_len );
|
RtlMoveMemory( ip.pB, ansi_dll, ansi_len );
|
||||||
ip.pB += ansi_len;
|
ip.pB += ansi_len;
|
||||||
ip.pI->OriginalFirstThunk = 0;
|
ip.pI->OriginalFirstThunk = 0;
|
||||||
ip.pI->TimeDateStamp = 0;
|
ip.pI->TimeDateStamp = 0;
|
||||||
@ -213,7 +213,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, PBYTE pBase )
|
|||||||
ip.pL = (PLONG)pImports;
|
ip.pL = (PLONG)pImports;
|
||||||
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
|
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
|
||||||
*ip.pL++ = 0;
|
*ip.pL++ = 0;
|
||||||
memcpy( ip.pB, ansi_dll, ansi_len );
|
RtlMoveMemory( ip.pB, ansi_dll, ansi_len );
|
||||||
ip.pB += ansi_len;
|
ip.pB += ansi_len;
|
||||||
ip.pI->OriginalFirstThunk = 0;
|
ip.pI->OriginalFirstThunk = 0;
|
||||||
ip.pI->TimeDateStamp = 0;
|
ip.pI->TimeDateStamp = 0;
|
||||||
@ -331,7 +331,7 @@ void RemoteLoad64( LPPROCESS_INFORMATION ppi )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (DWORD)TSIZE(wcslen( DllName ) + 1);
|
len = (DWORD)TSIZE(lstrlen( DllName ) + 1);
|
||||||
ip.pB = code;
|
ip.pB = code;
|
||||||
|
|
||||||
*ip.pL++ = ntdll + rLdrLoadDll; // address of LdrLoadDll
|
*ip.pL++ = ntdll + rLdrLoadDll; // address of LdrLoadDll
|
||||||
@ -400,7 +400,7 @@ void RemoteLoad32( LPPROCESS_INFORMATION ppi )
|
|||||||
}
|
}
|
||||||
bMem = PtrToUint( pMem );
|
bMem = PtrToUint( pMem );
|
||||||
|
|
||||||
len = (DWORD)TSIZE(wcslen( DllName ) + 1);
|
len = (DWORD)TSIZE(lstrlen( DllName ) + 1);
|
||||||
ip.pB = code;
|
ip.pB = code;
|
||||||
|
|
||||||
*ip.pS++ = 0x5451; // push ecx esp
|
*ip.pS++ = 0x5451; // push ecx esp
|
||||||
|
64
makefile.vc
64
makefile.vc
@ -22,6 +22,9 @@
|
|||||||
# 30 April, 2018:
|
# 30 April, 2018:
|
||||||
# use undocumented rc option /s to remove its logo;
|
# use undocumented rc option /s to remove its logo;
|
||||||
# use a batch rule (even if this project is too small to make a difference).
|
# use a batch rule (even if this project is too small to make a difference).
|
||||||
|
#
|
||||||
|
# 8 May, 2018:
|
||||||
|
# rc /s only removes the logo as a side-effect; use /nologo when available.
|
||||||
|
|
||||||
#BITS = 32
|
#BITS = 32
|
||||||
#BITS = 64
|
#BITS = 64
|
||||||
@ -39,20 +42,26 @@ DIR = x86
|
|||||||
!ELSE
|
!ELSE
|
||||||
!IF $(BITS) == 64
|
!IF $(BITS) == 64
|
||||||
DIR = x64
|
DIR = x64
|
||||||
RFLAGS = /D_WIN64
|
|
||||||
!ELSE
|
!ELSE
|
||||||
!ERROR BITS should be defined to 32 or 64.
|
!ERROR BITS should be defined to 32 or 64.
|
||||||
!ENDIF
|
!ENDIF
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# This is required for the 2003 Platform SDK, but not for Visual Studio 2010.
|
# Disable security checks, but VC6 & 7 don't have /GS-.
|
||||||
!IF "$(_NMAKE_VER)" == "7.00.8882"
|
!IF "$(_NMAKE_VER)" == "7.00.8882" && $(BITS) == 32
|
||||||
!IF $(BITS) == 64
|
NOSECCHK =
|
||||||
LIBS64 = bufferoverflowu.lib
|
RFLAGS =
|
||||||
# The 2003 Toolkit doesn't have MSVCRT.LIB, but VC98 does.
|
# The 2003 Toolkit doesn't have MSVCRT.LIB, but VC98 does.
|
||||||
!ELSEIF !DEFINED(SHARE) && !DEFINED(MSVCDIR)
|
!IF !DEFINED(SHARE) && !DEFINED(MSVCDIR)
|
||||||
SHARE =
|
SHARE =
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
!ELSE
|
||||||
|
NOSECCHK = /GS-
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# 2008 (SDK v6) and earlier rc do not have /nologo.
|
||||||
|
!IF [cmd /d /c exit /b $(_NMAKE_VER)] <= 9
|
||||||
|
RFLAGS =
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# Link with MSVCRT.LIB by default.
|
# Link with MSVCRT.LIB by default.
|
||||||
@ -63,9 +72,14 @@ SHARE = /MD
|
|||||||
# Manifest tool to embed the manifest required by 2008.
|
# Manifest tool to embed the manifest required by 2008.
|
||||||
MT = mt.exe
|
MT = mt.exe
|
||||||
|
|
||||||
RFLAGS = /s
|
!IFNDEF RFLAGS
|
||||||
CFLAGS = /nologo /W3 /O2 $(SHARE) /D_CRT_SECURE_NO_WARNINGS
|
RFLAGS = /nologo
|
||||||
LIBS = advapi32.lib $(LIBS64)
|
!ENDIF
|
||||||
|
!IF $(BITS) == 64
|
||||||
|
RFLAGS = $(RFLAGS) /D_WIN64
|
||||||
|
!ENDIF
|
||||||
|
CFLAGS = /nologo /W3 /O2 $(NOSECCHK) /D_CRT_SECURE_NO_WARNINGS
|
||||||
|
LIBS = kernel32.lib advapi32.lib
|
||||||
|
|
||||||
# Identify ansicon.exe using "ANSI" as a version number.
|
# Identify ansicon.exe using "ANSI" as a version number.
|
||||||
LINK = /link /version:20033.18771
|
LINK = /link /version:20033.18771
|
||||||
@ -92,14 +106,14 @@ MTmsg = @echo Embedding manifest&
|
|||||||
|
|
||||||
all: ansicon$(BITS)
|
all: ansicon$(BITS)
|
||||||
|
|
||||||
ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64 x64\ANSI32.dll
|
ansicon32: x86 x86\ANSI32.dll x86\ansicon.exe x64 x64\ANSI32.dll
|
||||||
|
|
||||||
ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll
|
ansicon64: x64 x64\ANSI64.dll x64\ansicon.exe
|
||||||
|
|
||||||
x86:
|
x86:
|
||||||
mkdir x86
|
mkdir x86
|
||||||
|
|
||||||
x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res
|
x86\ansicon.exe: x86\ansicon.obj x86\ansi32.lib x86\ansicon.res
|
||||||
$(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LINK) /filealign:512
|
$(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LINK) /filealign:512
|
||||||
!IF "$(_NMAKE_VER)" == "9.00.30729.01"
|
!IF "$(_NMAKE_VER)" == "9.00.30729.01"
|
||||||
$(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;1
|
$(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;1
|
||||||
@ -107,30 +121,23 @@ x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res
|
|||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res
|
x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res
|
||||||
$(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link \
|
$(LDmsg)$(CC) /nologo /LD /Fe$@ $** $(LIBS) /link \
|
||||||
/base:0xAC0000 /filealign:512
|
/base:0xAC0000 /entry:DllMain /filealign:512
|
||||||
!IF "$(_NMAKE_VER)" == "9.00.30729.01"
|
|
||||||
$(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2
|
|
||||||
@del $@.manifest
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
x64:
|
x64:
|
||||||
mkdir x64
|
mkdir x64
|
||||||
|
|
||||||
x64\ansicon.exe: x64\ansicon.obj $(X64OBJS) x64\ansicon.res
|
x64\ansicon.exe: x64\ansicon.obj x64\ansi64.lib x64\ansicon.res
|
||||||
$(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LINK)
|
$(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LINK)
|
||||||
|
|
||||||
x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res
|
x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res
|
||||||
$(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link \
|
$(LDmsg)$(CC) /nologo /LD /Fe$@ $** $(LIBS) /link \
|
||||||
/base:0xAC000000
|
/base:0xAC000000 /entry:DllMain
|
||||||
|
|
||||||
x64\ANSI32.dll: x64\ANSI32.obj $(X6432OBJS) x86\ansi.res
|
x64\ANSI32.dll: x64\ANSI32.obj $(X6432OBJS) x86\ansi.res
|
||||||
$(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link \
|
$(LDmsg)$(CC) /nologo /LD /Fe$@ $** $(LIBS) /link \
|
||||||
/base:0xAC0000 /filealign:512 /largeaddressaware
|
/base:0xAC0000 /entry:DllMain /filealign:512 \
|
||||||
!IF "$(_NMAKE_VER)" == "9.00.30729.01"
|
/largeaddressaware
|
||||||
$(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2
|
|
||||||
@del $@.manifest
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
ansicon.c: ansicon.h version.h
|
ansicon.c: ansicon.h version.h
|
||||||
ansicon.rc: version.h
|
ansicon.rc: version.h
|
||||||
@ -141,6 +148,9 @@ injdll.c: ansicon.h
|
|||||||
proctype.c: ansicon.h
|
proctype.c: ansicon.h
|
||||||
procrva.c: ansicon.h
|
procrva.c: ansicon.h
|
||||||
|
|
||||||
|
$(DIR)\ansicon.obj:
|
||||||
|
$(CCmsg)$(CC) /c $(CFLAGS) $(SHARE) /Fo$@ $?
|
||||||
|
|
||||||
x64\ANSI32.obj: ANSI.c
|
x64\ANSI32.obj: ANSI.c
|
||||||
$(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?
|
$(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $?
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ DWORD GetProcRVA( LPCTSTR module, LPCSTR func )
|
|||||||
#endif
|
#endif
|
||||||
len = GetSystemDirectory( buf, MAX_PATH );
|
len = GetSystemDirectory( buf, MAX_PATH );
|
||||||
buf[len++] = '\\';
|
buf[len++] = '\\';
|
||||||
wcscpy( buf + len, module );
|
lstrcpy( buf + len, module );
|
||||||
hMod = LoadLibraryEx( buf, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE );
|
hMod = LoadLibraryEx( buf, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE );
|
||||||
if (hMod == NULL)
|
if (hMod == NULL)
|
||||||
{
|
{
|
||||||
|
30
proctype.c
30
proctype.c
@ -46,6 +46,22 @@ int ProcessType( LPPROCESS_INFORMATION ppi, PBYTE* pBase, BOOL* gui )
|
|||||||
MEMORY_BASIC_INFORMATION minfo;
|
MEMORY_BASIC_INFORMATION minfo;
|
||||||
IMAGE_DOS_HEADER dos_header;
|
IMAGE_DOS_HEADER dos_header;
|
||||||
IMAGE_NT_HEADERS nt_header;
|
IMAGE_NT_HEADERS nt_header;
|
||||||
|
PBYTE dummy_base;
|
||||||
|
BOOL dummy_gui;
|
||||||
|
BOOL skip_log;
|
||||||
|
|
||||||
|
// There's no need to log if we're only getting one value.
|
||||||
|
skip_log = FALSE;
|
||||||
|
if (pBase == NULL)
|
||||||
|
{
|
||||||
|
pBase = &dummy_base;
|
||||||
|
skip_log = TRUE;
|
||||||
|
}
|
||||||
|
if (gui == NULL)
|
||||||
|
{
|
||||||
|
gui = &dummy_gui;
|
||||||
|
skip_log = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
*pBase = NULL;
|
*pBase = NULL;
|
||||||
*gui = FALSE;
|
*gui = FALSE;
|
||||||
@ -62,7 +78,7 @@ int ProcessType( LPPROCESS_INFORMATION ppi, PBYTE* pBase, BOOL* gui )
|
|||||||
&& nt_header.Signature == IMAGE_NT_SIGNATURE
|
&& nt_header.Signature == IMAGE_NT_SIGNATURE
|
||||||
&& !(nt_header.FileHeader.Characteristics & IMAGE_FILE_DLL))
|
&& !(nt_header.FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||||
{
|
{
|
||||||
// Don't load into ansicon.exe, it wants to do that itself.
|
// Don't load into ansicon.exe, it's already imported.
|
||||||
if (nt_header.OptionalHeader.MajorImageVersion == 20033 && // 'AN'
|
if (nt_header.OptionalHeader.MajorImageVersion == 20033 && // 'AN'
|
||||||
nt_header.OptionalHeader.MinorImageVersion == 18771) // 'SI'
|
nt_header.OptionalHeader.MinorImageVersion == 18771) // 'SI'
|
||||||
return -1;
|
return -1;
|
||||||
@ -102,6 +118,7 @@ int ProcessType( LPPROCESS_INFORMATION ppi, PBYTE* pBase, BOOL* gui )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!skip_log)
|
||||||
DEBUGSTR( 1, " 32-bit %s (base = %q)",
|
DEBUGSTR( 1, " 32-bit %s (base = %q)",
|
||||||
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
||||||
return 32;
|
return 32;
|
||||||
@ -109,20 +126,19 @@ int ProcessType( LPPROCESS_INFORMATION ppi, PBYTE* pBase, BOOL* gui )
|
|||||||
if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
if (!skip_log)
|
||||||
DEBUGSTR( 1, " 64-bit %s (base = %p)",
|
DEBUGSTR( 1, " 64-bit %s (base = %p)",
|
||||||
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
||||||
return 64;
|
return 64;
|
||||||
#elif defined(W32ON64)
|
|
||||||
// Console will log due to -P, but GUI may be ignored (if not,
|
|
||||||
// this'll show up twice).
|
|
||||||
if (*gui)
|
|
||||||
DEBUGSTR( 1, " 64-bit GUI (base = %P)", minfo.BaseAddress );
|
|
||||||
return 64;
|
|
||||||
#else
|
#else
|
||||||
DEBUGSTR( 1, " 64-bit %s (base = %P)",
|
DEBUGSTR( 1, " 64-bit %s (base = %P)",
|
||||||
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
(*gui) ? "GUI" : "console", minfo.BaseAddress );
|
||||||
|
#if defined(W32ON64)
|
||||||
|
return 64;
|
||||||
|
#else
|
||||||
DEBUGSTR( 1, " Unsupported (use x64\\ansicon)" );
|
DEBUGSTR( 1, " Unsupported (use x64\\ansicon)" );
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
DEBUGSTR( 1, " Ignoring unsupported machine (0x%X)",
|
DEBUGSTR( 1, " Ignoring unsupported machine (0x%X)",
|
||||||
|
11
readme.txt
11
readme.txt
@ -339,13 +339,16 @@ Version History
|
|||||||
|
|
||||||
Legend: + added, - bug-fixed, * changed.
|
Legend: + added, - bug-fixed, * changed.
|
||||||
|
|
||||||
1.84-wip - 4 May, 2018:
|
1.84-wip - 7 May, 2018:
|
||||||
- close the flush handles on detach;
|
- close the flush handles on detach;
|
||||||
- WriteFile wasn't properly testing if its handle was for a console;
|
- WriteFile wasn't properly testing if its handle was for a console;
|
||||||
- use remote load on Win8+ if the process has no IAT;
|
- use remote load on Win8+ if the process has no IAT;
|
||||||
* remove dependency on USER32, dynamically load WINMM;
|
- fix logging really long command lines;
|
||||||
|
- default to 7 or -7 if ANSICON_DEF could not be parsed;
|
||||||
|
* remove dependency on CRT & USER32, dynamically load WINMM;
|
||||||
* exit process if the primary thread is detached (for processes on Win10
|
* exit process if the primary thread is detached (for processes on Win10
|
||||||
that return, rather than call ExitProcess).
|
that return, rather than call ExitProcess);
|
||||||
|
* ansicon.exe statically loads the DLL.
|
||||||
|
|
||||||
1.83 - 16 February, 2018:
|
1.83 - 16 February, 2018:
|
||||||
- create the flush thread on first use.
|
- create the flush thread on first use.
|
||||||
@ -621,4 +624,4 @@ Distribution
|
|||||||
|
|
||||||
|
|
||||||
========================
|
========================
|
||||||
Jason Hood, 4 May, 2018.
|
Jason Hood, 7 May, 2018.
|
||||||
|
300
util.c
300
util.c
@ -30,12 +30,12 @@ LPTSTR get_program_name( LPTSTR program )
|
|||||||
GetModuleFileName( NULL, prog_path, lenof(prog_path) );
|
GetModuleFileName( NULL, prog_path, lenof(prog_path) );
|
||||||
program = prog_path;
|
program = prog_path;
|
||||||
}
|
}
|
||||||
name = wcsrchr( program, '\\' );
|
name = ac_wcsrchr( program, '\\' );
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
++name;
|
++name;
|
||||||
else
|
else
|
||||||
name = program;
|
name = program;
|
||||||
ext = wcsrchr( name, '.' );
|
ext = ac_wcsrchr( name, '.' );
|
||||||
if (ext != NULL && ext != name)
|
if (ext != NULL && ext != name)
|
||||||
*ext = '\0';
|
*ext = '\0';
|
||||||
|
|
||||||
@ -107,13 +107,13 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len )
|
|||||||
|
|
||||||
src.a = (LPSTR)str;
|
src.a = (LPSTR)str;
|
||||||
if (len == 0 && str != 0)
|
if (len == 0 && str != 0)
|
||||||
len = (DWORD)(wide ? wcslen( src.w ) : strlen( src.a ));
|
len = (DWORD)(wide ? lstrlen( src.w ) : strlen( src.a ));
|
||||||
|
|
||||||
if (pos + len * 6 + 8 >= buf_len)
|
if (pos + len * 6 + 8 >= buf_len)
|
||||||
{
|
{
|
||||||
LPVOID tmp = HeapReAlloc( hHeap, 0, buf, buf_len + len * 6 + 8 );
|
LPVOID tmp = HeapReAlloc( hHeap, 0, buf, buf_len + len * 6 + 8 );
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return 0;
|
return pos;
|
||||||
buf = tmp;
|
buf = tmp;
|
||||||
buf_len = (DWORD)HeapSize( hHeap, 0, buf );
|
buf_len = (DWORD)HeapSize( hHeap, 0, buf );
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len )
|
|||||||
case '\r': buf[pos++] = 'r'; break;
|
case '\r': buf[pos++] = 'r'; break;
|
||||||
case 27 : buf[pos++] = 'e'; break;
|
case 27 : buf[pos++] = 'e'; break;
|
||||||
default:
|
default:
|
||||||
pos += sprintf( buf + pos, "x%.2X", ch );
|
pos += ac_sprintf( buf + pos, "x%2X", ch );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -214,7 +214,7 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (quote && start_trail)
|
if (quote && start_trail)
|
||||||
pos += sprintf( buf + pos, "\\x%.2X", ch );
|
pos += ac_sprintf( buf + pos, "\\x%2X", ch );
|
||||||
else
|
else
|
||||||
buf[pos++] = ch;
|
buf[pos++] = ch;
|
||||||
}
|
}
|
||||||
@ -223,8 +223,10 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len )
|
|||||||
int mb = WideCharToMultiByte( cp, flags, src.w - 1, 1, buf + pos, 12,
|
int mb = WideCharToMultiByte( cp, flags, src.w - 1, 1, buf + pos, 12,
|
||||||
NULL, pDef );
|
NULL, pDef );
|
||||||
if (def)
|
if (def)
|
||||||
mb = sprintf( buf + pos, ch < 0x100 ? "%cx%.2X" : "%cu%.4X",
|
{
|
||||||
(quote) ? '\\' : '^', ch );
|
buf[pos++] = (quote) ? '\\' : '^';
|
||||||
|
mb = ac_sprintf( buf + pos, ch < 0x100 ? "x%2X" : "u%4X", ch );
|
||||||
|
}
|
||||||
pos += mb;
|
pos += mb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,12 +257,13 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... )
|
|||||||
mutex = CreateMutex( NULL, FALSE, L"ANSICON_debug_file" );
|
mutex = CreateMutex( NULL, FALSE, L"ANSICON_debug_file" );
|
||||||
if (mutex == NULL)
|
if (mutex == NULL)
|
||||||
{
|
{
|
||||||
file = INVALID_HANDLE_VALUE;
|
log_level = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buf = HeapAlloc( hHeap, 0, 2048 );
|
buf = HeapAlloc( hHeap, 0, 2048 );
|
||||||
buf_len = (DWORD)HeapSize( hHeap, 0, buf );
|
buf_len = (DWORD)HeapSize( hHeap, 0, buf );
|
||||||
prefix_len = sprintf( buf, "%S (%lu): ", prog, GetCurrentProcessId() );
|
prefix_len = str_format( 0, TRUE, (DWORD_PTR)prog, 0 );
|
||||||
|
prefix_len += ac_sprintf(buf+prefix_len, " (%u): ", GetCurrentProcessId());
|
||||||
}
|
}
|
||||||
if (WaitForSingleObject( mutex, 500 ) == WAIT_TIMEOUT)
|
if (WaitForSingleObject( mutex, 500 ) == WAIT_TIMEOUT)
|
||||||
return;
|
return;
|
||||||
@ -273,7 +276,6 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... )
|
|||||||
if (file == INVALID_HANDLE_VALUE)
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
ReleaseMutex( mutex );
|
ReleaseMutex( mutex );
|
||||||
CloseHandle( mutex );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,15 +289,15 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... )
|
|||||||
|
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
{
|
{
|
||||||
memset( buf + 2, '=', 72 );
|
RtlFillMemory( buf + 2, 72, '=' );
|
||||||
buf[0] = buf[74] = buf[76] = '\r';
|
buf[0] = buf[74] = buf[76] = '\r';
|
||||||
buf[1] = buf[75] = buf[77] = '\n';
|
buf[1] = buf[75] = buf[77] = '\n';
|
||||||
WriteFile( file, buf, 78, &written, NULL );
|
WriteFile( file, buf, 78, &written, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
GetLocalTime( &now );
|
GetLocalTime( &now );
|
||||||
len = sprintf( buf, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d)"
|
len = ac_sprintf( buf, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d)"
|
||||||
" started %d-%.2d-%.2d %d:%.2d:%.2d\r\n",
|
" started %d-%2d-%2d %d:%2d:%2d\r\n",
|
||||||
log_level,
|
log_level,
|
||||||
now.wYear, now.wMonth, now.wDay,
|
now.wYear, now.wMonth, now.wDay,
|
||||||
now.wHour, now.wMinute, now.wSecond );
|
now.wHour, now.wMinute, now.wSecond );
|
||||||
@ -369,16 +371,16 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... )
|
|||||||
num = va_arg( pArgList, DWORD_PTR );
|
num = va_arg( pArgList, DWORD_PTR );
|
||||||
switch (*szFormat++)
|
switch (*szFormat++)
|
||||||
{
|
{
|
||||||
case 'u': len += sprintf( buf + len, "%u", (DWORD)num ); break;
|
case 'u': len += ac_sprintf( buf + len, "%u", (DWORD)num ); break;
|
||||||
case 'X': len += sprintf( buf + len, "%X", (DWORD)num ); break;
|
case 'X': len += ac_sprintf( buf + len, "%X", (DWORD)num ); break;
|
||||||
case 'p':
|
case 'p':
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
len += sprintf( buf + len, "%.8X_%.8X",
|
len += ac_sprintf( buf + len, "%8X_%8X",
|
||||||
(DWORD)(num >> 32), (DWORD)num );
|
(DWORD)(num >> 32), (DWORD)num );
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'q': len += sprintf( buf + len, "%.8X", (DWORD)num ); break;
|
case 'q': len += ac_sprintf( buf + len, "%8X", (DWORD)num ); break;
|
||||||
case 'P': len += sprintf( buf + len, "00000000_%.8X", (DWORD)num ); break;
|
case 'P': len += ac_sprintf( buf + len, "00000000_%8X", (DWORD)num ); break;
|
||||||
case 's': len = str_format( len, FALSE, num, slen ); break;
|
case 's': len = str_format( len, FALSE, num, slen ); break;
|
||||||
case 'S': len = str_format( len, TRUE, num, slen ); break;
|
case 'S': len = str_format( len, TRUE, num, slen ); break;
|
||||||
default:
|
default:
|
||||||
@ -407,3 +409,263 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... )
|
|||||||
CloseHandle( file );
|
CloseHandle( file );
|
||||||
ReleaseMutex( mutex );
|
ReleaseMutex( mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Provide custom versions of used C runtime functions, to remove dependence on
|
||||||
|
// the runtime library.
|
||||||
|
|
||||||
|
// For my purposes (palette index and colors):
|
||||||
|
// * no leading space;
|
||||||
|
// * base is 10 or 16;
|
||||||
|
// * number doesn't overflow.
|
||||||
|
unsigned long ac_wcstoul( const wchar_t* str, wchar_t** end, int base )
|
||||||
|
{
|
||||||
|
unsigned c, n;
|
||||||
|
unsigned long num = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
n = -1;
|
||||||
|
c = *str;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
n = c - '0';
|
||||||
|
else if (base == 16)
|
||||||
|
{
|
||||||
|
c |= 0x20;
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
n = c - 'a' + 10;
|
||||||
|
}
|
||||||
|
if (n == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
num = num * base + n;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end != NULL)
|
||||||
|
*end = (wchar_t*)str;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes (log level):
|
||||||
|
// * same as ac_wcstoul.
|
||||||
|
int ac_wtoi( const wchar_t* str )
|
||||||
|
{
|
||||||
|
return (int)ac_wcstoul( str, NULL, 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes (default attribute):
|
||||||
|
// * same as ac_wcstoul.
|
||||||
|
long ac_wcstol( const wchar_t* str, wchar_t** end, int base )
|
||||||
|
{
|
||||||
|
int neg = (*str == '-');
|
||||||
|
long num = ac_wcstoul( str + neg, end, base );
|
||||||
|
return neg ? -num : num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes (program separator):
|
||||||
|
// * set is only one or two characters.
|
||||||
|
wchar_t* ac_wcspbrk( const wchar_t* str, const wchar_t* set )
|
||||||
|
{
|
||||||
|
while (*str != '\0')
|
||||||
|
{
|
||||||
|
if (*str == set[0] || *str == set[1])
|
||||||
|
return (wchar_t*)str;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes (path components):
|
||||||
|
// * c is not null.
|
||||||
|
wchar_t* ac_wcsrchr( const wchar_t* str, wchar_t c )
|
||||||
|
{
|
||||||
|
wchar_t* last = NULL;
|
||||||
|
|
||||||
|
while (*str != '\0')
|
||||||
|
{
|
||||||
|
if (*str == c)
|
||||||
|
last = (wchar_t*)str;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes (import module matching):
|
||||||
|
// * A-Z becomes a-z;
|
||||||
|
// * s2 is lower case;
|
||||||
|
// * both strings are at least LEN long;
|
||||||
|
// * returns 0 for match, 1 for no match.
|
||||||
|
int ac_strnicmp( const char* s1, const char* s2, size_t len )
|
||||||
|
{
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
if (*s1 != *s2)
|
||||||
|
{
|
||||||
|
if (*s2 < 'a' || *s2 > 'z' || (*s1 | 0x20) != *s2)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++s1;
|
||||||
|
++s2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char hex[16] = { '0','1','2','3','4','5','6','7',
|
||||||
|
'8','9','A','B','C','D','E','F' };
|
||||||
|
|
||||||
|
// For my purposes:
|
||||||
|
// * BUF is big enough;
|
||||||
|
// * FMT is valid;
|
||||||
|
// * width implies zero fill and the number is not bigger than the width;
|
||||||
|
// * only types d, u & X are supported, all as 32-bit unsigned;
|
||||||
|
// * BUF is NOT NUL-terminated.
|
||||||
|
int ac_sprintf( char* buf, const char* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
DWORD num;
|
||||||
|
int t, width;
|
||||||
|
char* beg = buf;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
t = *fmt++;
|
||||||
|
if (t != '%')
|
||||||
|
*buf++ = t;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = va_arg( args, DWORD );
|
||||||
|
t = *fmt++;
|
||||||
|
width = 0;
|
||||||
|
if (t == '2' || t == '4' || t == '8')
|
||||||
|
{
|
||||||
|
width = t - '0';
|
||||||
|
t = *fmt++;
|
||||||
|
}
|
||||||
|
if (t == 'X')
|
||||||
|
{
|
||||||
|
int bits;
|
||||||
|
if (width == 0)
|
||||||
|
{
|
||||||
|
if (num & 0xF0000000)
|
||||||
|
bits = 32;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bits = 4;
|
||||||
|
while (num >> bits)
|
||||||
|
bits += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bits = width * 4;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bits -= 4;
|
||||||
|
*buf++ = hex[num >> bits & 0xF];
|
||||||
|
} while (bits);
|
||||||
|
}
|
||||||
|
else // (t == 'd' || t == 'u')
|
||||||
|
{
|
||||||
|
if (width == 2)
|
||||||
|
{
|
||||||
|
*buf++ = (int)(num / 10) + '0';
|
||||||
|
*buf++ = (int)(num % 10) + '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned power;
|
||||||
|
if (num >= 1000000000)
|
||||||
|
power = 1000000000;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
power = 1;
|
||||||
|
while (num / (power * 10))
|
||||||
|
power *= 10;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*buf++ = (unsigned)(num / power) % 10 + '0';
|
||||||
|
power /= 10;
|
||||||
|
} while (power);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)(buf - beg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For my purposes:
|
||||||
|
// * BUF is big enough;
|
||||||
|
// * FMT is valid;
|
||||||
|
// * width is only for X, is only 2 and the number is not bigger than that;
|
||||||
|
// * X, d & u are 32-bit unsigned decimal, a digit less than maximum;
|
||||||
|
// * c is not output if NUL;
|
||||||
|
// * no other type is used;
|
||||||
|
// * return value is not used.
|
||||||
|
int ac_wprintf( wchar_t* buf, const char* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
DWORD num;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
t = *fmt++;
|
||||||
|
if (t != '%')
|
||||||
|
*buf++ = t;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = va_arg( args, DWORD );
|
||||||
|
t = *fmt++;
|
||||||
|
if (t == '2')
|
||||||
|
{
|
||||||
|
++fmt;
|
||||||
|
*buf++ = hex[num >> 4];
|
||||||
|
*buf++ = hex[num & 0xF];
|
||||||
|
}
|
||||||
|
else if (t == 'X')
|
||||||
|
{
|
||||||
|
int bits = 4;
|
||||||
|
while (num >> bits)
|
||||||
|
bits += 4;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bits -= 4;
|
||||||
|
*buf++ = hex[num >> bits & 0xF];
|
||||||
|
} while (bits);
|
||||||
|
}
|
||||||
|
else if (t == 'c')
|
||||||
|
{
|
||||||
|
if (num)
|
||||||
|
*buf++ = (wchar_t)num;
|
||||||
|
}
|
||||||
|
else // (t == 'd' || t == 'u')
|
||||||
|
{
|
||||||
|
int power = 10;
|
||||||
|
while (num / power)
|
||||||
|
power *= 10;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
power /= 10;
|
||||||
|
*buf++ = (int)(num / power) % 10 + '0';
|
||||||
|
} while (power != 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user