From be7672b92e7f97c0e55c91cfc9aacfb51a3274e5 Mon Sep 17 00:00:00 2001
From: Jason Hood <jadoxa@yahoo.com.au>
Date: Thu, 16 Dec 2010 16:00:56 +1000
Subject: [PATCH] Close the handles opened by CreateProcess. Prevent the block
 when directly running a GUI process. File logging improvements (on by
 default, this time).

---
 ANSI.c     | 63 +++++++++++++++++++++++++++++-------------------------
 ansicon.c  | 20 ++++++++++++-----
 ansicon.h  |  8 +++----
 debugstr.c | 13 ++++++++++-
 injdll32.c |  4 ++--
 makefile   | 11 ++--------
 proctype.c | 13 ++++++++---
 readme.txt |  4 ++--
 8 files changed, 81 insertions(+), 55 deletions(-)

diff --git a/ANSI.c b/ANSI.c
index 09cf13f..338b739 100644
--- a/ANSI.c
+++ b/ANSI.c
@@ -57,10 +57,11 @@
   v1.31, 13 & 19 November, 2010:
     fix multibyte conversion problems.
 
-  v1.32, 4 & 12 December, 2010:
+  v1.32, 4, 12 & 16 December, 2010:
     test for lpNumberOfCharsWritten/lpNumberOfBytesWritten being NULL;
     recognise DSR and xterm window title;
-    ignore sequences starting with \e[? & \e[>.
+    ignore sequences starting with \e[? & \e[>;
+    close the handles opened by CreateProcess.
 */
 
 #include "ansicon.h"
@@ -347,10 +348,8 @@ BOOL HookAPIAllMod( PHookFn Hooks, BOOL restore )
 
 // ========== Print Buffer functions
 
-#define BUFFER_SIZE 256
-
-int   nCharInBuffer = 0;
-TCHAR ChBuffer[BUFFER_SIZE];
+int	nCharInBuffer;
+LPCTSTR ChBuffer;
 
 //-----------------------------------------------------------------------------
 //   FlushBuffer()
@@ -366,18 +365,14 @@ void FlushBuffer( void )
 }
 
 //-----------------------------------------------------------------------------
-//   PushBuffer( char c )
-// Adds a character in the buffer and flushes the buffer if it is full.
+//   PushBuffer( LPCTSTR s )
+// Adds a character in the "buffer".
 //-----------------------------------------------------------------------------
 
-void PushBuffer( TCHAR c )
+void PushBuffer( LPCTSTR s )
 {
-  ChBuffer[nCharInBuffer++] = c;
-  if (nCharInBuffer >= BUFFER_SIZE)
-  {
-    FlushBuffer();
-    DEBUGSTR( L"flush" );
-  }
+  if (nCharInBuffer++ == 0)
+    ChBuffer = s;
 }
 
 //-----------------------------------------------------------------------------
@@ -798,20 +793,20 @@ ParseAndPrintString( HANDLE hDev,
 		     LPDWORD lpNumberOfBytesWritten
 		     )
 {
-  DWORD  i;
-  LPTSTR s;
+  DWORD   i;
+  LPCTSTR s;
 
   if (hDev != hConOut)	// reinit if device has changed
   {
     hConOut = hDev;
     state = 1;
   }
-  for (i = nNumberOfBytesToWrite, s = (LPTSTR)lpBuffer; i > 0; i--, s++)
+  for (i = nNumberOfBytesToWrite, s = (LPCTSTR)lpBuffer; i > 0; i--, s++)
   {
     if (state == 1)
     {
       if (*s == ESC) state = 2;
-      else PushBuffer( *s );
+      else PushBuffer( s );
     }
     else if (state == 2)
     {
@@ -929,11 +924,18 @@ void Inject( LPPROCESS_INFORMATION pinfo, LPPROCESS_INFORMATION lpi,
 #endif
   }
 
-  if (lpi)
-    memcpy( lpi, pinfo, sizeof(PROCESS_INFORMATION) );
-
   if (!(dwCreationFlags & CREATE_SUSPENDED))
     ResumeThread( pinfo->hThread );
+
+  if (lpi)
+  {
+    memcpy( lpi, pinfo, sizeof(PROCESS_INFORMATION) );
+  }
+  else
+  {
+    CloseHandle( pinfo->hProcess );
+    CloseHandle( pinfo->hThread );
+  }
 }
 
 
@@ -1288,10 +1290,6 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
 
   if (dwReason == DLL_PROCESS_ATTACH)
   {
-#if (MYDEBUG > 1)
-    DEBUGSTR( NULL );	// create a new file
-#endif
-
     hDllInstance = hInstance; // save Dll instance handle
     DEBUGSTR( L"hDllInstance = %p", hDllInstance );
 
@@ -1309,10 +1307,17 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
     OriginalAttr();
     DisableThreadLibraryCalls( hInstance );
   }
-  else if (dwReason == DLL_PROCESS_DETACH && lpReserved == NULL)
+  else if (dwReason == DLL_PROCESS_DETACH)
   {
-    DEBUGSTR( L"Unloading" );
-    HookAPIAllMod( Hooks, TRUE );
+    if (lpReserved == NULL)
+    {
+      DEBUGSTR( L"Unloading" );
+      HookAPIAllMod( Hooks, TRUE );
+    }
+    else
+    {
+      DEBUGSTR( L"Terminating" );
+    }
   }
 
   return( bResult );
diff --git a/ansicon.c b/ansicon.c
index c64d5a6..1fe37e4 100644
--- a/ansicon.c
+++ b/ansicon.c
@@ -43,13 +43,14 @@
     VC compatibility (2008 Express for 32-bit, PSDK 2003 R2 for 64-bit);
     explicitly use wide characters (stick with TCHAR, but not <tchar.h>).
 
-  v1.32, 4 & 12 December, 2010:
+  v1.32, 4, 12 & 16 December, 2010:
     make -p more robust;
-    inject into GUI processes again.
+    inject into GUI processes again;
+    don't block when directly running a GUI process.
 */
 
 #define PVERS L"1.32"
-#define PDATE L"12 December, 2010"
+#define PDATE L"16 December, 2010"
 
 #include "ansicon.h"
 #include <shellapi.h>
@@ -169,6 +170,10 @@ int main( void )
     }
   }
 
+#if (MYDEBUG > 1)
+  DEBUGSTR( NULL ); // create a new file
+#endif
+
   option = (argc > 1 && argv[1][0] == '-');
   if (option && (towlower( argv[1][1] ) == 'i' ||
 		 towlower( argv[1][1] ) == 'u'))
@@ -289,8 +294,13 @@ int main( void )
 	si.cb = sizeof(si);
 	if (CreateProcess( NULL, cmd, NULL,NULL, TRUE, 0, NULL,NULL, &si, &pi ))
 	{
-	  SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
-	  WaitForSingleObject( pi.hProcess, INFINITE );
+	  if (ProcessType( &pi ) > 0)
+	  {
+	    SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
+	    WaitForSingleObject( pi.hProcess, INFINITE );
+	  }
+	  CloseHandle( pi.hProcess );
+	  CloseHandle( pi.hThread );
 	}
 	else
 	{
diff --git a/ansicon.h b/ansicon.h
index 6684db8..2d04920 100644
--- a/ansicon.h
+++ b/ansicon.h
@@ -20,17 +20,17 @@
 #define lenof(array) (sizeof(array)/sizeof(*(array)))
 
 
-BOOL ProcessType( LPPROCESS_INFORMATION );
+int  ProcessType( LPPROCESS_INFORMATION );
 void InjectDLL32( LPPROCESS_INFORMATION, LPCTSTR );
 void InjectDLL64( LPPROCESS_INFORMATION, LPCTSTR );
 
 
 // ========== Auxiliary debug function
 
-//#define MYDEBUG 1	// use OutputDebugString
-//#define MYDEBUG 2	// use %temp%\ansicon.log
 #ifndef MYDEBUG
-#  define MYDEBUG 0	// no debugging
+#  define MYDEBUG 2	// 0 - no debugging
+			// 1 - use OutputDebugString
+			// 2 - use %temp%\ansicon.log
 #endif
 
 #if (MYDEBUG > 0)
diff --git a/debugstr.c b/debugstr.c
index e6c7b01..3eff9a8 100644
--- a/debugstr.c
+++ b/debugstr.c
@@ -75,7 +75,18 @@ void DEBUGSTR( LPTSTR szFormat, ... ) // sort of OutputDebugStringf
   FILE* file = fopen( tempfile, "at" ); // _fmode might be binary
   if (file != NULL)
   {
-    fwprintf( file, L"%s\n", szFormat );
+    TCHAR  path[MAX_PATH];
+    LPTSTR prog, ext;
+    GetModuleFileName( NULL, path, lenof(path) );
+    prog = wcsrchr( path, '\\' );
+    if (prog != NULL)
+      ++prog;
+    else
+      prog = path;
+    ext = wcsrchr( prog, '.' );
+    if (ext != NULL)
+      *ext = '\0';
+    fwprintf( file, L"%s: %s\n", prog, szFormat );
     fclose( file );
   }
   }
diff --git a/injdll32.c b/injdll32.c
index d2f7df1..7f7888d 100644
--- a/injdll32.c
+++ b/injdll32.c
@@ -66,7 +66,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
     // Assume if one is defined, so is the other.
     if (Wow64GetThreadContext == 0)
     {
-      DEBUGSTR( "Failed to get pointer to Wow64GetThreadContext.\n" );
+      DEBUGSTR( L"Failed to get pointer to Wow64GetThreadContext.\n" );
       return;
     }
 #endif
@@ -82,7 +82,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
     if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
 			&si, &pi ))
     {
-      DEBUGSTR( "Failed to execute \"%s\".\n", (LPCTSTR)code );
+      DEBUGSTR( L"Failed to execute \"%s\".\n", (LPCTSTR)code );
       return;
     }
     WaitForSingleObject( pi.hProcess, INFINITE );
diff --git a/makefile b/makefile
index 4a95ba9..b0999da 100644
--- a/makefile
+++ b/makefile
@@ -14,13 +14,13 @@ CFLAGS = -O2 -Wall
 X86OBJS = x86/proctype.o x86/injdll32.o x86/debugstr.o
 X64OBJS = x64/proctype.o x64/injdll64.o x64/injdll32.o x64/debugstr.o
 
-x86/%.o: %.c
+x86/%.o: %.c ansicon.h
 	$(CC) -m32 -c $(CFLAGS) $(CPPFLAGS) $< -o $@
 
 x86/%v.o: %.rc
 	windres -U _WIN64 -F pe-i386 $< $@
 
-x64/%.o: %.c
+x64/%.o: %.c ansicon.h
 	$(CC) -m64 -c $(CFLAGS) $(CPPFLAGS) $< -o $@
 
 x64/%v.o: %.rc
@@ -61,13 +61,6 @@ x86/ansiv.o:	ansi.rc
 x64/ansiconv.o: ansicon.rc
 x64/ansiv.o:	ansi.rc
 
-ansicon.c:  ansicon.h
-ANSI.c:     ansicon.h
-debugstr.c: ansicon.h
-injdll32.c: ansicon.h
-injdll64.c: ansicon.h
-proctype.c: ansicon.h
-
 clean:
 	-rm x86/*.o
 	-rm x64/*.o
diff --git a/proctype.c b/proctype.c
index 346f2f2..133d3f4 100644
--- a/proctype.c
+++ b/proctype.c
@@ -26,14 +26,21 @@ int ProcessType( LPPROCESS_INFORMATION pinfo )
 	{
 	  if (nt_header.Signature == IMAGE_NT_SIGNATURE)
 	  {
+	    BOOL gui = (nt_header.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
 	    if (nt_header.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI ||
-		nt_header.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
+		gui )
 	    {
 	      if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
-		return 32;
+	      {
+		DEBUGSTR( L"  32-bit %s", (gui) ? L"GUI" : L"console" );
+		return (gui) ? -32 : 32;
+	      }
 #ifdef _WIN64
 	      if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
-		return 64;
+	      {
+		DEBUGSTR( L"  64-bit %s", (gui) ? L"GUI" : L"console" );
+		return (gui) ? -64 : 64;
+	      }
 #endif
 	      DEBUGSTR( L"  Ignoring unsupported machine (0x%X)",
 			nt_header.FileHeader.Machine );
diff --git a/readme.txt b/readme.txt
index a490d6d..fc39541 100644
--- a/readme.txt
+++ b/readme.txt
@@ -147,7 +147,7 @@
 
     Legend: + added, - bug-fixed, * changed.
 
-    1.32 - 12 December, 2010:
+    1.32 - 16 December, 2010:
     - fixed crash due to NULL lpNumberOfBytesWritten/lpNumberOfCharsWritten;
     - -p will test the parent process for validity;
     * hook into GUI processes;
@@ -273,4 +273,4 @@
 
 
     ==============================
-    Jason Hood, 12 December, 2010.
+    Jason Hood, 16 December, 2010.