diff --git a/ANSI.c b/ANSI.c index 5c7a0c6..18f66c8 100644 --- a/ANSI.c +++ b/ANSI.c @@ -197,17 +197,24 @@ v1.83, 16 February, 2018: create the flush thread on first use. - v1.84-wip, 17 February, 2018: - close the flush handles on detach. + v1.84-wip, 17 February, 26 to 30 April, 2018: + close the flush handles on detach; + dynamically load WINMM.DLL; + use sprintf/_snprintf/_snwprintf instead of wsprintf, avoiding USER32.DLL; + replace bsearch (in procrva.c) with specific code. */ #include "ansicon.h" #include "version.h" -#include +#include #ifndef SND_SENTRY #define SND_SENTRY 0x80000 #endif +#undef PlaySound +typedef BOOL (WINAPI *FnPlaySound)( LPCWSTR, HMODULE, DWORD ); +FnPlaySound PlaySound; +HMODULE winmm; #define is_digit(c) ('0' <= (c) && (c) <= '9') @@ -483,7 +490,7 @@ void get_state( void ) valid_state = TRUE; - wsprintf( buf, L"ANSICON_State_%X", PtrToUint( hwnd ) ); + _snwprintf( buf, lenof(buf), L"ANSICON_State_%X", PtrToUint( hwnd ) ); hMap = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(STATE), buf ); init = (GetLastError() != ERROR_ALREADY_EXISTS); @@ -552,7 +559,7 @@ void get_state( void ) *a++ = '-'; ATTR = ((ATTR >> 4) & 15) | ((ATTR & 15) << 4); } - wsprintf( a, L"%X", ATTR & 255 ); + _snwprintf( a, 3, L"%X", ATTR & 255 ); SetEnvironmentVariable( L"ANSICON_DEF", def ); } set_ansicon( &Info ); @@ -1018,9 +1025,9 @@ void send_palette_sequence( COLORREF c ) g = GetGValue( c ); b = GetBValue( c ); if ((c & 0x0F0F0F) == ((c >> 4) & 0x0F0F0F)) - wsprintf( buf, L"#%X%X%X", r & 0xF, g & 0xF, b & 0xF ); + _snwprintf( buf, lenof(buf), L"#%X%X%X", r & 0xF, g & 0xF, b & 0xF ); else - wsprintf( buf, L"#%02X%02X%02X", r, g, b ); + _snwprintf( buf, lenof(buf), L"#%02X%02X%02X", r, g, b ); SendSequence( buf ); } @@ -1765,9 +1772,9 @@ void InterpretEscSeq( void ) case 6: // ESC[6n Report cursor position { TCHAR buf[32]; - wsprintf( buf, L"\33[%d;%d%sR", - CUR.Y - top + 1, CUR.X + 1, - (suffix2 == '+') ? L"+" : L"" ); + _snwprintf( buf, lenof(buf), L"\33[%d;%d%sR", + CUR.Y - top + 1, CUR.X + 1, + (suffix2 == '+') ? L"+" : L"" ); SendSequence( buf ); } return; @@ -2236,7 +2243,17 @@ ParseAndPrintString( HANDLE hDev, else if (pState->crm) PushBuffer( (WCHAR)c ); else if (c == BEL) { - if (hBell == NULL) + if (PlaySound == NULL) + { + winmm = LoadLibraryEx( L"winmm.dll", NULL, 0 ); + if (winmm != NULL) + PlaySound = (FnPlaySound)GetProcAddress( winmm, "PlaySoundW" ); + if (PlaySound == NULL) + PlaySound = INVALID_HANDLE_VALUE; + } + if (PlaySound == INVALID_HANDLE_VALUE) + PushBuffer( (WCHAR)c ); + else if (hBell == NULL) hBell = CreateThread( NULL, 4096, BellThread, NULL, 0, NULL ); } else if (c == SO) shifted = TRUE; @@ -2975,7 +2992,7 @@ void Inject( DWORD dwCreationFlags, LPPROCESS_INFORMATION lpi, STARTUPINFO si; PROCESS_INFORMATION pi; wcscpy( DllNameType, L"CON.exe" ); - wsprintf( args, L"ansicon -P%ld", child_pi->dwProcessId ); + _snwprintf( args, lenof(args), L"ansicon -P%lu", child_pi->dwProcessId ); ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); if (CreateProcess( DllName, args, NULL, NULL, FALSE, 0, NULL, NULL, @@ -3689,10 +3706,10 @@ void set_ansicon( PCONSOLE_SCREEN_BUFFER_INFO pcsbi ) pcsbi = &csbi; } - wsprintf( buf, L"%dx%d (%dx%d)", - pcsbi->dwSize.X, pcsbi->dwSize.Y, - pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1, - pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 ); + _snwprintf( buf, lenof(buf), L"%dx%d (%dx%d)", + pcsbi->dwSize.X, pcsbi->dwSize.Y, + pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1, + pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1 ); SetEnvironmentVariable( L"ANSICON", buf ); } @@ -3920,6 +3937,8 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) { DEBUGSTR( 1, "Unloading" ); HookAPIAllMod( Hooks, TRUE, FALSE ); + if (winmm != NULL) + FreeLibrary( winmm ); } else { diff --git a/ansicon.c b/ansicon.c index 8511d9f..4ea679c 100644 --- a/ansicon.c +++ b/ansicon.c @@ -91,7 +91,7 @@ use -pu to unload from the parent. */ -#define PDATE L"17 February, 2018" +#define PDATE L"30 April, 2018" #include "ansicon.h" #include "version.h" @@ -199,7 +199,8 @@ BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app ) len = (DWORD)(prog - prog_path); memcpy( DllName, prog_path, TSIZE(len) ); #ifdef _WIN64 - wsprintf( DllName + len, L"ANSI%d.dll", (type == 48) ? 64 : type ); + _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) @@ -269,7 +270,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app, BOOL unload ) memcpy( DllName, prog_path, TSIZE(len) ); #ifdef _WIN64 type = (IsWow64Process( ppi->hProcess, &WOW64 ) && WOW64) ? 32 : 64; - wsprintf( DllName + len, L"ANSI%d.dll", type ); + _snwprintf( DllName + len, MAX_PATH-1 - len, L"ANSI%d.dll", type ); #endif me.dwSize = sizeof(MODULEENTRY32); for (fOk = Module32First( hSnap, &me ); fOk; fOk = Module32Next( hSnap, &me )) diff --git a/makefile.vc b/makefile.vc index dbd3f40..1e0b09a 100644 --- a/makefile.vc +++ b/makefile.vc @@ -60,13 +60,14 @@ SHARE = /MD MT = mt.exe CFLAGS = /nologo /W3 /O2 $(SHARE) /D_CRT_SECURE_NO_WARNINGS -LIBS = advapi32.lib user32.lib winmm.lib $(LIBS64) +LIBS = advapi32.lib $(LIBS64) # Identify ansicon.exe using "ANSI" as a version number. LINK = /link /version:20033.18771 X86OBJS = x86\injdll.obj x86\proctype.obj x86\util.obj X64OBJS = x64\injdll.obj x64\proctype.obj x64\util.obj x64\procrva.obj +X6432OBJS = x86\injdll.obj x64\proctype32.obj x86\util.obj !IF !DEFINED(V) V = 0 @@ -118,7 +119,7 @@ x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link \ /base:0xAC000000 -x64\ANSI32.dll: x64\ANSI32.obj x64\proctype32.obj x86\injdll.obj x86\util.obj x86\ansi.res +x64\ANSI32.dll: x64\ANSI32.obj $(X6432OBJS) x86\ansi.res $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link \ /base:0xAC0000 /filealign:512 /largeaddressaware !IF "$(_NMAKE_VER)" == "9.00.30729.01" diff --git a/procrva.c b/procrva.c index 3204bcc..fa73917 100644 --- a/procrva.c +++ b/procrva.c @@ -9,12 +9,6 @@ static PIMAGE_DOS_HEADER pDosHeader; -static int export_cmp( const void* a, const void* b ) -{ - return strcmp( (LPCSTR)a, MakeVA( LPCSTR, *(const PDWORD)b ) ); -} - - #ifdef _WIN64 DWORD GetProcRVA( LPCTSTR module, LPCSTR func, int bits ) #else @@ -28,8 +22,8 @@ DWORD GetProcRVA( LPCTSTR module, LPCSTR func ) PIMAGE_EXPORT_DIRECTORY pExportDir; PDWORD fun_table, name_table; PWORD ord_table; - PDWORD pFunc; DWORD rva; + int lo, mid, hi, cmp; #ifdef _WIN64 if (bits == 32) @@ -65,20 +59,30 @@ DWORD GetProcRVA( LPCTSTR module, LPCSTR func ) name_table = MakeVA( PDWORD, pExportDir->AddressOfNames ); ord_table = MakeVA( PWORD, pExportDir->AddressOfNameOrdinals ); - pFunc = bsearch( func, name_table, pExportDir->NumberOfNames, - sizeof(DWORD), export_cmp ); - if (pFunc == NULL) + rva = 0; + lo = 0; + hi = pExportDir->NumberOfNames - 1; + while (lo <= hi) + { + mid = (lo + hi) / 2; + cmp = strcmp( func, MakeVA( LPCSTR, name_table[mid] ) ); + if (cmp == 0) + { + rva = fun_table[ord_table[mid]]; + break; + } + if (cmp < 0) + hi = mid - 1; + else + lo = mid + 1; + } + if (rva == 0) { #ifdef _WIN64 DEBUGSTR( 1, "Could not find %u-bit %s!", bits, func ); #else DEBUGSTR( 1, "Could not find %s!", func ); #endif - rva = 0; - } - else - { - rva = fun_table[ord_table[pFunc - name_table]]; } FreeLibrary( hMod ); return rva; diff --git a/readme.txt b/readme.txt index a2a5e04..af536d8 100644 --- a/readme.txt +++ b/readme.txt @@ -339,8 +339,9 @@ Version History Legend: + added, - bug-fixed, * changed. - 1.84-wip - 17 February, 2018: - - close the flush handles on detach. + 1.84-wip - 30 April, 2018: + - close the flush handles on detach; + * remove dependency on USER32, dynamically load WINMM. 1.83 - 16 February, 2018: - create the flush thread on first use. @@ -615,5 +616,5 @@ Distribution in LICENSE.txt. -============================== -Jason Hood, 17 February, 2018. +=========================== +Jason Hood, 30 April, 2018. diff --git a/util.c b/util.c index 9d4ed8b..069d471 100644 --- a/util.c +++ b/util.c @@ -107,14 +107,20 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len ) if (len == 0) { if (str == 0) - pos += wsprintfA( buf + pos, "" ); + { + memcpy( buf + pos, "", 6 ); + pos += 6; + } else if (quote) { buf[pos++] = '"'; buf[pos++] = '"'; } else if (alt) - pos += wsprintfA( buf + pos, "" ); + { + memcpy( buf + pos, "", 7 ); + pos += 7; + } return pos; } @@ -165,7 +171,7 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len ) case '\r': buf[pos++] = 'r'; break; case 27 : buf[pos++] = 'e'; break; default: - pos += wsprintfA( buf + pos, "x%.2X", ch ); + pos += sprintf( buf + pos, "x%.2X", ch ); } } else @@ -194,7 +200,7 @@ static DWORD str_format( DWORD pos, BOOL wide, DWORD_PTR str, DWORD len ) } } if (quote && start_trail) - pos += wsprintfA( buf + pos, "\\x%.2X", ch ); + pos += sprintf( buf + pos, "\\x%.2X", ch ); else buf[pos++] = ch; } @@ -203,8 +209,8 @@ 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, NULL, pDef ); if (def) - mb = wsprintfA( buf + pos, ch < 0x100 ? "%cx%.2X" : "%cu%.4X", - (quote) ? '\\' : '^', ch ); + mb = sprintf( buf + pos, ch < 0x100 ? "%cx%.2X" : "%cu%.4X", + (quote) ? '\\' : '^', ch ); pos += mb; } } @@ -240,7 +246,7 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... ) } buf = HeapAlloc( hHeap, 0, 2048 ); buf_len = (DWORD)HeapSize( hHeap, 0, buf ); - prefix_len = wsprintfA( buf, "%S (%lu): ", prog, GetCurrentProcessId() ); + prefix_len = sprintf( buf, "%S (%lu): ", prog, GetCurrentProcessId() ); } if (WaitForSingleObject( mutex, 500 ) == WAIT_TIMEOUT) return; @@ -274,11 +280,11 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... ) } GetLocalTime( &now ); - len = wsprintfA( buf, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d)" - " started %d-%.2d-%.2d %d:%.2d:%.2d\r\n", - log_level, - now.wYear, now.wMonth, now.wDay, - now.wHour, now.wMinute, now.wSecond ); + len = sprintf( buf, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d)" + " started %d-%.2d-%.2d %d:%.2d:%.2d\r\n", + log_level, + now.wYear, now.wMonth, now.wDay, + now.wHour, now.wMinute, now.wSecond ); WriteFile( file, buf, len, &written, NULL ); if (szFormat == NULL) { @@ -349,16 +355,16 @@ void DEBUGSTR( int level, LPCSTR szFormat, ... ) num = va_arg( pArgList, DWORD_PTR ); switch (*szFormat++) { - case 'u': len += wsprintfA( buf + len, "%u", (DWORD)num ); break; - case 'X': len += wsprintfA( buf + len, "%X", (DWORD)num ); break; + case 'u': len += sprintf( buf + len, "%u", (DWORD)num ); break; + case 'X': len += sprintf( buf + len, "%X", (DWORD)num ); break; case 'p': #ifdef _WIN64 - len += wsprintfA( buf + len, "%.8X_%.8X", - (DWORD)(num >> 32), (DWORD)num ); + len += sprintf( buf + len, "%.8X_%.8X", + (DWORD)(num >> 32), (DWORD)num ); break; #endif - case 'q': len += wsprintfA( buf + len, "%.8X", (DWORD)num ); break; - case 'P': len += wsprintfA( buf + len, "00000000_%.8X", (DWORD)num ); break; + case 'q': len += sprintf( buf + len, "%.8X", (DWORD)num ); break; + case 'P': len += sprintf( buf + len, "00000000_%.8X", (DWORD)num ); break; case 's': len = str_format( len, FALSE, num, slen ); break; case 'S': len = str_format( len, TRUE, num, slen ); break; default: